diff --git a/CHANGELOG.md b/CHANGELOG.md index 452d898dacdc..698b4aceadf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Feat: 通知を種類ごとに 全員から受け取る/フォロー中のユーザーのみ受け取る/フォロワーのみ受け取る/相互のみ受け取る/指定したリストのメンバーのみ受け取る/受け取らない から選べるように - Enhance: タイムラインからRenoteを除外するオプションを追加 - Enhance: ユーザーページのノート一覧でRenoteを除外できるように +- Enhance: タイムラインでファイルが添付されたノートのみ表示するオプションを追加 - Enhance: モデレーションログ機能の強化 - Enhance: 依存関係の更新 - Enhance: ローカリゼーションの更新 diff --git a/locales/index.d.ts b/locales/index.d.ts index 099ebbfc7a66..15736f6994af 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1128,6 +1128,7 @@ export interface Locale { "edited": string; "notificationRecieveConfig": string; "mutualFollow": string; + "fileAttachedOnly": string; "_announcement": { "forExistingUsers": string; "forExistingUsersDescription": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 321c2c5f0152..dcdff1b317fd 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1125,6 +1125,7 @@ showRenotes: "リノートを表示" edited: "編集済み" notificationRecieveConfig: "通知の受信設定" mutualFollow: "相互フォロー" +fileAttachedOnly: "ファイル付きのみ" _announcement: forExistingUsers: "既存ユーザーのみ" diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index 3e7c53751283..1dcafd6be117 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -24,9 +24,11 @@ const props = withDefaults(defineProps<{ sound?: boolean; withRenotes?: boolean; withReplies?: boolean; + onlyFiles?: boolean; }>(), { withRenotes: true, withReplies: false, + onlyFiles: false, }); const emit = defineEmits<{ @@ -69,10 +71,12 @@ if (props.src === 'antenna') { query = { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }; connection = stream.useChannel('homeTimeline', { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }); connection.on('note', prepend); @@ -82,10 +86,12 @@ if (props.src === 'antenna') { query = { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }; connection = stream.useChannel('localTimeline', { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }); connection.on('note', prepend); } else if (props.src === 'social') { @@ -93,10 +99,12 @@ if (props.src === 'antenna') { query = { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }; connection = stream.useChannel('hybridTimeline', { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }); connection.on('note', prepend); } else if (props.src === 'global') { @@ -104,10 +112,12 @@ if (props.src === 'antenna') { query = { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }; connection = stream.useChannel('globalTimeline', { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, }); connection.on('note', prepend); } else if (props.src === 'mentions') { @@ -131,11 +141,13 @@ if (props.src === 'antenna') { query = { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, listId: props.list, }; connection = stream.useChannel('userList', { withRenotes: props.withRenotes, withReplies: props.withReplies, + withFiles: props.onlyFiles ? true : undefined, listId: props.list, }); connection.on('note', prepend); diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index a11c6fa07427..3c29ccdce728 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -15,11 +15,12 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -62,6 +63,7 @@ let srcWhenNotSignin = $ref(isLocalTimelineAvailable ? 'local' : 'global'); const src = $computed({ get: () => ($i ? defaultStore.reactiveState.tl.value.src : srcWhenNotSignin), set: (x) => saveSrc(x) }); const withRenotes = $ref(true); const withReplies = $ref(false); +const onlyFiles = $ref(false); watch($$(src), () => queue = 0); @@ -147,6 +149,11 @@ const headerActions = $computed(() => [{ text: i18n.ts.withReplies, icon: 'ti ti-arrow-back-up', ref: $$(withReplies), + }, { + type: 'switch', + text: i18n.ts.onlyFiles, + icon: 'ti ti-photo', + ref: $$(onlyFiles), }], ev.currentTarget ?? ev.target); }, }]); diff --git a/packages/frontend/src/ui/deck/deck-store.ts b/packages/frontend/src/ui/deck/deck-store.ts index fcd595661be0..49fdf4d31465 100644 --- a/packages/frontend/src/ui/deck/deck-store.ts +++ b/packages/frontend/src/ui/deck/deck-store.ts @@ -32,6 +32,7 @@ export type Column = { tl?: 'home' | 'local' | 'social' | 'global'; withRenotes?: boolean; withReplies?: boolean; + onlyFiles?: boolean; }; export const deckStore = markRaw(new Storage('deck', { diff --git a/packages/frontend/src/ui/deck/tl-column.vue b/packages/frontend/src/ui/deck/tl-column.vue index e89c8b3358ab..b6dc6c7f2145 100644 --- a/packages/frontend/src/ui/deck/tl-column.vue +++ b/packages/frontend/src/ui/deck/tl-column.vue @@ -23,10 +23,11 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -52,6 +53,7 @@ const isLocalTimelineAvailable = (($i == null && instance.policies.ltlAvailable) const isGlobalTimelineAvailable = (($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable)); const withRenotes = $ref(props.column.withRenotes ?? true); const withReplies = $ref(props.column.withReplies ?? false); +const onlyFiles = $ref(props.column.onlyFiles ?? false); watch($$(withRenotes), v => { updateColumn(props.column.id, { @@ -111,6 +113,10 @@ const menu = [{ type: 'switch', text: i18n.ts.withReplies, ref: $$(withReplies), +}, { + type: 'switch', + text: i18n.ts.fileAttachedOnly, + ref: $$(onlyFiles), }];