Skip to content

Commit

Permalink
+
Browse files Browse the repository at this point in the history
  • Loading branch information
joybox committed Mar 1, 2022
1 parent be5a97a commit 173aadc
Show file tree
Hide file tree
Showing 97 changed files with 26,867 additions and 5,018 deletions.
16 changes: 16 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/javascript-node/.devcontainer/base.Dockerfile

# [Choice] Node.js version: 16, 14, 12
ARG VARIANT="16-buster"
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment if you want to install an additional version of node using nvm
# ARG EXTRA_NODE_VERSION=10
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"

# [Optional] Uncomment if you want to install more global node modules
# RUN su node -c "npm install -g <your-package-list-here>"
28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/javascript-node
{
"name": "Node.js",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 12, 14, 16
"args": { "VARIANT": "16" }
},
"forwardPorts": [3000],

// Set *default* container specific settings.json values on container create.
"settings": {},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",

// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
36 changes: 36 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
"semi": ["error", "always"],
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never", "asyncArrow": "always"}],
"operator-linebreak": ["error", "after"],
"indent": "off",
'@typescript-eslint/indent': [
'error',
2
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
"no-empty-function": "off",
"@typescript-eslint/no-empty-function": "off",
"no-useless-constructor": "off",
"no-unused-expressions": "off",
"promise/param-names": "off",
"@typescript-eslint/no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true }],
"prefer-promise-reject-errors": ["error", {"allowEmptyReject": true}],
"@typescript-eslint/no-non-null-assertion": "off"
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ yarn-error.log*
/backend/out/
/src/**/*.js
/src/**/*.js.map
/client
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ COPY plugins ./plugins
COPY types ./types
COPY Shared ./Shared
COPY .browserslistrc tsconfig.json tslint.json vue.config.js ./
COPY .eslintrc.js ./

RUN npm run build-frontend

Expand Down
148 changes: 87 additions & 61 deletions Shared/Types.ts
Original file line number Diff line number Diff line change
@@ -1,121 +1,147 @@
export type Exact<T, D> = T extends D ?
Exclude<keyof T, keyof D> extends never ?
Exclude<keyof T, keyof D> extends never ?
T : never : never;

export interface Plugin {
id: number;
name: string;
enabled: boolean;
id: number;
name: string;
enabled: boolean;
}

export type PluginState = [number, boolean];
export type ReorderPluginInfo = [number, number];
export type ReorderObservablePluginInfo = [string, number, number];
export type ArchiveTagAction = [string, string];
export type UpdateObservableDownload = [string, number];
export type UpdateObservableValidity = [string, boolean];

export interface Stream {
uri: string;
lastSeen: number;
plugins: Plugin[];
uri: string;
lastSeen: number;
download: number;
valid: boolean;
plugins: Plugin[];
}

export interface RecordingProgressId {
label: string;
label: string;
}

export interface RecordingProgressInit extends RecordingProgressId {
streamUrl: string;
streamUrl: string;
}

export interface RecordingProgressUpdate extends RecordingProgressId {
time: number;
bitrate: number;
size: number;
paused: boolean;
time: number;
bitrate: number;
size: number;
paused: boolean;
}

export interface RecordingProgressInfo extends RecordingProgressUpdate, RecordingProgressInit { }

export interface Streamer {
uri: string;
lastSeen: number;
plugins: string[];
uri: string;
lastSeen: number;
download: number;
valid: boolean;
plugins: string[];
}

export interface ArchiveRecord {
title: string;
source: string;
timestamp: number;
duration: number;
size: number;
filename: string;
locked: boolean;
tags: Set<string>;
title: string;
source: string;
timestamp: number;
duration: number;
size: number;
reencoded: boolean;
filename: string;
locked: boolean;
tags: Set<string>;
}

export type SerializedArchiveRecord = Omit<ArchiveRecord, 'tags'> & { tags: string[] };

export type SerializedFileRecord = Omit<FileRecord, 'tags'> & { tags: string[] };
type second = number;

export interface SystemMonitorInfo {
cpu: number;
rss: number;
hdd: number;
export interface PlaylistSegment {
filename: string;
begin: second;
end: second;
loop: number;
}

export interface AppStateSnapshot {
observables: Streamer[];
plugins: Plugin[];
archiveFilters: Filter[];
observablesFilters: Filter[];
archive: SerializedArchiveRecord[];
clipProgress: ClipProgressState[];
activeRecords: RecordingProgressInfo[];
systemResources: SystemMonitorInfo;
startTime: number;
defaultAccess: AppAccessType;
storageQuota: number;
instanceQuota: number;
downloadSpeedQuota: number;
export interface Playlist {
id: number;
title: string;
timestamp: number;
segments: PlaylistSegment[];
}

export interface FileRecord extends ArchiveRecord {
thumbnail: string;
thumbnail: string;
}

export type SerializedArchiveRecord = Omit<ArchiveRecord, 'tags'> & { tags: string[] };

export type SerializedFileRecord = Omit<FileRecord, 'tags'> & { tags: string[] };

export interface SystemMonitorInfo {
cpu: number;
rss: number;
hdd: number;
}

export interface ClipProgressInit {
label: string;
duration: number; // seconds
label: string;
duration: number; // seconds
}

export interface ClipProgress {
label: string;
progress: number;
eta: number;
label: string;
progress: number;
eta: number;
}

export type ClipProgressState = ClipProgressInit & ClipProgress;

export interface LastSeenInfo {
url: string;
lastSeen: number;
url: string;
lastSeen: number;
}

export interface SystemInfo {
cpu: number;
rss: number;
hdd: number;
cpu: number;
rss: number;
hdd: number;
}

export interface LogItem {
timestamp: number;
message: string;
timestamp: number;
message: string;
}

export enum AppAccessType { NO_ACCESS, VIEW_ACCESS, FULL_ACCESS }

export interface Filter {
id: number;
name: string;
query: string;
id: number;
name: string;
query: string;
}

export interface AppStateSnapshot {
observables: Streamer[];
plugins: Plugin[];
archiveFilters: Filter[];
observablesFilters: Filter[];
archive: SerializedArchiveRecord[];
playlists: Playlist[];
clipProgress: ClipProgressState[];
activeRecords: RecordingProgressInfo[];
systemResources: SystemMonitorInfo;
startTime: number;
defaultAccess: AppAccessType;
storageQuota: number;
instanceQuota: number;
downloadSpeedQuota: number;
}

export enum NotificationType { NewRecord, SizeQuota }
56 changes: 41 additions & 15 deletions Shared/Util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,48 @@ export enum SizeToByteMetric { BYTE = 'B', KB = 'k', MB = 'M', GB = 'G', TB = 'T
* @returns Rounded number of bytes or NaN
*/
export function SizeStrToByte(size: string, defaultMetric: SizeToByteMetric = SizeToByteMetric.BYTE): number {
if (typeof size !== 'string') {
return NaN;
if (typeof size !== 'string') {
return NaN;
}

const MetricMult = (m: string): number => {
return Math.pow(1000, [
SizeToByteMetric.BYTE,
SizeToByteMetric.KB,
SizeToByteMetric.MB,
SizeToByteMetric.GB,
SizeToByteMetric.TB].findIndex(x => x === m));
};

return Math.ceil(size.endsWith('bit') ?
Number.parseFloat(size) * MetricMult(size[size.length - 4]) / 8 :
size.endsWith('B') ?
Number.parseFloat(size) * MetricMult(size[size.length - 2]) :
Number.parseFloat(size) * MetricMult(defaultMetric));
}

export function Clamp(x: number, lo: number, hi: number): number {
return Math.min(hi, Math.max(x, lo));
}

export function Merge<T>(comparator: (l: T, r: T) => boolean, ...arrays: T[][]): T[] {
const it: number[] = new Array(arrays.length).fill(0, 0, arrays.length);
let minIdx = 0;
const ret: T[] = [];
while (minIdx !== -1) {
minIdx = arrays.findIndex((x, i) => it[i] < x.length);

for (let n = 0; n < arrays.length; ++n) {
if (it[n] < arrays[n].length && comparator(arrays[n][it[n]], arrays[minIdx][it[minIdx]])) {
minIdx = n;
}
}

const MetricMult = (m: string): number => {
return Math.pow(1000, [
SizeToByteMetric.BYTE,
SizeToByteMetric.KB,
SizeToByteMetric.MB,
SizeToByteMetric.GB,
SizeToByteMetric.TB].findIndex(x => x === m));
};
if (minIdx !== -1) {
ret.push(arrays[minIdx][it[minIdx]]);
++it[minIdx];
}
}

return Math.ceil(size.endsWith('bit') ?
Number.parseFloat(size) * MetricMult(size[size.length - 4]) / 8 :
size.endsWith('B') ?
Number.parseFloat(size) * MetricMult(size[size.length - 2]) :
Number.parseFloat(size) * MetricMult(defaultMetric));
return ret;
}
Loading

0 comments on commit 173aadc

Please sign in to comment.