diff --git a/locales/index.d.ts b/locales/index.d.ts
index 3645639305..b9558b2cff 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -898,6 +898,10 @@ export interface Locale extends ILocale {
* ソフトウェア
*/
"software": string;
+ /**
+ * ソフトウェア名
+ */
+ "softwareName": string;
/**
* バージョン
*/
@@ -5828,6 +5832,10 @@ export interface Locale extends ILocale {
* サーバー応答なしのため停止中
*/
"autoSuspendedForNotResponding": string;
+ /**
+ * 配信停止中のソフトウェアであるため停止中
+ */
+ "softwareSuspended": string;
};
};
"_bubbleGame": {
@@ -6313,6 +6321,14 @@ export interface Locale extends ILocale {
* 一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。
*/
"thisSettingWillAutomaticallyOffWhenModeratorsInactive": string;
+ /**
+ * 配信停止中のソフトウェア
+ */
+ "deliverSuspendedSoftware": string;
+ /**
+ * 脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。
+ */
+ "deliverSuspendedSoftwareDescription": string;
};
"_accountMigration": {
/**
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 0e20001d6b..6ab287831d 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -220,6 +220,7 @@ silenceThisInstance: "サーバーをサイレンス"
mediaSilenceThisInstance: "サーバーをメディアサイレンス"
operations: "操作"
software: "ソフトウェア"
+softwareName: "ソフトウェア名"
version: "バージョン"
metadata: "メタデータ"
withNFiles: "{n}つのファイル"
@@ -1467,6 +1468,7 @@ _delivery:
manuallySuspended: "手動停止中"
goneSuspended: "サーバー削除のため停止中"
autoSuspendedForNotResponding: "サーバー応答なしのため停止中"
+ softwareSuspended: "配信停止中のソフトウェアであるため停止中"
_bubbleGame:
howToPlay: "遊び方"
@@ -1605,6 +1607,8 @@ _serverSettings:
openRegistration: "アカウントの作成をオープンにする"
openRegistrationWarning: "登録を開放することはリスクが伴います。サーバーを常に監視し、トラブルが発生した際にすぐに対応できる体制がある場合のみオンにすることを推奨します。"
thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。"
+ deliverSuspendedSoftware: "配信停止中のソフトウェア"
+ deliverSuspendedSoftwareDescription: "脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。"
_accountMigration:
moveFrom: "別のアカウントからこのアカウントに移行"
diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue
index c019bda32c..fd8e76b2bd 100644
--- a/packages/frontend/src/pages/admin/settings.vue
+++ b/packages/frontend/src/pages/admin/settings.vue
@@ -232,6 +232,31 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.federationAllowedHosts }}{{ i18n.ts.modified }}
{{ i18n.ts.federationAllowedHostsDescription }}
+
+
+
+ {{ i18n.ts._serverSettings.deliverSuspendedSoftware }}
+
+
+ {{ i18n.ts.add }}
+
+
+
+
+
{{ i18n.ts._serverSettings.deliverSuspendedSoftwareDescription }}
+
+
+
@@ -372,10 +397,12 @@ const urlPreviewForm = useForm({
const federationForm = useForm({
federation: meta.federation,
federationHosts: meta.federationHosts.join('\n'),
+ deliverSuspendedSoftware: meta.deliverSuspendedSoftware,
}, async (state) => {
await os.apiWithDialog('admin/update-meta', {
federation: state.federation,
federationHosts: state.federationHosts.split('\n'),
+ deliverSuspendedSoftware: state.deliverSuspendedSoftware,
});
fetchInstance(true);
});
@@ -402,4 +429,53 @@ definePage(() => ({
font-size: 0.85em;
color: var(--MI_THEME-fgTransparentWeak);
}
+
+.metadataRoot {
+ container-type: inline-size;
+}
+
+.fieldDragItem {
+ display: flex;
+ padding: 10px;
+ align-items: flex-end;
+ border-radius: 6px;
+
+ /* (drag button) 32px + (drag button margin) 8px + (input width) 200px * 2 + (input gap) 12px = 452px */
+ @container (max-width: 452px) {
+ align-items: center;
+ }
+}
+
+.dragItemHandle {
+ cursor: grab;
+ width: 32px;
+ height: 32px;
+ margin: 0 8px 0 0;
+ opacity: 0.5;
+ flex-shrink: 0;
+
+ &:active {
+ cursor: grabbing;
+ }
+}
+
+.dragItemRemove {
+ @extend .dragItemHandle;
+
+ color: #ff2a2a;
+ opacity: 1;
+ cursor: pointer;
+
+ &:hover, &:focus {
+ opacity: .7;
+ }
+
+ &:active {
+ cursor: pointer;
+ }
+}
+
+.dragItemForm {
+ flex-grow: 1;
+}
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 66ddf627e4..89d9a93fe7 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._delivery.stop }}
- {{ i18n.ts._delivery.resume }}
+ {{ i18n.ts._delivery.resume }}
{{ i18n.ts.blockThisInstance }}
{{ i18n.ts.silenceThisInstance }}
{{ i18n.ts.mediaSilenceThisInstance }}
@@ -167,7 +167,7 @@ const tab = ref('overview');
const chartSrc = ref('instance-requests');
const meta = ref(null);
const instance = ref(null);
-const suspensionState = ref<'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding'>('none');
+const suspensionState = ref<'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding' | 'softwareSuspended'>('none');
const isBlocked = ref(false);
const isSilenced = ref(false);
const isMediaSilenced = ref(false);
diff --git a/packages/frontend/src/use/use-form.ts b/packages/frontend/src/use/use-form.ts
index 26cca839c3..1c93557413 100644
--- a/packages/frontend/src/use/use-form.ts
+++ b/packages/frontend/src/use/use-form.ts
@@ -5,6 +5,7 @@
import { computed, reactive, watch } from 'vue';
import type { Reactive } from 'vue';
+import { deepEqual } from '@/utility/deep-equal';
function copy(v: T): T {
return JSON.parse(JSON.stringify(v));
@@ -27,7 +28,7 @@ export function useForm>(initialState: T, save: (n
watch([currentState, previousState], () => {
for (const key in modifiedStates) {
- modifiedStates[key] = currentState[key] !== previousState[key];
+ modifiedStates[key] = !deepEqual(currentState[key], previousState[key]);
}
}, { deep: true });