diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f40667b..14785c763 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - ユーザーが誤ったメールアドレスを入力した場合に招待コードが失効してしまう問題が解消されます。 - Enhance: すでにフォローしたすべての人の返信をTLに追加できるように - Enhance: 未読の通知数を表示できるように +- Enhance: 通知されず、確認の必要もないお知らせ(silence)を作成可能になりました - Enhance: ローカリゼーションの更新 - Enhance: 依存関係の更新 - Change: CWを使用する場合、注釈を空にすることは許可されなくなりました @@ -63,6 +64,7 @@ - Fix: 11以上されているリアクションにおいてツールチップで示されるリアクション数が本来よりも1多い問題を修正 #12174 - Fix: サイレンス状態で公開範囲のパブリックを選択できてしまう問題を修正 #12224 - Fix: In deck layout, replies option is not saved after refresh +- Fix: アーカイブしたお知らせがコントロールパネルに表示される問題を修正 - Note: アップデート後、サウンドに関する設定が初期化されます ### Server @@ -72,6 +74,7 @@ - Enhance: プロフィールの自己紹介欄のMFMが連合するようになりました - 相手がMisskey v2023.11.0以降である必要があります - Enhance: チャンネル取得時のパフォーマンスを向上 +- Enhance: AP: ApplicationタイプのアカウントをisBotとして扱うように - Fix: リストTLに自分のフォロワー限定投稿が含まれない問題を修正 - Fix: ローカルタイムラインに投稿者自身の投稿への返信が含まれない問題を修正 - Fix: 自分のフォローしているユーザーの自分のフォローしていないユーザーの visibility: followers な投稿への返信がストリーミングで流れてくる問題を修正 diff --git a/locales/en-US.yml b/locales/en-US.yml index 40a5f7b14..5056b2412 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1157,6 +1157,7 @@ disableStreamingTimeline: "Disable real-time timeline updates" useGroupedNotifications: "Display grouped notifications" signupPendingError: "There was a problem verifying the email address. The link may have expired." cwNotationRequired: "If \"Hide content\" is enabled, a description must be provided." +doReaction: "Add reaction" _announcement: forExistingUsers: "Existing users only" forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it." @@ -1203,6 +1204,54 @@ _initialTutorial: title: "What are Reactions?" description: "Notes can be reacted to with various emojis. Reactions allow you to express nuances that may not be conveyed with just a 'like.'" letsTryReacting: "Reactions can be added by clicking the '+' button on the note. Try reacting to this sample note!" + reactToContinue: "Add a reaction to proceed." + reactNotification: "You'll receive real-time notifications when someone reacts to your note." + reactDone: "You can undo a reaction by pressing the '-' button." + _timeline: + title: "The Concept of Timelines" + description1: "Misskey provides multiple timelines based on usage (some may not be available depending on the server's policies)." + home: "You can view notes from accounts you follow." + local: "You can view notes from all users on this server." + social: "Notes from the Home and Local timelines will be displayed." + global: "You can view notes from all connected servers." + description2: "You can switch between timelines at the top of the screen at any time." + description3: "Additionally, there are list timelines and channel timelines. For more details, please refer to {link}." + _postNote: + title: "Note Posting Settings" + description1: "When posting a note on Misskey, various options are available. The posting form looks like this." + _visibility: + description: "You can limit who can view your note." + public: "Your note will be visible for all users." + home: "Public only on the Home timeline. People visiting your profile, via followers, and through renotes can see it." + followers: "Visible to followers only. Only followers can see it and no one else, and it cannot be renoted by others." + direct: "Visible only to specified users, and the recipient will be notified. It can be used as an alternative to direct messaging." + doNotSendConfidencialOnDirect1: "Be careful when sending sensitive information!" + doNotSendConfidencialOnDirect2: "Administrators of the server can see what you write. Be careful with sensitive information when sending direct notes to users on untrusted servers." + localOnly: "Posting with this flag will not federate the note to other servers. Users on other servers will not be able to view these notes directly, regardless of the display settings above." + _cw: + title: "Content Warning" + description: "Instead of the body, the content written in 'comments' field will be displayed. Pressing \"read more\" will reveal the body." + _exampleNote: + cw: "This will surely make you hungry!" + note: "Just had a chocolate-glazed donut 🍩😋" + useCases: "This is used when following the server guidelines for necessary notes or for self-restriction of spoiler or sensitive text." + _howToMakeAttachmentsSensitive: + title: "How to Mark Attachments as Sensitive?" + description: "For attachments that are required by server guidelines or that should not be left intact, add a \"sensitive\" flag." + tryThisFile: "Try marking the image attached in this form as sensitive!" + _exampleNote: + note: "Oops, messed up opening the natto lid..." + method: "To mark an attachment as sensitive, click the file thumbnail, open the menu, and click \"Mark as Sensitive.\"" + sensitiveSucceeded: "When attaching files, please set sensitivities in accordance with the server guidelines." + doItToContinue: "Mark the attachment file as sensitive to proceed." + _done: + title: "The tutorial is complete! 🎉" + description: "The functions introduced here are just a small part. For a more detailed understanding of using Misskey, please refer to {link}." +_timelineDescription: + home: "In the Home timeline, you can see notes from accounts you follow." + local: "In the Local timeline, you can see notes from all users on this server." + social: "The Social timeline displays notes from both the Home and Local timelines." + global: "In the Global timeline, you can see notes from all connected servers." _serverRules: description: "A set of rules to be displayed before registration. Setting a summary of the Terms of Service is recommended." _serverSettings: @@ -1472,6 +1521,9 @@ _achievements: _smashTestNotificationButton: title: "Test overflow" description: "Trigger the notification test repeatedly within an extremely short time" + _tutorialCompleted: + title: "Misskey Elementary Course Diploma" + description: "Tutorial completed" _role: new: "New role" edit: "Edit role" @@ -1660,6 +1712,7 @@ _channel: notesCount: "{n} Notes" nameAndDescription: "Name and description" nameOnly: "Name only" + allowRenoteToExternal: "Allow renote and quote outside the channel" _menuDisplay: sideFull: "Side" sideIcon: "Side (Icons)" diff --git a/locales/index.d.ts b/locales/index.d.ts index aedaaa9f7..fc6653b05 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1172,6 +1172,8 @@ export interface Locale { "readConfirmText": string; "shouldNotBeUsedToPresentPermanentInfo": string; "dialogAnnouncementUxWarn": string; + "silence": string; + "silenceDescription": string; }; "_initialAccountSetting": { "accountCreated": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 6ecebfc39..67a57f994 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1170,6 +1170,8 @@ _announcement: readConfirmText: "「{title}」の内容を読み、既読にします。" shouldNotBeUsedToPresentPermanentInfo: "特に新規ユーザーのUXを損ねる可能性が高いため、ストック情報ではなくフロー情報の掲示にお知らせを使用することを推奨します。" dialogAnnouncementUxWarn: "ダイアログ形式のお知らせが同時に2つ以上ある場合、UXに悪影響を及ぼす可能性が非常に高いため、使用は慎重に行うことを推奨します。" + silence: "非通知" + silenceDescription: "オンにすると、このお知らせは通知されず、既読にする必要もなくなります。" _initialAccountSetting: accountCreated: "アカウントの作成が完了しました!" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 90cb5ac3c..4bad051a4 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1157,6 +1157,7 @@ disableStreamingTimeline: "停用時間軸的即時更新" useGroupedNotifications: "分組顯示通知訊息" signupPendingError: "驗證您的電子郵件地址時出現問題。連結可能已過期。" cwNotationRequired: "如果開啟「隱藏內容」,則需要註解說明。" +doReaction: "做出反應" _announcement: forExistingUsers: "僅限既有的使用者" forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。" @@ -1229,7 +1230,7 @@ _initialTutorial: localOnly: "不將貼文發布到聯邦上的其他伺服器。不論上述發布範圍,使用此設定後,其他伺服器上的使用者將無法直接查看此貼文。" _cw: title: "隱藏內容(CW)" - description: "將顯示「註釋」中寫入的內容而不是本文。按一下「查看更多」以顯示本文。" + description: "將顯示「註釋」中寫入的內容而不是本文。按一下「顯示內容」以顯示本文。" _exampleNote: cw: "美食恐怖主義注意" note: "我吃了一個巧克力甜甜圈🍩😋" diff --git a/packages/backend/migration/1699141698112-announcement-silence.js b/packages/backend/migration/1699141698112-announcement-silence.js new file mode 100644 index 000000000..eef9b076f --- /dev/null +++ b/packages/backend/migration/1699141698112-announcement-silence.js @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AnnouncementSilence1699141698112 { + name = 'AnnouncementSilence1699141698112' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "announcement" ADD "silence" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`CREATE INDEX "IDX_7b8d9225168e962f94ea517e00" ON "announcement" ("silence") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_7b8d9225168e962f94ea517e00"`); + await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "silence"`); + } +} diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index ec1a082d7..8c348e595 100644 --- a/packages/backend/src/core/AnnouncementService.ts +++ b/packages/backend/src/core/AnnouncementService.ts @@ -47,6 +47,7 @@ export class AnnouncementService { const q = this.announcementsRepository.createQueryBuilder('announcement') .where('announcement.isActive = true') + .andWhere('announcement.silence = false') .andWhere(new Brackets(qb => { qb.orWhere('announcement.userId = :userId', { userId: user.id }); qb.orWhere('announcement.userId IS NULL'); @@ -73,6 +74,7 @@ export class AnnouncementService { icon: values.icon, display: values.display, forExistingUsers: values.forExistingUsers, + silence: values.silence, needConfirmationToRead: values.needConfirmationToRead, userId: values.userId, }).then(x => this.announcementsRepository.findOneByOrFail(x.identifiers[0])); @@ -124,6 +126,7 @@ export class AnnouncementService { display: values.display, icon: values.icon, forExistingUsers: values.forExistingUsers, + silence: values.silence, needConfirmationToRead: values.needConfirmationToRead, isActive: values.isActive, }); @@ -210,6 +213,7 @@ export class AnnouncementService { icon: announcement.icon, display: announcement.display, needConfirmationToRead: announcement.needConfirmationToRead, + silence: announcement.silence, forYou: announcement.userId === me?.id, isRead: reads.some(read => read.announcementId === announcement.id), })); diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index d6a7de060..bf38d5fd6 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -269,7 +269,7 @@ export class ApPersonService implements OnModuleInit { const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32); - const isBot = getApType(object) === 'Service'; + const isBot = getApType(object) === 'Service' || getApType(object) === 'Application'; const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/); @@ -456,7 +456,7 @@ export class ApPersonService implements OnModuleInit { emojis: emojiNames, name: truncate(person.name, nameLength), tags, - isBot: getApType(object) === 'Service', + isBot: getApType(object) === 'Service' || getApType(object) === 'Application', isCat: (person as any).isCat === true, isLocked: person.manuallyApprovesFollowers, movedToUri: person.movedTo ?? null, diff --git a/packages/backend/src/models/Announcement.ts b/packages/backend/src/models/Announcement.ts index 05d5a086f..8f8be88fe 100644 --- a/packages/backend/src/models/Announcement.ts +++ b/packages/backend/src/models/Announcement.ts @@ -66,6 +66,12 @@ export class MiAnnouncement { }) public forExistingUsers: boolean; + @Index() + @Column('boolean', { + default: false, + }) + public silence: boolean; + @Index() @Column({ ...id(), diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts index 253a29cf5..69c31a05e 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts @@ -58,6 +58,7 @@ export const paramDef = { icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'], default: 'info' }, display: { type: 'string', enum: ['normal', 'banner', 'dialog'], default: 'normal' }, forExistingUsers: { type: 'boolean', default: false }, + silence: { type: 'boolean', default: false }, needConfirmationToRead: { type: 'boolean', default: false }, userId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, }, @@ -78,6 +79,7 @@ export default class extends Endpoint { // eslint- icon: ps.icon, display: ps.display, forExistingUsers: ps.forExistingUsers, + silence: ps.silence, needConfirmationToRead: ps.needConfirmationToRead, userId: ps.userId, }, me); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts index fefc379c0..9630299a6 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts @@ -86,6 +86,7 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); + query.andWhere('announcement.isActive = true'); if (ps.userId) { query.andWhere('announcement.userId = :userId', { userId: ps.userId }); } else { @@ -113,6 +114,7 @@ export default class extends Endpoint { // eslint- display: announcement.display, isActive: announcement.isActive, forExistingUsers: announcement.forExistingUsers, + silence: announcement.silence, needConfirmationToRead: announcement.needConfirmationToRead, userId: announcement.userId, reads: reads.get(announcement)!, diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts index d36590c26..717866aea 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts @@ -35,6 +35,7 @@ export const paramDef = { icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'] }, display: { type: 'string', enum: ['normal', 'banner', 'dialog'] }, forExistingUsers: { type: 'boolean' }, + silence: { type: 'boolean' }, needConfirmationToRead: { type: 'boolean' }, isActive: { type: 'boolean' }, }, @@ -63,6 +64,7 @@ export default class extends Endpoint { // eslint- display: ps.display, icon: ps.icon, forExistingUsers: ps.forExistingUsers, + silence: ps.silence, needConfirmationToRead: ps.needConfirmationToRead, isActive: ps.isActive, }, me); diff --git a/packages/frontend/src/components/MkTutorialDialog.PostNote.vue b/packages/frontend/src/components/MkTutorialDialog.PostNote.vue index 9b55a1dca..b395f6485 100644 --- a/packages/frontend/src/components/MkTutorialDialog.PostNote.vue +++ b/packages/frontend/src/components/MkTutorialDialog.PostNote.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only