From 914355c6445027c17e20cbb31504ab6a6de64dd3 Mon Sep 17 00:00:00 2001 From: Kaity A Date: Sun, 30 Apr 2023 11:09:51 +1000 Subject: [PATCH 1/8] Add Libre Translate support --- .../migration/1682777547198-LibreTranslate.js | 23 ++++++++++ packages/backend/src/config/types.ts | 5 +++ packages/backend/src/models/entities/meta.ts | 12 ++++++ .../api/endpoints/admin/accounts/hosted.ts | 11 +++++ .../src/server/api/endpoints/admin/meta.ts | 5 ++- .../server/api/endpoints/admin/update-meta.ts | 18 ++++++++ .../backend/src/server/api/endpoints/meta.ts | 3 +- .../server/api/endpoints/notes/translate.ts | 43 ++++++++++++++++++- packages/client/src/pages/admin/settings.vue | 34 +++++++++++++++ 9 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 packages/backend/migration/1682777547198-LibreTranslate.js diff --git a/packages/backend/migration/1682777547198-LibreTranslate.js b/packages/backend/migration/1682777547198-LibreTranslate.js new file mode 100644 index 0000000000..dbaf483e6c --- /dev/null +++ b/packages/backend/migration/1682777547198-LibreTranslate.js @@ -0,0 +1,23 @@ +export class LibreTranslate1682777547198 { + name = "LibreTranslate1682777547198"; + + async up(queryRunner) { + await queryRunner.query(` + ALTER TABLE "meta" + ADD "libreTranslateApiUrl" character varying(512) + `); + await queryRunner.query(` + ALTER TABLE "meta" + ADD "libreTranslateApiKey" character varying(128) + `); + } + + async down(queryRunner) { + await queryRunner.query(` + ALTER TABLE "meta" DROP COLUMN "libreTranslateApiKey" + `); + await queryRunner.query(` + ALTER TABLE "meta" DROP COLUMN "libreTranslateApiUrl" + `); + } +} diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 4f367debe0..0cd8c02adc 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -89,6 +89,11 @@ export type Source = { authKey?: string; isPro?: boolean; }; + libreTranslate: { + managed?: boolean; + apiUrl?: string; + apiKey?: string; + }; email: { managed?: boolean; address?: string; diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 26a7c9c193..2f77796c4b 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -386,6 +386,18 @@ export class Meta { }) public deeplIsPro: boolean; + @Column('varchar', { + length: 512, + nullable: true, + }) + public libreTranslateApiUrl: string | null; + + @Column('varchar', { + length: 128, + nullable: true, + }) + public libreTranslateApiKey: string | null; + @Column('varchar', { length: 512, nullable: true, diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts index 15ad1f9a17..a7b6e95c28 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/hosted.ts @@ -30,6 +30,17 @@ export default define(meta, paramDef, async (ps, me) => { set.deeplIsPro = config.deepl.isPro; } } + if ( + config.libreTranslate.managed != null && + config.libreTranslate.managed === true + ) { + if (typeof config.libreTranslate.apiUrl === "string") { + set.libreTranslateApiUrl = config.libreTranslate.apiUrl; + } + if (typeof config.libreTranslate.apiKey === "string") { + set.libreTranslateApiKey = config.libreTranslate.apiKey; + } + } if (config.email.managed != null && config.email.managed === true) { set.enableEmail = true; if (typeof config.email.address === "string") { diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index c8c639f504..f0ac57892d 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -512,7 +512,8 @@ export default define(meta, paramDef, async (ps, me) => { enableGithubIntegration: instance.enableGithubIntegration, enableDiscordIntegration: instance.enableDiscordIntegration, enableServiceWorker: instance.enableServiceWorker, - translatorAvailable: instance.deeplAuthKey != null, + translatorAvailable: + instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, pinnedPages: instance.pinnedPages, pinnedClipId: instance.pinnedClipId, cacheRemoteFiles: instance.cacheRemoteFiles, @@ -564,6 +565,8 @@ export default define(meta, paramDef, async (ps, me) => { objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle, deeplAuthKey: instance.deeplAuthKey, deeplIsPro: instance.deeplIsPro, + libreTranslateApiUrl: instance.libreTranslateApiUrl, + libreTranslateApiKey: instance.libreTranslateApiKey, enableIpLogging: instance.enableIpLogging, enableActiveEmailValidation: instance.enableActiveEmailValidation, }; diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index f7e79b64b5..a230007323 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -124,6 +124,8 @@ export const paramDef = { summalyProxy: { type: "string", nullable: true }, deeplAuthKey: { type: "string", nullable: true }, deeplIsPro: { type: "boolean" }, + libreTranslateApiUrl: { type: "string", nullable: true }, + libreTranslateApiKey: { type: "string", nullable: true }, enableTwitterIntegration: { type: "boolean" }, twitterConsumerKey: { type: "string", nullable: true }, twitterConsumerSecret: { type: "string", nullable: true }, @@ -515,6 +517,22 @@ export default define(meta, paramDef, async (ps, me) => { set.deeplIsPro = ps.deeplIsPro; } + if (ps.libreTranslateApiUrl !== undefined) { + if (ps.libreTranslateApiUrl === "") { + set.libreTranslateApiUrl = null; + } else { + set.libreTranslateApiUrl = ps.libreTranslateApiUrl; + } + } + + if (ps.libreTranslateApiKey !== undefined) { + if (ps.libreTranslateApiKey === "") { + set.libreTranslateApiKey = null; + } else { + set.libreTranslateApiKey = ps.libreTranslateApiKey; + } + } + if (ps.enableIpLogging !== undefined) { set.enableIpLogging = ps.enableIpLogging; } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 4dc1c941e3..23989750fc 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -482,7 +482,8 @@ export default define(meta, paramDef, async (ps, me) => { enableServiceWorker: instance.enableServiceWorker, - translatorAvailable: instance.deeplAuthKey != null, + translatorAvailable: + instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, defaultReaction: instance.defaultReaction, ...(ps.detail diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index c6415ceef2..d86fc12a2e 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -51,15 +51,54 @@ export default define(meta, paramDef, async (ps, user) => { const instance = await fetchMeta(); - if (instance.deeplAuthKey == null) { + if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) { return 204; // TODO: 良い感じのエラー返す } let targetLang = ps.targetLang; if (targetLang.includes("-")) targetLang = targetLang.split("-")[0]; + if (instance.libreTranslateApiUrl != null) { + const jsonBody = { + q: note.text, + source: "auto", + target: targetLang, + format: "text", + api_key: instance.libreTranslateApiKey ?? "", + }; + + const url = new URL(instance.libreTranslateApiUrl); + if (url.pathname.endsWith("/")) { + url.pathname = url.pathname.slice(0, -1); + } + if (!url.pathname.endsWith("/translate")) { + url.pathname += "/translate"; + } + const res = await fetch(url.toString(), { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(jsonBody), + agent: getAgentByUrl, + }); + + const json = (await res.json()) as { + detectedLanguage?: { + confidence: number; + language: string; + }; + translatedText: string; + }; + + return { + sourceLang: json.detectedLanguage?.language, + text: json.translatedText, + }; + } + const params = new URLSearchParams(); - params.append("auth_key", instance.deeplAuthKey); + params.append("auth_key", instance.deeplAuthKey ?? ""); params.append("text", note.text); params.append("target_lang", targetLang); diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index 5349df805a..feedaff6d5 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -371,6 +371,34 @@ + + + + + + + + + + + + + + @@ -422,6 +450,8 @@ let swPublicKey: any = $ref(null); let swPrivateKey: any = $ref(null); let deeplAuthKey: string = $ref(""); let deeplIsPro: boolean = $ref(false); +let libreTranslateApiUrl: string = $ref(""); +let libreTranslateApiKey: string = $ref(""); let defaultReaction: string = $ref(""); let defaultReactionCustom: string = $ref(""); @@ -456,6 +486,8 @@ async function init() { swPrivateKey = meta.swPrivateKey; deeplAuthKey = meta.deeplAuthKey; deeplIsPro = meta.deeplIsPro; + libreTranslateApiUrl = meta.libreTranslateApiUrl; + libreTranslateApiKey = meta.libreTranslateApiKey; defaultReaction = ["⭐", "👍", "❤️"].includes(meta.defaultReaction) ? meta.defaultReaction : "custom"; @@ -498,6 +530,8 @@ function save() { swPrivateKey, deeplAuthKey, deeplIsPro, + libreTranslateApiUrl, + libreTranslateApiKey, defaultReaction, }).then(() => { fetchInstance(); From 461fdd1408307b1a82acec73698ddb5c8cb0b87f Mon Sep 17 00:00:00 2001 From: Kaitlyn Allan Date: Sat, 29 Apr 2023 21:05:33 +1000 Subject: [PATCH 2/8] Remove eslint from calckey-js (use rome) --- packages/calckey-js/.eslintignore | 7 ---- packages/calckey-js/.eslintrc.js | 65 ------------------------------- packages/calckey-js/package.json | 3 +- 3 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 packages/calckey-js/.eslintignore delete mode 100644 packages/calckey-js/.eslintrc.js diff --git a/packages/calckey-js/.eslintignore b/packages/calckey-js/.eslintignore deleted file mode 100644 index f22128f047..0000000000 --- a/packages/calckey-js/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules -/built -/coverage -/.eslintrc.js -/jest.config.ts -/test -/test-d diff --git a/packages/calckey-js/.eslintrc.js b/packages/calckey-js/.eslintrc.js deleted file mode 100644 index 164cf1fbe8..0000000000 --- a/packages/calckey-js/.eslintrc.js +++ /dev/null @@ -1,65 +0,0 @@ -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - parserOptions: { - tsconfigRootDir: __dirname, - project: ["./tsconfig.json"], - }, - plugins: ["@typescript-eslint"], - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - rules: { - indent: [ - "error", - "tab", - { - SwitchCase: 1, - MemberExpression: "off", - flatTernaryExpressions: true, - ArrayExpression: "first", - ObjectExpression: "first", - }, - ], - "eol-last": ["error", "always"], - semi: ["error", "always"], - quotes: ["error", "single"], - "comma-dangle": ["error", "always-multiline"], - "keyword-spacing": [ - "error", - { - before: true, - after: true, - }, - ], - "key-spacing": [ - "error", - { - beforeColon: false, - afterColon: true, - }, - ], - "space-infix-ops": ["error"], - "space-before-blocks": ["error", "always"], - "object-curly-spacing": ["error", "always"], - "nonblock-statement-body-position": ["error", "beside"], - eqeqeq: ["error", "always", { null: "ignore" }], - "no-multiple-empty-lines": ["error", { max: 1 }], - "no-multi-spaces": ["error"], - "no-var": ["error"], - "prefer-arrow-callback": ["error"], - "no-throw-literal": ["error"], - "no-param-reassign": ["warn"], - "no-constant-condition": ["warn"], - "no-empty-pattern": ["warn"], - "@typescript-eslint/no-unnecessary-condition": ["error"], - "@typescript-eslint/no-inferrable-types": ["warn"], - "@typescript-eslint/no-non-null-assertion": ["warn"], - "@typescript-eslint/explicit-function-return-type": ["warn"], - "@typescript-eslint/no-misused-promises": [ - "error", - { - checksVoidReturn: false, - }, - ], - "@typescript-eslint/consistent-type-imports": "error", - }, -}; diff --git a/packages/calckey-js/package.json b/packages/calckey-js/package.json index d68f241752..598dd1cdbc 100644 --- a/packages/calckey-js/package.json +++ b/packages/calckey-js/package.json @@ -9,9 +9,8 @@ "tsd": "tsd", "api": "pnpm api-extractor run --local --verbose", "api-prod": "pnpm api-extractor run --verbose", - "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", "typecheck": "tsc --noEmit", - "lint": "pnpm typecheck && pnpm eslint", + "lint": "pnpm typecheck && pnpm rome check \"src/*.ts\"", "jest": "jest --coverage --detectOpenHandles", "test": "pnpm jest && pnpm tsd" }, From d1c1d75388b35a7ea5c6a5c57e25ab6c47f1b721 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator Date: Sat, 29 Apr 2023 19:14:36 -0700 Subject: [PATCH 3/8] Revert "keyboard accessibility (#9725)" This reverts commit c1d5922acbe7060c0ea779ccf314e9f0e6b91bb3. --- package.json | 2 - packages/client/src/components/MkButton.vue | 3 +- packages/client/src/components/MkCwButton.vue | 18 +- .../src/components/MkDriveFileThumbnail.vue | 7 +- .../client/src/components/MkEmojiPicker.vue | 278 +++++++------ .../client/src/components/MkLaunchPad.vue | 2 +- .../client/src/components/MkMediaImage.vue | 4 - .../client/src/components/MkMenu.child.vue | 21 +- packages/client/src/components/MkMenu.vue | 382 +++++++++--------- packages/client/src/components/MkModal.vue | 86 ++-- .../src/components/MkModalPageWindow.vue | 1 - .../client/src/components/MkModalWindow.vue | 95 +++-- packages/client/src/components/MkNote.vue | 8 +- .../client/src/components/MkNotePreview.vue | 2 +- packages/client/src/components/MkNoteSub.vue | 4 +- .../client/src/components/MkPopupMenu.vue | 2 - .../src/components/MkPostFormAttaches.vue | 1 + .../src/components/MkSubNoteContent.vue | 27 +- .../client/src/components/MkSuperMenu.vue | 5 +- .../src/components/MkUserSelectDialog.vue | 2 - .../client/src/components/MkUsersTooltip.vue | 2 +- packages/client/src/components/MkWidgets.vue | 2 +- .../client/src/components/form/folder.vue | 4 +- packages/client/src/components/form/radio.vue | 3 - .../client/src/components/form/switch.vue | 3 - .../src/components/global/MkPageHeader.vue | 2 - .../src/components/global/RouterView.vue | 3 - packages/client/src/directives/focus.ts | 3 - packages/client/src/directives/index.ts | 2 - packages/client/src/directives/tooltip.ts | 33 +- packages/client/src/pages/admin/_header_.vue | 6 +- .../src/pages/admin/overview.moderators.vue | 2 +- packages/client/src/pages/follow-requests.vue | 1 - .../client/src/pages/settings/accounts.vue | 8 +- packages/client/src/style.scss | 4 + .../src/ui/_common_/navbar-for-mobile.vue | 1 - packages/client/src/ui/_common_/navbar.vue | 21 +- packages/client/src/ui/classic.header.vue | 1 - packages/client/src/ui/classic.sidebar.vue | 4 +- packages/client/src/ui/classic.vue | 2 - pnpm-lock.yaml | 41 +- 41 files changed, 495 insertions(+), 603 deletions(-) delete mode 100644 packages/client/src/directives/focus.ts diff --git a/package.json b/package.json index 51556dea54..80942ff540 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,6 @@ "@bull-board/ui": "^4.10.2", "@napi-rs/cli": "^2.15.0", "@tensorflow/tfjs": "^3.21.0", - "focus-trap": "^7.2.0", - "focus-trap-vue": "^4.0.1", "js-yaml": "4.1.0", "seedrandom": "^3.0.5" }, diff --git a/packages/client/src/components/MkButton.vue b/packages/client/src/components/MkButton.vue index feac281d9e..5f1a5bdb7e 100644 --- a/packages/client/src/components/MkButton.vue +++ b/packages/client/src/components/MkButton.vue @@ -195,7 +195,8 @@ function onMousedown(evt: MouseEvent): void { } &:focus-visible { - outline: auto; + outline: solid 2px var(--focus); + outline-offset: 2px; } &.inline { diff --git a/packages/client/src/components/MkCwButton.vue b/packages/client/src/components/MkCwButton.vue index 1f6340510b..659cb1fbb6 100644 --- a/packages/client/src/components/MkCwButton.vue +++ b/packages/client/src/components/MkCwButton.vue @@ -1,6 +1,5 @@