diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 75fb60ae6b..95d51dc967 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,6 +8,8 @@ on: paths: - packages/** pull_request: + branches-ignore: + - weblate jobs: pnpm_install: diff --git a/CHANGELOG.md b/CHANGELOG.md index 26013c14df..c711572655 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,19 @@ --> +## next + +### General +- Enhance: タイムラインからRenoteを除外するオプションを追加 +- Enhance: ユーザーページのノート一覧でRenoteを除外できるように + +### Client +- Enhance: モデレーションログ機能の強化 +- Enhance: Plugin:register_post_form_actionを用いてCWを取得・変更できるように + +### Server +- Enhance: MasterプロセスのPIDを書き出せるように + ## 2023.9.1 ### General diff --git a/README.md b/README.md index 60fcd4f66b..5522774add 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ **🌎 **[Sharkey](https://joinsharkey.org/)** is an open source, decentralized social media platform that's free forever! 🚀** --- + +Translation status + - Work In Progress - --- diff --git a/locales/de-DE.yml b/locales/de-DE.yml index b5ce1f45b3..988e7854d6 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -161,7 +161,7 @@ youCanCleanRemoteFilesCache: "Klicke auf den 🗑️-Knopf der Dateiverwaltungsa cacheRemoteSensitiveFiles: "Sensitive Dateien von fremden Instanzen im Cache speichern" cacheRemoteSensitiveFilesDescription: "Ist diese Einstellung deaktiviert, so werden sensitive Dateien fremder Instanzen direkt von dort ohne Zwischenspeicherung geladen." flagAsBot: "Als Bot markieren" -flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Misskeys interne Systeme dieses Benutzerkonto als Bot behandeln." +flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Sharkeys interne Systeme dieses Benutzerkonto als Bot behandeln." flagAsCat: "Als Katze markieren" flagAsCatDescription: "Aktiviere diese Option, um dieses Benutzerkonto als Katze zu markieren." flagShowTimelineReplies: "Antworten in der Chronik anzeigen" @@ -221,7 +221,7 @@ noUsers: "Keine Benutzer gefunden" editProfile: "Profil bearbeiten" noteDeleteConfirm: "Möchtest du diese Notiz wirklich löschen?" pinLimitExceeded: "Du kannst nicht noch mehr Notizen anheften." -intro: "Misskey ist installiert! Lass uns nun ein Administratorkonto einrichten." +intro: "Sharkey ist installiert! Lass uns nun ein Administratorkonto einrichten." done: "Fertig" processing: "In Bearbeitung …" preview: "Vorschau" @@ -555,7 +555,7 @@ sort: "Sortieren" ascendingOrder: "Aufsteigende Reihenfolge" descendingOrder: "Absteigende Reihenfolge" scratchpad: "Testumgebung" -scratchpadDescription: "Die Testumgebung bietet einen Bereich für AiScript-Experimente. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Misskey überprüfen." +scratchpadDescription: "Die Testumgebung bietet einen Bereich für AiScript-Experimente. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Sharkey überprüfen." output: "Ausgabe" script: "Skript" disablePagesScript: "AiScript auf Seiten deaktivieren" @@ -687,7 +687,7 @@ unclip: "Aus Clip entfernen" confirmToUnclipAlreadyClippedNote: "Diese Notiz ist bereits im \"{name}\" Clip enthalten. Möchtest du sie aus diesem Clip entfernen?" public: "Öffentlich" private: "Privat" -i18nInfo: "Misskey wird durch freiwillige Helfer in viele verschiedene Sprachen übersetzt. Auf {link} kannst du mithelfen." +i18nInfo: "Sharkey wird durch freiwillige Helfer in viele verschiedene Sprachen übersetzt. Auf {link} kannst du mithelfen." manageAccessTokens: "Zugriffstokens verwalten" accountInfo: "Benutzerkonto-Informationen" notesCount: "Anzahl der Notizen" @@ -741,7 +741,7 @@ onlineUsersCount: "{n} Benutzer sind online" nUsers: "{n} Benutzer" nNotes: "{n} Notizen" sendErrorReports: "Fehlerberichte senden" -sendErrorReportsDescription: "Ist diese Option aktiviert, so werden beim Auftreten von Fehlern detaillierte Fehlerinformationen an Misskey weitergegeben, was zur Verbesserung der Qualität von Misskey beiträgt.\nEnthalten in diesen Informationen sind u.a. die Version deines Betriebssystems, welchen Browser du verwendest und ein Verlauf deiner Aktivitäten innerhalb Misskey." +sendErrorReportsDescription: "Ist diese Option aktiviert, so werden beim Auftreten von Fehlern detaillierte Fehlerinformationen an Sharkey weitergegeben, was zur Verbesserung der Qualität von Sharkey beiträgt.\nEnthalten in diesen Informationen sind u.a. die Version deines Betriebssystems, welchen Browser du verwendest und ein Verlauf deiner Aktivitäten innerhalb Sharkey." myTheme: "Mein Farbschema" backgroundColor: "Hintergrundfarbe" accentColor: "Akzentfarbe" @@ -835,7 +835,7 @@ hashtags: "Hashtags" troubleshooting: "Problembehandlung" useBlurEffect: "Weichzeichnungseffekt in der Benutzeroberfläche verwenden" learnMore: "Mehr erfahren" -misskeyUpdated: "Misskey wurde aktualisiert!" +misskeyUpdated: "Sharkey wurde aktualisiert!" whatIsNew: "Änderungen anzeigen" translate: "Übersetzen" translatedFrom: "Aus {x} übersetzt" @@ -964,8 +964,8 @@ numberOfLikes: "\"Gefällt mir\"-Anzahl" show: "Anzeigen" neverShow: "Nicht wieder anzeigen" remindMeLater: "Vielleicht später" -didYouLikeMisskey: "Gefällt dir Misskey?" -pleaseDonate: "Misskey ist die kostenlose Software, die von {host} verwendet wird. Wir würden uns über Spenden freuen, damit dessen Entwicklung weitergeführt werden kann!" +didYouLikeMisskey: "Gefällt dir Sharkey?" +pleaseDonate: "Sharkey ist die kostenlose Software, die von {host} verwendet wird. Wir würden uns über Spenden freuen, damit dessen Entwicklung weitergeführt werden kann!" roles: "Rollen" role: "Rolle" noRole: "Rolle nicht gefunden" @@ -1075,7 +1075,7 @@ rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Diese Rollen müssen öffe cancelReactionConfirm: "Möchtest du deine Reaktion wirklich löschen?" changeReactionConfirm: "Möchtest du deine Reaktion wirklich ändern?" later: "Später" -goToMisskey: "Zu Misskey" +goToMisskey: "Zu Sharkey" additionalEmojiDictionary: "Zusätzliche Emoji-Wörterbücher" installed: "Installiert" branding: "Branding" @@ -1141,7 +1141,7 @@ _initialAccountSetting: pushNotificationDescription: "Durch die Aktivierung von Push-Benachrichtigungen kannst du von {name} Benachrichtigungen direkt auf dein Gerät erhalten." initialAccountSettingCompleted: "Kontoeinrichtung abgeschlossen!" haveFun: "Viel Spaß mit {name}!" - ifYouNeedLearnMore: "Besuche {link}, falls du mehr über {name} (Misskey) lernen möchtest." + ifYouNeedLearnMore: "Besuche {link}, falls du mehr über {name} (Sharkey) lernen möchtest." skipAreYouSure: "Die Kontoeinrichtung wirklich überspringen?" laterAreYouSure: "Die Kontoeinrichtung wirklich später erledigen?" _serverRules: @@ -1163,7 +1163,7 @@ _accountMigration: moveTo: "Dieses Konto zu einem neuen migrieren" moveToLabel: "Umzugsziel:" moveCannotBeUndone: "Die Migration eines Benutzerkontos ist unwiderruflich." - moveAccountDescription: "Hierdurch wird dein Konto zu einem anderen migriert.\n ・Follower von diesem Konto werden automatisch auf das neue Konto migriert\n ・Dieses Konto wird allen Nutzern, denen es derzeit folgt, nicht mehr folgen\n ・Mit diesem Konto können keine neuen Notizen usw. erstellt werden\n\nWährend die Migration der Follower automatisch erfolgt, muss die Migration der Konten, denen du folgst, manuell vorbereitet werden. Exportiere hierzu die Liste der gefolgten Nutzer über das Einstellungsmenu, und importiere diese Liste im neuen Konto. Das gleiche Verfahren gilt für erstellte Listen und stummgeschaltete oder blockierte Nutzer.\n\n(Diese Erklärung gilt für Misskey v13.12.0 oder später. Die Funktionsweise andere ActivityPub-Software, beispielsweise Mastodon, kann hiervon abweichen.)" + moveAccountDescription: "Hierdurch wird dein Konto zu einem anderen migriert.\n ・Follower von diesem Konto werden automatisch auf das neue Konto migriert\n ・Dieses Konto wird allen Nutzern, denen es derzeit folgt, nicht mehr folgen\n ・Mit diesem Konto können keine neuen Notizen usw. erstellt werden\n\nWährend die Migration der Follower automatisch erfolgt, muss die Migration der Konten, denen du folgst, manuell vorbereitet werden. Exportiere hierzu die Liste der gefolgten Nutzer über das Einstellungsmenu, und importiere diese Liste im neuen Konto. Das gleiche Verfahren gilt für erstellte Listen und stummgeschaltete oder blockierte Nutzer.\n\n(Diese Erklärung gilt für Sharkey v13.12.0 oder später. Die Funktionsweise andere ActivityPub-Software, beispielsweise Mastodon, kann hiervon abweichen.)" moveAccountHowTo: "Um ein Konto zu migrieren, erstelle zuerst auf dem Umzugsziel einen Alias für dieses Konto.\nGib dann das Umzugsziel in folgendem Format ein: @username@server.example.com" startMigration: "Migrieren" migrationConfirm: "Dieses Konto wirklich zu {account} umziehen? Sobald der Umzug beginnt, kann er nicht rückgängig gemacht werden, und dieses Konto nicht wieder im ursprünglichen Zustand verwendet werden." @@ -1174,9 +1174,9 @@ _achievements: earnedAt: "Freigeschaltet am" _types: _notes1: - title: "Hallo Misskey!" + title: "Hallo Sharkey!" description: "Sende deine erste Notiz" - flavor: "Hab eine schöne Zeit mit Misskey!" + flavor: "Hab eine schöne Zeit mit Sharkey!" _notes10: title: "Ein paar Notizen" description: "10 Notizen gesendet" @@ -1272,7 +1272,7 @@ _achievements: _login1000: title: "Meister der Notizen Ⅲ" description: "An 1000 Tagen eingeloggt" - flavor: "Danke, dass du Misskey nutzt!" + flavor: "Danke, dass du Sharkey nutzt!" _noteClipped1: title: "Muss... clippen..." description: "Die erste Notiz geclippt" @@ -1332,18 +1332,18 @@ _achievements: title: "Fan von Errungenschaften" description: "Schau dir die Liste deiner Errungenschaften für mindestens 3 Minuten an" _iLoveMisskey: - title: "I Love Misskey" - description: "Sende \"I ❤ #Misskey\"" - flavor: "Danke, dass du Misskey verwendest! - vom Entwicklerteam" + title: "I Love Sharkey" + description: "Sende \"I ❤ #Sharkey\"" + flavor: "Danke, dass du Sharkey verwendest! - vom Entwicklerteam" _foundTreasure: title: "Schatzsuche" description: "Du hast einen verborgenen Schatz gefunden" _client30min: title: "Kurze Pause" - description: "Habe Misskey für mindestens 30 Minuten geöffnet" + description: "Habe Sharkey für mindestens 30 Minuten geöffnet" _client60min: - title: "Munter mit Misskey" - description: "Habe Misskey für mindestens 60 Minuten geöffnet" + title: "Munter mit Sharkey" + description: "Habe Sharkey für mindestens 60 Minuten geöffnet" _noteDeletedWithin1min: title: "Ups" description: "Lösche eine Notiz innerhalb von 1 Minute nachdem sie gesendet wurde" @@ -1711,7 +1711,7 @@ _time: hour: "Stunde(n)" day: "Tag(en)" _timelineTutorial: - title: "Wie du Misskey verwendest" + title: "Wie du Sharkey verwendest" step1_1: "Dieser Bildschirm ist die \"Chronik\". Hier werden alle \"Notizen\" von {name} angezeigt." step1_2: "Es gibt einige verschiedene Chroniken. Beispielsweise werden in der \"Startseite\" alle Notizen von Nutzern, denen du folgst, angezeigt, und in der \"Lokalen Chronik\" werden Notizen aller Nutzer auf {name} angezeigt." step2_1: "Lass uns als nächstes versuchen, eine Notiz zu schreiben. Dies kannst du tun, indem du auf den Knopf mit dem Stift-Icon drückst." diff --git a/locales/en-US.yml b/locales/en-US.yml index 705ed66672..b7c279ac06 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -221,7 +221,7 @@ noUsers: "There are no users" editProfile: "Edit profile" noteDeleteConfirm: "Are you sure you want to delete this note?" pinLimitExceeded: "You cannot pin any more notes" -intro: "Installation of Misskey has been finished! Please create an admin user." +intro: "Installation of Sharkey has been finished! Please create an admin user." done: "Done" processing: "Processing..." preview: "Preview" @@ -741,7 +741,7 @@ onlineUsersCount: "{n} users are online" nUsers: "{n} Users" nNotes: "{n} Notes" sendErrorReports: "Send error reports" -sendErrorReportsDescription: "When turned on, detailed error information will be shared with Misskey when a problem occurs, helping to improve the quality of Misskey.\nThis will include information such the version of your OS, what browser you're using, your activity in Misskey, etc." +sendErrorReportsDescription: "When turned on, detailed error information will be shared with Sharkey when a problem occurs, helping to improve the quality of Sharkey.\nThis will include information such the version of your OS, what browser you're using, your activity in Sharkey, etc." myTheme: "My theme" backgroundColor: "Background color" accentColor: "Accent color" @@ -835,7 +835,7 @@ hashtags: "Hashtags" troubleshooting: "Troubleshooting" useBlurEffect: "Use blur effects in the UI" learnMore: "Learn more" -misskeyUpdated: "Misskey has been updated!" +misskeyUpdated: "Sharkey has been updated!" whatIsNew: "Show changes" translate: "Translate" translatedFrom: "Translated from {x}" @@ -964,8 +964,8 @@ numberOfLikes: "Likes" show: "Show" neverShow: "Don't show again" remindMeLater: "Maybe later" -didYouLikeMisskey: "Have you taken a liking to Misskey?" -pleaseDonate: "{host} uses the free software, Misskey. We would highly appreciate your donations so development of Misskey can continue!" +didYouLikeMisskey: "Have you taken a liking to Sharkey?" +pleaseDonate: "{host} uses the free software, Sharkey. We would highly appreciate your donations so development of Sharkey can continue!" roles: "Roles" role: "Role" noRole: "Role not found" @@ -1075,7 +1075,7 @@ rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "These roles must be public cancelReactionConfirm: "Really delete your reaction?" changeReactionConfirm: "Really change your reaction?" later: "Later" -goToMisskey: "To Misskey" +goToMisskey: "To Sharkey" additionalEmojiDictionary: "Additional emoji dictionaries" installed: "Installed" branding: "Branding" @@ -1120,6 +1120,7 @@ notifyNotes: "Notify about new notes" unnotifyNotes: "Stop notifying about new notes" authentication: "Authentication" authenticationRequiredToContinue: "Please authenticate to continue" +showRenotes: "Include renotes" _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." @@ -1141,7 +1142,7 @@ _initialAccountSetting: pushNotificationDescription: "Enabling push notifications will allow you to receive notifications from {name} directly on your device." initialAccountSettingCompleted: "Profile setup complete!" haveFun: "Enjoy {name}!" - ifYouNeedLearnMore: "If you'd like to learn more about how to use {name} (Misskey), please visit {link}." + ifYouNeedLearnMore: "If you'd like to learn more about how to use {name} (Sharkey), please visit {link}." skipAreYouSure: "Really skip profile setup?" laterAreYouSure: "Really do profile setup later?" _serverRules: @@ -1163,7 +1164,7 @@ _accountMigration: moveTo: "Migrate this account to a different one" moveToLabel: "Account to move to:" moveCannotBeUndone: "Account migration cannot be undone." - moveAccountDescription: "This will migrate your account to a different one.\n ・Followers from this account will automatically be migrated to the new account\n ・This account will unfollow all users it is currently following\n ・You will be unable to create new notes etc. on this account\n\nWhile migration of followers is automatic, you must manually prepare some steps to migrate the list of users you are following. To do so, carry out a follows export that you will later import on the new account in the settings menu. The same procedure applies to your lists as well as your muted and blocked users.\n\n(This explanation applies to Misskey v13.12.0 and later. Other ActivityPub software, such as Mastodon, might function differently.)" + moveAccountDescription: "This will migrate your account to a different one.\n ・Followers from this account will automatically be migrated to the new account\n ・This account will unfollow all users it is currently following\n ・You will be unable to create new notes etc. on this account\n\nWhile migration of followers is automatic, you must manually prepare some steps to migrate the list of users you are following. To do so, carry out a follows export that you will later import on the new account in the settings menu. The same procedure applies to your lists as well as your muted and blocked users.\n\n(This explanation applies to Sharkey v13.12.0 and later. Other ActivityPub software, such as Mastodon, might function differently.)" moveAccountHowTo: "To migrate, first create an alias for this account on the account to move to.\nAfter you have created the alias, enter the account to move to in the following format: @username@server.example.com" startMigration: "Migrate" migrationConfirm: "Really migrate this account to {account}? Once started, this process cannot be stopped or taken back, and you will not be able to use this account in its original state anymore." @@ -1176,7 +1177,7 @@ _achievements: _notes1: title: "just setting up my msky" description: "Post your first note" - flavor: "Have a good time with Misskey!" + flavor: "Have a good time with Sharkey!" _notes10: title: "Some notes" description: "Post 10 notes" @@ -1272,7 +1273,7 @@ _achievements: _login1000: title: "Master of Notes III" description: "Log in for a total of 1,000 days" - flavor: "Thank you for using Misskey!" + flavor: "Thank you for using Sharkey!" _noteClipped1: title: "Must... clip..." description: "Clip your first note" @@ -1332,18 +1333,18 @@ _achievements: title: "Likes Achievements" description: "Look at your list of achievements for at least 3 minutes" _iLoveMisskey: - title: "I Love Misskey" - description: "Post \"I ❤ #Misskey\"" - flavor: "Misskey's development team greatly appreciates your support!" + title: "I Love Sharkey" + description: "Post \"I ❤ #Sharkey\"" + flavor: "Sharkey's development team greatly appreciates your support!" _foundTreasure: title: "Treasure Hunt" description: "You've found the hidden treasure" _client30min: title: "Short break" - description: "Keep Misskey opened for at least 30 minutes" + description: "Keep Sharkey opened for at least 30 minutes" _client60min: - title: "No \"Miss\" in Misskey" - description: "Keep Misskey opened for at least 60 minutes" + title: "No \"Miss\" in Sharkey" + description: "Keep Sharkey opened for at least 60 minutes" _noteDeletedWithin1min: title: "Nevermind" description: "Delete a note within a minute of posting it" @@ -1711,7 +1712,7 @@ _time: hour: "Hour(s)" day: "Day(s)" _timelineTutorial: - title: "How to use Misskey" + title: "How to use Sharkey" step1_1: "This is the \"timeline\". All \"notes\" submitted on {name} will be chronologically displayed here." step1_2: "There are a few different timelines. For example, the \"Home timeline\" will contain notes of users you follow, and the \"Local timeline\" will contain notes from all users of {name}." step2_1: "Let's try posting a note next. You can do so by pressing the button with a pencil icon." diff --git a/locales/index.d.ts b/locales/index.d.ts index 4d8123eb5d..eb2793c710 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1124,6 +1124,7 @@ export interface Locale { "authentication": string; "authenticationRequiredToContinue": string; "dateAndTime": string; + "showRenotes": string; "_announcement": { "forExistingUsers": string; "forExistingUsersDescription": string; @@ -2277,6 +2278,7 @@ export interface Locale { "markSensitiveDriveFile": string; "unmarkSensitiveDriveFile": string; "resolveAbuseReport": string; + "createInvitation": string; }; } declare const locales: { diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 647f5fb5f0..637d580d6a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1121,6 +1121,7 @@ unnotifyNotes: "投稿の通知を解除" authentication: "認証" authenticationRequiredToContinue: "続けるには認証を行ってください" dateAndTime: "日時" +showRenotes: "リノートを表示" _announcement: forExistingUsers: "既存ユーザーのみ" @@ -2190,3 +2191,4 @@ _moderationLogTypes: markSensitiveDriveFile: "ファイルをセンシティブ付与" unmarkSensitiveDriveFile: "ファイルをセンシティブ解除" resolveAbuseReport: "通報を解決" + createInvitation: "招待コードを作成" diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts index 7112e06bdc..2cc5ab6e35 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts @@ -10,6 +10,7 @@ import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; import { generateInviteCode } from '@/misc/generate-invite-code.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -60,6 +61,7 @@ export default class extends Endpoint { // eslint- private inviteCodeEntityService: InviteCodeEntityService, private idService: IdService, + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { if (ps.expiresAt && isNaN(Date.parse(ps.expiresAt))) { @@ -78,6 +80,11 @@ export default class extends Endpoint { // eslint- } const tickets = await Promise.all(ticketsPromises); + + this.moderationLogService.log(me, 'createInvitation', { + invitations: tickets, + }); + return await this.inviteCodeEntityService.packMany(tickets, me); }); } diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 0b3b5c902e..8784e86153 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -4,6 +4,7 @@ */ import { Inject, Injectable } from '@nestjs/common'; +import { Brackets } from 'typeorm'; import type { NotesRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { QueryService } from '@/core/QueryService.js'; @@ -40,6 +41,7 @@ export const paramDef = { properties: { withFiles: { type: 'boolean', default: false }, withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, @@ -88,6 +90,16 @@ export default class extends Endpoint { // eslint- if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); } + + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } //#endregion const timeline = await query.limit(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index e9ae5dc755..9bde5dee21 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -52,6 +52,7 @@ export const paramDef = { includeLocalRenotes: { type: 'boolean', default: true }, withFiles: { type: 'boolean', default: false }, withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, }, required: [], } as const; @@ -137,6 +138,16 @@ export default class extends Endpoint { // eslint- if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); } + + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } //#endregion const timeline = await query.limit(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index af1e0398dc..0fefddc51b 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -42,6 +42,7 @@ export const paramDef = { properties: { withFiles: { type: 'boolean', default: false }, withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, fileType: { type: 'array', items: { type: 'string', } }, @@ -110,6 +111,16 @@ export default class extends Endpoint { // eslint- query.andWhere('0 = (SELECT COUNT(*) FROM drive_file df WHERE df.id = ANY(note."fileIds") AND df."isSensitive" = TRUE)'); } } + + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } //#endregion const timeline = await query.limit(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index 042115ab84..0d47cc1702 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -42,6 +42,7 @@ export const paramDef = { includeLocalRenotes: { type: 'boolean', default: true }, withFiles: { type: 'boolean', default: false }, withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, }, required: [], } as const; @@ -126,6 +127,16 @@ export default class extends Endpoint { // eslint- if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); } + + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } //#endregion const timeline = await query.limit(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 6932073791..c20274b2ba 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -49,6 +49,8 @@ export const paramDef = { includeMyRenotes: { type: 'boolean', default: true }, includeRenotedMyNotes: { type: 'boolean', default: true }, includeLocalRenotes: { type: 'boolean', default: true }, + withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, withFiles: { type: 'boolean', default: false, @@ -130,6 +132,20 @@ export default class extends Endpoint { // eslint- })); } + if (!ps.withReplies) { + query.andWhere('note.replyId IS NULL'); + } + + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } + if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); } diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 5934baef47..e660a0bb25 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -41,7 +41,8 @@ export const paramDef = { type: 'object', properties: { userId: { type: 'string', format: 'misskey:id' }, - includeReplies: { type: 'boolean', default: true }, + withReplies: { type: 'boolean', default: false }, + withRenotes: { type: 'boolean', default: true }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, @@ -114,10 +115,20 @@ export default class extends Endpoint { // eslint- } } - if (!ps.includeReplies) { + if (!ps.withReplies) { query.andWhere('note.replyId IS NULL'); } + if (ps.withRenotes === false) { + query.andWhere(new Brackets(qb => { + qb.orWhere('note.renoteId IS NULL'); + qb.orWhere(new Brackets(qb => { + qb.orWhere('note.text IS NOT NULL'); + qb.orWhere('note.fileIds != \'{}\''); + })); + })); + } + if (ps.includeMyRenotes === false) { query.andWhere(new Brackets(qb => { qb.orWhere('note.userId != :userId', { userId: user.id }); diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index a33f1a956a..fef52b6856 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -19,6 +19,7 @@ class GlobalTimelineChannel extends Channel { public static shouldShare = true; public static requireCredential = false; private withReplies: boolean; + private withRenotes: boolean; constructor( private metaService: MetaService, @@ -37,7 +38,8 @@ class GlobalTimelineChannel extends Channel { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.gtlAvailable) return; - this.withReplies = params.withReplies as boolean; + this.withReplies = params.withReplies ?? false; + this.withRenotes = params.withRenotes ?? true; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -68,6 +70,8 @@ class GlobalTimelineChannel extends Channel { if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } + if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; + // Ignore notes from instances the user has muted if (isInstanceMuted(note, new Set(this.userProfile?.mutedInstances ?? []))) return; diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index bd8888f679..198c68e1c2 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -17,6 +17,7 @@ class HomeTimelineChannel extends Channel { public static shouldShare = true; public static requireCredential = true; private withReplies: boolean; + private withRenotes: boolean; constructor( private noteEntityService: NoteEntityService, @@ -30,7 +31,8 @@ class HomeTimelineChannel extends Channel { @bindThis public async init(params: any) { - this.withReplies = params.withReplies as boolean; + this.withReplies = params.withReplies ?? false; + this.withRenotes = params.withRenotes ?? true; this.subscriber.on('notesStream', this.onNote); } @@ -77,6 +79,8 @@ class HomeTimelineChannel extends Channel { if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } + if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index 760fb8d19f..cde4297478 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -19,6 +19,7 @@ class HybridTimelineChannel extends Channel { public static shouldShare = true; public static requireCredential = true; private withReplies: boolean; + private withRenotes: boolean; constructor( private metaService: MetaService, @@ -37,7 +38,8 @@ class HybridTimelineChannel extends Channel { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.ltlAvailable) return; - this.withReplies = params.withReplies as boolean; + this.withReplies = params.withReplies ?? false; + this.withRenotes = params.withRenotes ?? true; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -89,6 +91,8 @@ class HybridTimelineChannel extends Channel { if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } + if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index f32f8c5cec..ef708c4fee 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -18,6 +18,7 @@ class LocalTimelineChannel extends Channel { public static shouldShare = true; public static requireCredential = false; private withReplies: boolean; + private withRenotes: boolean; constructor( private metaService: MetaService, @@ -36,7 +37,8 @@ class LocalTimelineChannel extends Channel { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.ltlAvailable) return; - this.withReplies = params.withReplies as boolean; + this.withReplies = params.withReplies ?? false; + this.withRenotes = params.withRenotes ?? true; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -68,6 +70,8 @@ class LocalTimelineChannel extends Channel { if (reply.userId !== this.user.id && note.userId !== this.user.id && reply.userId !== note.userId) return; } + if (note.renote && note.text == null && (note.fileIds == null || note.fileIds.length === 0) && !this.withRenotes) return; + // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isUserRelated(note, this.userIdsWhoMeMuting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 35ea710f9e..7b928263ab 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -56,6 +56,7 @@ export const moderationLogTypes = [ 'markSensitiveDriveFile', 'unmarkSensitiveDriveFile', 'resolveAbuseReport', + 'createInvitation', ] as const; export type ModerationLogPayloads = { @@ -198,4 +199,7 @@ export type ModerationLogPayloads = { report: any; forwarded: boolean; }; + createInvitation: { + invitations: any[]; + }; }; diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 9a7327eaf6..71df95c745 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -821,8 +821,10 @@ function showActions(ev) { action: () => { action.handler({ text: text, + cw: cw, }, (key, value) => { if (key === 'text') { text = value; } + if (key === 'cw') { useCw = value !== null; cw = value; } }); }, })), ev.currentTarget ?? ev.target); diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue index fff0639473..14d08968d1 100644 --- a/packages/frontend/src/components/MkSubNoteContent.vue +++ b/packages/frontend/src/components/MkSubNoteContent.vue @@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only RN: ... -
+
({{ i18n.t('withNFiles', { n: note.files.length }) }})
@@ -37,6 +37,7 @@ import MkPoll from '@/components/MkPoll.vue'; import { i18n } from '@/i18n.js'; import { $i } from '@/account.js'; import { shouldCollapsed } from '@/scripts/collapsed.js'; +import { defaultStore } from '@/store.js'; import { useRouter } from '@/router.js'; const props = defineProps<{ diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index d6712e7606..3e7c537512 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -15,14 +15,19 @@ import * as sound from '@/scripts/sound.js'; import { $i } from '@/account.js'; import { defaultStore } from '@/store.js'; -const props = defineProps<{ +const props = withDefaults(defineProps<{ src: string; list?: string; antenna?: string; channel?: string; role?: string; sound?: boolean; -}>(); + withRenotes?: boolean; + withReplies?: boolean; +}>(), { + withRenotes: true, + withReplies: false, +}); const emit = defineEmits<{ (ev: 'note'): void; @@ -62,10 +67,12 @@ if (props.src === 'antenna') { } else if (props.src === 'home') { endpoint = 'notes/timeline'; query = { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }; connection = stream.useChannel('homeTimeline', { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }); connection.on('note', prepend); @@ -73,28 +80,34 @@ if (props.src === 'antenna') { } else if (props.src === 'local') { endpoint = 'notes/local-timeline'; query = { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }; connection = stream.useChannel('localTimeline', { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }); connection.on('note', prepend); } else if (props.src === 'social') { endpoint = 'notes/hybrid-timeline'; query = { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }; connection = stream.useChannel('hybridTimeline', { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }); connection.on('note', prepend); } else if (props.src === 'global') { endpoint = 'notes/global-timeline'; query = { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }; connection = stream.useChannel('globalTimeline', { - withReplies: defaultStore.state.showTimelineReplies, + withRenotes: props.withRenotes, + withReplies: props.withReplies, }); connection.on('note', prepend); } else if (props.src === 'mentions') { @@ -116,9 +129,13 @@ if (props.src === 'antenna') { } else if (props.src === 'list') { endpoint = 'notes/user-list-timeline'; query = { + withRenotes: props.withRenotes, + withReplies: props.withReplies, listId: props.list, }; connection = stream.useChannel('userList', { + withRenotes: props.withRenotes, + withReplies: props.withReplies, listId: props.list, }); connection.on('note', prepend); diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue index 4f11a9b964..8fe3c38eba 100644 --- a/packages/frontend/src/components/MkVisitorDashboard.vue +++ b/packages/frontend/src/components/MkVisitorDashboard.vue @@ -114,8 +114,7 @@ function showMenu(ev) { } function exploreOtherServers() { - // TODO: 言語をよしなに - window.open('https://join.misskey.page/ja-JP/instances', '_blank'); + window.open('https://join.misskey.page/instances', '_blank'); } diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue index ef8bfbbbfc..580816abaa 100644 --- a/packages/frontend/src/components/global/MkPageHeader.vue +++ b/packages/frontend/src/components/global/MkPageHeader.vue @@ -45,7 +45,7 @@ import { onMounted, onUnmounted, ref, inject } from 'vue'; import tinycolor from 'tinycolor2'; import XTabs, { Tab } from './MkPageHeader.tabs.vue'; import { scrollToTop } from '@/scripts/scroll.js'; -import { globalEvents } from '@/events'; +import { globalEvents } from '@/events.js'; import { injectPageMetadata } from '@/scripts/page-metadata.js'; import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js'; diff --git a/packages/frontend/src/pages/about-sharkey.vue b/packages/frontend/src/pages/about-sharkey.vue index b60b9403c4..a360bbbd08 100644 --- a/packages/frontend/src/pages/about-sharkey.vue +++ b/packages/frontend/src/pages/about-sharkey.vue @@ -84,20 +84,6 @@ SPDX-License-Identifier: AGPL-3.0-only - - -
-
- Mask Network -
-
- Skeb -
-
- DC Advirth -
-
-
diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 14f94479f1..8d83b32fa1 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -16,6 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only : {{ log.info.role.name }} : {{ log.info.before.name }} : {{ log.info.role.name }} + : {{ log.info.emoji.name }} : {{ log.info.before.name }} : @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }} : @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }} diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 30015bb285..771f43c66b 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -29,7 +29,6 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.showFixedPostForm }} {{ i18n.ts.showFixedPostFormInChannel }} - {{ i18n.ts.flagShowTimelineReplies }} @@ -47,6 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.showNoteActionsOnlyHover }} {{ i18n.ts.showClipButtonInNoteFooter }} {{ i18n.ts.collapseRenotes }} + Collapse files Load conversation on replies {{ i18n.ts.enableAdvancedMfm }} {{ i18n.ts.enableAnimatedMfm }} @@ -225,6 +225,7 @@ const showNoteActionsOnlyHover = computed(defaultStore.makeGetterSetter('showNot const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showClipButtonInNoteFooter')); const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize')); const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes')); +const collapseFiles = computed(defaultStore.makeGetterSetter('collapseFiles')); const autoloadConversation = computed(defaultStore.makeGetterSetter('autoloadConversation')); const reduceAnimation = computed(defaultStore.makeGetterSetter('animation', v => !v, v => !v)); const useBlurEffectForModal = computed(defaultStore.makeGetterSetter('useBlurEffectForModal')); @@ -251,7 +252,6 @@ const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars')); const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('mediaListWithOneImageAppearance')); const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition')); const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis')); -const showTimelineReplies = computed(defaultStore.makeGetterSetter('showTimelineReplies')); const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn')); watch(lang, () => { diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index cce7360b9b..5fc43dc650 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -15,9 +15,11 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -58,6 +60,8 @@ const rootEl = $shallowRef(); let queue = $ref(0); 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); watch($$(src), () => queue = 0); @@ -129,7 +133,23 @@ function focus(): void { tlComponent.focus(); } -const headerActions = $computed(() => []); +const headerActions = $computed(() => [{ + icon: 'ti ti-dots', + text: i18n.ts.options, + handler: (ev) => { + os.popupMenu([{ + type: 'switch', + text: i18n.ts.showRenotes, + icon: 'ti ti-repeat', + ref: $$(withRenotes), + }, { + type: 'switch', + text: i18n.ts.withReplies, + icon: 'ti ti-arrow-back-up', + ref: $$(withReplies), + }], ev.currentTarget ?? ev.target); + }, +}]); const headerTabs = $computed(() => [...(defaultStore.reactiveState.pinnedUserLists.value.map(l => ({ key: 'list:' + l.id, diff --git a/packages/frontend/src/pages/user/index.timeline.vue b/packages/frontend/src/pages/user/index.timeline.vue index 3a2a2ade81..42040f5304 100644 --- a/packages/frontend/src/pages/user/index.timeline.vue +++ b/packages/frontend/src/pages/user/index.timeline.vue @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -36,7 +36,8 @@ const pagination = { limit: 10, params: computed(() => ({ userId: props.user.id, - includeReplies: include.value === 'replies' || include.value === 'files', + withRenotes: include.value === 'all', + withReplies: include.value === 'all' || include.value === 'files', withFiles: include.value === 'files', })), }; @@ -51,7 +52,7 @@ const pagination = { .tl { background: var(--bg); - border-radius: var(--radius); - overflow: clip; + border-radius: var(--radius); + overflow: clip; } diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 3805c95550..37bc6e3417 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -65,6 +65,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'account', default: true, }, + collapseFiles: { + where: 'account', + default: true, + }, rememberNoteVisibility: { where: 'account', default: false, @@ -127,7 +131,6 @@ export const defaultStore = markRaw(new Storage('base', { '-', 'announcements', 'search', - 'lookup', '-', 'favorites', 'drive', diff --git a/packages/frontend/src/ui/deck/deck-store.ts b/packages/frontend/src/ui/deck/deck-store.ts index f910c5181d..034d675b0e 100644 --- a/packages/frontend/src/ui/deck/deck-store.ts +++ b/packages/frontend/src/ui/deck/deck-store.ts @@ -30,6 +30,8 @@ export type Column = { roleId?: string; includingTypes?: typeof notificationTypes[number][]; tl?: 'home' | 'local' | 'social' | 'global'; + withRenotes?: boolean; + withReplies?: 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 813b801d21..073898409c 100644 --- a/packages/frontend/src/ui/deck/tl-column.vue +++ b/packages/frontend/src/ui/deck/tl-column.vue @@ -20,12 +20,19 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._disabledTimeline.description }}

- + diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 0686354ff4..7d4d4cc8b8 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2604,10 +2604,13 @@ type ModerationLog = { } | { type: 'unmarkSensitiveDriveFile'; info: ModerationLogPayloads['unmarkSensitiveDriveFile']; +} | { + type: 'createInvitation'; + info: ModerationLogPayloads['createInvitation']; }); // @public (undocumented) -export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport"]; +export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation"]; // @public (undocumented) export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"]; diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index aedfb5570e..14a5b5643c 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -74,6 +74,7 @@ export const moderationLogTypes = [ 'markSensitiveDriveFile', 'unmarkSensitiveDriveFile', 'resolveAbuseReport', + 'createInvitation', ] as const; export type ModerationLogPayloads = { @@ -216,4 +217,7 @@ export type ModerationLogPayloads = { report: any; forwarded: boolean; }; + createInvitation: { + invitations: any[]; + }; }; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 0f874875f9..2b853335c0 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -666,4 +666,7 @@ export type ModerationLog = { } | { type: 'unmarkSensitiveDriveFile'; info: ModerationLogPayloads['unmarkSensitiveDriveFile']; +} | { + type: 'createInvitation'; + info: ModerationLogPayloads['createInvitation']; });