diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a50068f1d7..37c3bede9c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,7 @@ "workspaceFolder": "/workspace", "features": { "ghcr.io/devcontainers-contrib/features/pnpm:2": { - "version": "8.9.2" + "version": "latest" }, "ghcr.io/devcontainers/features/node:1": { "version": "20" diff --git a/CHANGELOG.md b/CHANGELOG.md index 19675bd910..e35a37e593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,10 +17,12 @@ ### General - Feat: メールアドレスの認証にverifymail.ioを使えるように (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/971ba07a44550f68d2ba31c62066db2d43a0caed) - Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83) +- Feat: TL上からノートが見えなくなるワードミュートであるハードミュートを追加 - Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正 ### Client - Enhance: 絵文字のオートコンプリート機能強化 #12364 +- Enhance: ユーザーのRawデータを表示するページが復活 - fix: 「設定のバックアップ」で一部の項目がバックアップに含まれていなかった問題を修正 - Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367 - Fix: コードエディタが正しく表示されない問題を修正 @@ -32,6 +34,7 @@ - Fix: ロールタイムラインが保存されない問題を修正 - Fix: api.jsonの生成ロジックを改善 #12402 - Fix: 招待コードが使い回せる問題を修正 +- Fix: 特定の条件下でチャンネルやユーザーのノート一覧に最新のノートが表示されなくなる問題を修正 ## 2023.11.1 diff --git a/locales/index.d.ts b/locales/index.d.ts index a26d45c843..958bd066f7 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1042,6 +1042,7 @@ export interface Locale { "enableChartsForFederatedInstances": string; "showClipButtonInNoteFooter": string; "reactionsDisplaySize": string; + "limitWidthOfReaction": string; "noteIdOrUrl": string; "video": string; "videos": string; @@ -1648,7 +1649,9 @@ export interface Locale { "assignTarget": string; "descriptionOfAssignTarget": string; "manual": string; + "manualRoles": string; "conditional": string; + "conditionalRoles": string; "condition": string; "isConditionalRole": string; "isPublic": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 4684bc0cfc..8651bd92d7 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1039,6 +1039,7 @@ enableChartsForRemoteUser: "リモートユーザーのチャートを生成" enableChartsForFederatedInstances: "リモートサーバーのチャートを生成" showClipButtonInNoteFooter: "ノートのアクションにクリップを追加" reactionsDisplaySize: "リアクションの表示サイズ" +limitWidthOfReaction: "リアクションの最大横幅を制限し、縮小して表示する" noteIdOrUrl: "ノートIDまたはURL" video: "動画" videos: "動画" @@ -1558,7 +1559,9 @@ _role: assignTarget: "アサイン" descriptionOfAssignTarget: "マニュアルは誰がこのロールに含まれるかを手動で管理します。\nコンディショナルは条件を設定し、それに合致するユーザーが自動で含まれるようになります。" manual: "マニュアル" + manualRoles: "マニュアルロール" conditional: "コンディショナル" + conditionalRoles: "コンディショナルロール" condition: "条件" isConditionalRole: "これはコンディショナルロールです。" isPublic: "公開ロール" diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index fae4249c8a..4ca7325f30 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -15,6 +15,7 @@ import { IdService } from '@/core/IdService.js'; import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { CacheService } from '@/core/CacheService.js'; +import { MetaService } from '@/core/MetaService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -72,12 +73,15 @@ export default class extends Endpoint { // eslint- private funoutTimelineService: FunoutTimelineService, private cacheService: CacheService, private activeUsersChart: ActiveUsersChart, + private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null); const isRangeSpecified = untilId != null && sinceId != null; + const serverSettings = await this.metaService.fetch(); + const channel = await this.channelsRepository.findOneBy({ id: ps.channelId, }); @@ -88,7 +92,7 @@ export default class extends Endpoint { // eslint- if (me) this.activeUsersChart.read(me); - if (isRangeSpecified || sinceId == null) { + if (serverSettings.enableFanoutTimeline && (isRangeSpecified || sinceId == null)) { const [ userIdsWhoMeMuting, ] = me ? await Promise.all([ diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 33f3f5655d..ea483b9b54 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -263,7 +263,7 @@ export default class extends Endpoint { // eslint- if (renote.channelId && renote.channelId !== ps.channelId) { // チャンネルのノートに対しリノート要求がきたとき、チャンネル外へのリノート可否をチェック // リノートのユースケースのうち、チャンネル内→チャンネル外は少数だと考えられるため、JOINはせず必要な時に都度取得する - const renoteChannel = await this.channelsRepository.findOneById(renote.channelId); + const renoteChannel = await this.channelsRepository.findOneBy({ id: renote.channelId }); if (renoteChannel == null) { // リノートしたいノートが書き込まれているチャンネルが無い throw new ApiError(meta.errors.noSuchChannel); diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 02be8bb93c..415ae42d3f 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -15,6 +15,7 @@ import { IdService } from '@/core/IdService.js'; import { isUserRelated } from '@/misc/is-user-related.js'; import { QueryService } from '@/core/QueryService.js'; import { FunoutTimelineService } from '@/core/FunoutTimelineService.js'; +import { MetaService } from '@/core/MetaService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -71,6 +72,7 @@ export default class extends Endpoint { // eslint- private cacheService: CacheService, private idService: IdService, private funoutTimelineService: FunoutTimelineService, + private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null); @@ -78,7 +80,9 @@ export default class extends Endpoint { // eslint- const isRangeSpecified = untilId != null && sinceId != null; const isSelf = me && (me.id === ps.userId); - if (isRangeSpecified || sinceId == null) { + const serverSettings = await this.metaService.fetch(); + + if (serverSettings.enableFanoutTimeline && (isRangeSpecified || sinceId == null)) { const [ userIdsWhoMeMuting, ] = me ? await Promise.all([ diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue index 66114b8734..2c7be319cb 100644 --- a/packages/frontend/src/components/MkAbuseReport.vue +++ b/packages/frontend/src/components/MkAbuseReport.vue @@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
{{ i18n.ts.reporter }}:
+
{{ i18n.ts.reporter }}: @{{ report.reporter.username }}
{{ i18n.ts.moderator }}: diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index 2b850016c5..9a107c3674 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only :class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]" @click="toggleReaction()" > - + {{ count }} @@ -188,7 +188,7 @@ if (!mock) { } } -.icon { +.limitWidth { max-width: 150px; } diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index d87d584daa..9f6c400fac 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -222,13 +222,13 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._role.new }}
- +
- +
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 06d3789829..313b5efc46 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -56,6 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only + {{ i18n.ts.limitWidthOfReaction }}
@@ -226,6 +227,7 @@ const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serve const showNoteActionsOnlyHover = computed(defaultStore.makeGetterSetter('showNoteActionsOnlyHover')); const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showClipButtonInNoteFooter')); const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize')); +const limitWidthOfReaction = computed(defaultStore.makeGetterSetter('limitWidthOfReaction')); const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes')); const reduceAnimation = computed(defaultStore.makeGetterSetter('animation', v => !v, v => !v)); const useBlurEffectForModal = computed(defaultStore.makeGetterSetter('useBlurEffectForModal')); @@ -290,6 +292,7 @@ watch([ overridedDeviceKind, mediaListWithOneImageAppearance, reactionsDisplaySize, + limitWidthOfReaction, highlightSensitiveMedia, keepScreenOn, disableStreamingTimeline, diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue index 7550d5bcb2..50cc9a3311 100644 --- a/packages/frontend/src/pages/user/index.vue +++ b/packages/frontend/src/pages/user/index.vue @@ -18,6 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only +
@@ -44,6 +45,7 @@ const XLists = defineAsyncComponent(() => import('./lists.vue')); const XPages = defineAsyncComponent(() => import('./pages.vue')); const XFlashs = defineAsyncComponent(() => import('./flashs.vue')); const XGallery = defineAsyncComponent(() => import('./gallery.vue')); +const XRaw = defineAsyncComponent(() => import('./raw.vue')); const props = withDefaults(defineProps<{ acct: string; @@ -112,6 +114,10 @@ const headerTabs = $computed(() => user ? [{ key: 'gallery', title: i18n.ts.gallery, icon: 'ti ti-icons', +}, { + key: 'raw', + title: 'Raw', + icon: 'ti ti-code', }] : []); definePageMetadata(computed(() => user ? { diff --git a/packages/frontend/src/pages/user/raw.vue b/packages/frontend/src/pages/user/raw.vue new file mode 100644 index 0000000000..0c0bfc29ca --- /dev/null +++ b/packages/frontend/src/pages/user/raw.vue @@ -0,0 +1,130 @@ + + + + + + + diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 0af2648772..65a3b90b1d 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -330,6 +330,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: 'medium' as 'small' | 'medium' | 'large', }, + limitWidthOfReaction: { + where: 'device', + default: true, + }, forceShowAds: { where: 'device', default: false,