From 5ecaf5095ecd4678dd3e05abcc5b0781f6fddb93 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 12 Jul 2025 15:13:35 +0900 Subject: [PATCH] =?UTF-8?q?enhance:=20=E3=82=A6=E3=82=A9=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=83=9E=E3=83=BC=E3=82=AF=E6=A9=9F=E8=83=BD=E3=82=92?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=A7=E5=88=B6=E5=BE=A1=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/backend/src/core/RoleService.ts | 3 +++ .../backend/src/models/json-schema/role.ts | 4 ++++ packages/frontend-shared/js/const.ts | 1 + .../frontend/src/composables/use-uploader.ts | 7 +++++-- .../frontend/src/pages/admin/roles.editor.vue | 20 +++++++++++++++++++ packages/frontend/src/pages/admin/roles.vue | 8 ++++++++ .../frontend/src/pages/settings/drive.vue | 2 +- packages/misskey-js/src/autogen/types.ts | 1 + 11 files changed, 49 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 869ecff00e..27810a5b72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Feat: クリップ内でノートを検索できるように - Feat: Playを検索できるように - Feat: モデレーションにおいて、特定のドライブファイルを添付しているチャットメッセージを一覧できるように +- Enhance: ウォーターマーク機能をロールで制御可能に ### Client - Feat: モデログを検索できるように diff --git a/locales/index.d.ts b/locales/index.d.ts index d5ec9f5d77..ceb3cc672d 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7795,6 +7795,10 @@ export interface Locale extends ILocale { * サーバーサイドのノートの下書きの作成可能数 */ "noteDraftLimit": string; + /** + * ウォーターマーク機能の使用可否 + */ + "watermarkAvailable": string; }; "_condition": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 760f89ef64..6af846f7ee 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2019,6 +2019,7 @@ _role: uploadableFileTypes_caption: "MIMEタイプを指定します。改行で区切って複数指定できるほか、アスタリスク(*)でワイルドカード指定できます。(例: image/*)" uploadableFileTypes_caption2: "ファイルによっては種別を判定できないことがあります。そのようなファイルを許可する場合は {x} を指定に追加してください。" noteDraftLimit: "サーバーサイドのノートの下書きの作成可能数" + watermarkAvailable: "ウォーターマーク機能の使用可否" _condition: roleAssignedTo: "マニュアルロールにアサイン済み" isLocal: "ローカルユーザー" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 314f7e221a..cddfc0094e 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -67,6 +67,7 @@ export type RolePolicies = { chatAvailability: 'available' | 'readonly' | 'unavailable'; uploadableFileTypes: string[]; noteDraftLimit: number; + watermarkAvailable: boolean; }; export const DEFAULT_POLICIES: RolePolicies = { @@ -111,6 +112,7 @@ export const DEFAULT_POLICIES: RolePolicies = { 'audio/*', ], noteDraftLimit: 10, + watermarkAvailable: true, }; @Injectable() @@ -433,6 +435,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { return [...set]; }), noteDraftLimit: calc('noteDraftLimit', vs => Math.max(...vs)), + watermarkAvailable: calc('watermarkAvailable', vs => vs.some(v => v === true)), }; } diff --git a/packages/backend/src/models/json-schema/role.ts b/packages/backend/src/models/json-schema/role.ts index a3f679129d..c9cdbd5d89 100644 --- a/packages/backend/src/models/json-schema/role.ts +++ b/packages/backend/src/models/json-schema/role.ts @@ -313,6 +313,10 @@ export const packedRolePoliciesSchema = { type: 'integer', optional: false, nullable: false, }, + watermarkAvailable: { + type: 'boolean', + optional: false, nullable: false, + }, }, } as const; diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index 4498a5e2b2..5c33c38f44 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -112,6 +112,7 @@ export const ROLE_POLICIES = [ 'chatAvailability', 'uploadableFileTypes', 'noteDraftLimit', + 'watermarkAvailable', ] as const; export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime']; diff --git a/packages/frontend/src/composables/use-uploader.ts b/packages/frontend/src/composables/use-uploader.ts index 6f4ed81f82..826d8c5203 100644 --- a/packages/frontend/src/composables/use-uploader.ts +++ b/packages/frontend/src/composables/use-uploader.ts @@ -104,6 +104,8 @@ export function useUploader(options: { multiple?: boolean; features?: UploaderFeatures; } = {}) { + const $i = ensureSignin(); + const events = new EventEmitter<{ 'itemUploaded': (ctx: { item: UploaderItem; }) => void; }>(); @@ -132,7 +134,7 @@ export function useUploader(options: { uploaded: null, uploadFailed: false, compressionLevel: prefer.s.defaultImageCompressionLevel, - watermarkPresetId: uploaderFeatures.value.watermark ? prefer.s.defaultWatermarkPresetId : null, + watermarkPresetId: uploaderFeatures.value.watermark && $i.policies.watermarkAvailable ? prefer.s.defaultWatermarkPresetId : null, file: markRaw(file), }); const reactiveItem = items.value.at(-1)!; @@ -264,6 +266,7 @@ export function useUploader(options: { if ( uploaderFeatures.value.watermark && + $i.policies.watermarkAvailable && WATERMARK_SUPPORTED_TYPES.includes(item.file.type) && !item.preprocessing && !item.uploading && @@ -500,7 +503,7 @@ export function useUploader(options: { let preprocessedFile: Blob | File = item.file; - const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(preprocessedFile.type); + const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(preprocessedFile.type) && $i.policies.watermarkAvailable; const preset = prefer.s.watermarkPresets.find(p => p.id === item.watermarkPresetId); if (needsWatermark && preset != null) { const canvas = window.document.createElement('canvas'); diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index a266e1df6f..c172e22688 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -780,6 +780,26 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + +
+ + + + + + + + + +
+
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index dee0fb1e5c..e78a4bbc11 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -291,6 +291,14 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + {{ i18n.ts._role.new }} diff --git a/packages/frontend/src/pages/settings/drive.vue b/packages/frontend/src/pages/settings/drive.vue index 0614b1242b..1b99f6dea5 100644 --- a/packages/frontend/src/pages/settings/drive.vue +++ b/packages/frontend/src/pages/settings/drive.vue @@ -87,7 +87,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- + diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index df6a22ec41..51e4b4f45d 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5225,6 +5225,7 @@ export type components = { /** @enum {string} */ chatAvailability: 'available' | 'readonly' | 'unavailable'; noteDraftLimit: number; + watermarkAvailable: boolean; }; ReversiGameLite: { /** Format: id */