diff --git a/apps/client/src/VideoField.ts b/apps/client/src/VideoField.ts new file mode 100644 index 0000000000000000000000000000000000000000..044deae70855c32c8e43164b1e274820f11b669e --- /dev/null +++ b/apps/client/src/VideoField.ts @@ -0,0 +1,24 @@ +import { + RegisterClientFormFieldOptions, + RegisterClientVideoFieldOptions, +} from '@larriereguichet/peertube-types/shared/models/plugins/client/register-client-form-field.model'; + +export type VideoFieldOptionTypes = RegisterClientVideoFieldOptions['type'][]; + +export const DEFAULT_OPTION_TYPES: VideoFieldOptionTypes = [ + 'upload', + 'import-url', + 'import-torrent', + 'update', + 'go-live', +]; + +export class VideoField { + public options: RegisterClientFormFieldOptions; + public types: VideoFieldOptionTypes; + + constructor(options: RegisterClientFormFieldOptions, types: VideoFieldOptionTypes = DEFAULT_OPTION_TYPES) { + this.options = options; + this.types = types; + } +} diff --git a/apps/client/src/VideoFieldManager.ts b/apps/client/src/VideoFieldManager.ts new file mode 100644 index 0000000000000000000000000000000000000000..460ce387748f16307b355c5a1f42924a4596b31b --- /dev/null +++ b/apps/client/src/VideoFieldManager.ts @@ -0,0 +1,70 @@ +import { + RegisterClientHelpers, + RegisterClientOptions, +} from '@larriereguichet/peertube-types/client/types/register-client-option.model'; +import { RegisterClientFormFieldOptions } from '@larriereguichet/peertube-types/shared/models/plugins/client/register-client-form-field.model'; +import { DEFAULT_OPTION_TYPES, VideoField, VideoFieldOptionTypes } from './VideoField'; + +export class VideoFieldManager { + private registerVideoField: RegisterClientOptions['registerVideoField']; + private translate: (toTranslate?: string) => Promise; + + constructor( + registerVideoField: RegisterClientOptions['registerVideoField'], + translate: RegisterClientHelpers['translate'] + ) { + this.registerVideoField = registerVideoField; + this.translate = (toTranslate?: string) => (toTranslate ? translate(toTranslate) : Promise.resolve(undefined)); + } + + async create(options: RegisterClientFormFieldOptions, types: VideoFieldOptionTypes = DEFAULT_OPTION_TYPES) { + return new VideoField( + { + ...options, + label: await this.translate(options.label), + descriptionHTML: await this.translate(options.descriptionHTML), + }, + types + ); + } + + register(videoField: VideoField) { + for (const type of videoField.types) { + this.registerVideoField(videoField.options, { type }); + } + } + + async createAndRegister( + options: RegisterClientFormFieldOptions, + types: VideoFieldOptionTypes = DEFAULT_OPTION_TYPES + ) { + const videoField = await this.create(options, types); + this.register(videoField); + + return videoField; + } + + async createAndRegisterCaptionForLanguage(language: string, types: VideoFieldOptionTypes = DEFAULT_OPTION_TYPES) { + return await this.createAndRegister( + { + name: `captions[${language}]`, + label: `${language} caption`, + descriptionHTML: 'You may edit the video caption here.', + // type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced' | 'select' | 'html' + // /!\ 'input-checkbox' could send "false" and "true" strings instead of boolean + type: 'input-textarea', + default: '', + // Optional, to hide a field depending on the current form state + // liveVideo is in the options object when the user is creating/updating a live + // videoToUpdate is in the options object when the user is updating a video + hidden: ({ formValues, videoToUpdate, liveVideo }) => { + console.log('formValues', formValues); + console.log('videoToUpdate', videoToUpdate); + console.log('liveVideo', liveVideo); + return formValues.pluginData['other-field'] === 'toto'; + }, + }, + types + ); + } +} diff --git a/apps/client/src/index.ts b/apps/client/src/index.ts index 30c98d469891cd364389f4ae6ec21fa123158c7e..a1af36bde32146f64638a7af904fe7aca95b71ac 100644 --- a/apps/client/src/index.ts +++ b/apps/client/src/index.ts @@ -1,7 +1,7 @@ import { RegisterClientOptions } from '@larriereguichet/peertube-types/client/types'; -import { Video } from '@larriereguichet/peertube-types/shared'; +import { VideoFieldManager } from './VideoFieldManager'; -export function register({ registerHook, peertubeHelpers }: RegisterClientOptions) { +async function register({ registerHook, peertubeHelpers, registerVideoField }: RegisterClientOptions) { registerHook({ target: 'action:admin-plugin-settings.init', handler: ({ npmName }: { npmName: string }) => { @@ -22,15 +22,8 @@ export function register({ registerHook, peertubeHelpers }: RegisterClientOption }, }); - registerHook({ - target: 'action:video-watch.video.loaded', - handler: ({ video }: { video: Video }) => { - fetch(`${peertubeHelpers.getBaseRouterRoute()}/videos/${video.uuid}/captions`, { - method: 'PUT', - headers: peertubeHelpers.getAuthHeader(), - }) - .then((res) => res.json()) - .then((data) => console.log('Hi %s.', data)); - }, - }); + const videoFieldManager = new VideoFieldManager(registerVideoField, peertubeHelpers.translate); + await videoFieldManager.createAndRegisterCaptionForLanguage('fr'); } + +export { register }; diff --git a/apps/client/tsconfig.json b/apps/client/tsconfig.json index 5aa55f4e56cf8a94a8827ae7690901eebbf09666..31cc5d7e0ac0746a3c3caa32115521ceeabdcebc 100644 --- a/apps/client/tsconfig.json +++ b/apps/client/tsconfig.json @@ -1,11 +1,12 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "target": "ES6", - "module": "ES6", + "module": "es6", + "moduleResolution": "Node", + "target": "es5", "baseUrl": "src", "rootDir": "src", "outDir": "../../dist/client", "tsBuildInfoFile": "../../dist/client.tsbuildinfo" - }, + } } diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 851e1c1ff36be470ea55870a043f6862f5a5c341..fc5f37b3e74d7e35660d56e3bed25962486aa9df 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,3 +1,4 @@ +require('require.js'); import { resolve } from 'path'; import os from 'os'; import { performance, PerformanceObserver } from 'perf_hooks'; diff --git a/apps/server/tsconfig.json b/apps/server/tsconfig.json index fd2bfcc07d2dcc2f53636e279c86cdb0e7ad6bb2..500454b007f0e00ed6dcd68284d3cc195082b454 100644 --- a/apps/server/tsconfig.json +++ b/apps/server/tsconfig.json @@ -1,21 +1,16 @@ { - "extends": "../../tsconfig.base.json", + "extends": "@tsconfig/node16/tsconfig.json", "compilerOptions": { - "lib": ["es2021"], - "module": "commonjs", - "target": "es2021", - - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, "baseUrl": "src", "rootDir": "./src", "outDir": "../../dist/server", + + "composite": true, "tsBuildInfoFile": "../../dist/server.tsbuildinfo", "typeRoots": [ - "./src/@types", "../../node_modules/@types"] + "./src/@types", "../../node_modules/@types"], +// "skipLibCheck": true }, "exclude": ["node_modules"] } diff --git a/package.json b/package.json index 7b8e063064baacbc51a42f3ef7bb9e32492d8271..d6aa7ecb0931800273258caf077f93aaee0580d6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "semantic-release": "semantic-release", "prettier": "prettier --write 'apps/**/*.ts' commitlint.config.js", "start": "tsc && node index.js", - "build": "webpack", + "build": "tsc --build --verbose && webpack", "clean": "tsc --build --clean", "dev": "webpack --watch --progress", "tsc": "tsc", @@ -90,12 +90,14 @@ "tsconfig-paths-webpack-plugin": "^3.5.1", "typescript": "^4.4.4", "webpack": "^5.61.0", - "webpack-cli": "^4.9.1" + "webpack-cli": "^4.9.1", + "webpack-node-externals": "^3.0.0" }, "dependencies": { "bytes": "^3.1.1", "form-data": "^4.0.0", "fs-extra": "^10.0.0", + "require.js": "^1.0.0", "subtitle": "^4.1.1", "unzipper": "^0.10.11", "vosk": "npm:@larriereguichet/vosk@0.4.4", diff --git a/webpack.config.js b/webpack.config.js index 4a918bf18d0644fb0c752dbaffed894d165624f1..04e3370ec7514d813282c7f89dc4cd7a6db87805 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,35 +3,49 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin'); module.exports = { - entry: "index.ts", - devtool: 'inline-source-map', - mode: 'development', - module: { - "rules": [ - { - "test": /\.tsx?$/, - "exclude": /node_modules/, - "use": { - "loader": "ts-loader", - "options": { - "projectReferences": true, - "logLevel": "info", - } - } - } - ] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js'], - plugins: [ - new TsconfigPathsPlugin(), - ] + experiments: { + outputModule: true, + }, + entry: './apps/client/src/index.ts', + devtool: 'inline-source-map', + mode: 'production', + output: { + path: path.resolve(__dirname, 'dist/client'), + filename: 'index.js', + clean: true, + library: { + // do not specify a `name` here + type: 'module', }, + }, + module: { + rules: [ + { + test: /\.tsx?$/, + include: path.resolve('apps/client/'), + exclude: /node_modules/, + use: { + loader: 'ts-loader', + options: { + configFile: path.resolve('apps/client/tsconfig.json'), + projectReferences: true, + logLevel: 'info', + }, + }, + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], plugins: [ - new CopyPlugin({ - patterns: [ - { from: path.resolve(__dirname, './apps/client/index.css'), to: path.resolve('dist/client/')}, - ], - }), - ] + new TsconfigPathsPlugin({ + configFile: path.resolve('apps/client/tsconfig.json'), + }), + ], + }, + plugins: [ + new CopyPlugin({ + patterns: [{ from: path.resolve(__dirname, './apps/client/index.css'), to: path.resolve('dist/client/') }], + }), + ], }; diff --git a/yarn.lock b/yarn.lock index 1c07612dbdf7346359524244108b98b1c7b23c3a..6db76c436dd26f703e02cc80f37bb5206c80f547 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7866,6 +7866,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/require.js/-/require.js-1.0.0.tgz#71fa3273366af4427b0265a218be5e62ed4f90c8" + integrity sha1-cfoyczZq9EJ7AmWiGL5eYu1PkMg= + resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -9396,6 +9401,11 @@ webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" +webpack-node-externals@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz#1a3407c158d547a9feb4229a9e3385b7b60c9917" + integrity sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ== + webpack-sources@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.2.tgz#d88e3741833efec57c4c789b6010db9977545260"