diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5e566263..78caef3252 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,19 +11,34 @@ You should also include the user name that made the change. ## 13.0.0 (unreleased) +### TL;DR +- New features (Play, new widgets, new charts, etc) +- Rewriten backend +- Better performance (backend and frontend) +- Various usability improvements +- Various UI tweaks + ### Changes +#### For server admins - Node.js 18.x or later is required +- PostgreSQL 15.x is required + - Misskey not using 15 specific features at 13.0.0, but may do so in the future. - Elasticsearchのサポートが削除されました - 代わりに今後任意の検索プロバイダを設定できる仕組みを構想しています。その仕組みを使えば今まで通りElasticsearchも利用できます -- ノートのウォッチ機能が削除されました - Migrate to Yarn Berry (v3.2.1) @ThatOneCalculator - You may have to `yarn run clean-all`, `sudo corepack enable` and `yarn set version berry` before running `yarn install` if you're still on yarn classic + +#### For users +- ノートのウォッチ機能が削除されました - 新たに動的なPagesを作ることはできなくなりました - - 代わりに今後AiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能の実装を予定しています。 -- AiScriptが0.12.0にアップデートされました - - 0.12.0の変更点についてはこちら https://github.com/syuilo/aiscript/blob/master/CHANGELOG.md#0120 - - 0.12.0未満のプラグインは読み込むことはできません + - 代わりにAiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能が実装されています。 +- AiScriptが0.12.2にアップデートされました + - 0.12.xの変更点についてはこちら https://github.com/syuilo/aiscript/blob/master/CHANGELOG.md#0120 + - 0.12.x未満のプラグインは読み込むことはできません - iOS15以下のデバイスはサポートされなくなりました +- Firefox109以下はサポートされなくなりました + +#### For app developers - API: カスタム絵文字エンティティに`url`プロパティが含まれなくなりました - 絵文字画像を表示するには、`/emoji/.webp`にリクエストすると画像が返ります。 - e.g. `https://p1.a9z.dev/emoji/misskey.webp` @@ -33,12 +48,13 @@ You should also include the user name that made the change. - API: `instance`エンティティに`latestStatus`、`lastCommunicatedAt`、`latestRequestSentAt`プロパティが含まれなくなりました ### Improvements -- Push notification of Antenna note @tamaina -- AVIF support @tamaina -- Add Cloudflare Turnstile CAPTCHA support @CyberRex0 +- Misskey Play @syuilo - Introduce retention-rate aggregation @syuilo - Make possible to export favorited notes @syuilo - Add per user pv chart @syuilo +- Push notification of Antenna note @tamaina +- AVIF support @tamaina +- Add Cloudflare Turnstile CAPTCHA support @CyberRex0 - Server: signToActivityPubGet is set to true by default @syuilo - Server: improve syslog performance @syuilo - Server: improve note scoring for featured notes @CyberRex0 @@ -47,6 +63,7 @@ You should also include the user name that made the change. - Server: delete outdated notes of antenna regularly to improve db performance @syuilo - Server: improve activitypub deliver performance @syuilo - Client: use tabler-icons instead of fontawesome to better design @syuilo +- Client: Add AiScript App widget - Client: Add new gabber kick sounds (thanks for noizenecio) - Client: Add link to user RSS feed in profile menu @ssmucny - Client: Compress non-animated PNG files @saschanaz @@ -57,11 +74,13 @@ You should also include the user name that made the change. - Client: Make widgets of universal/classic sync between devices @tamaina - Client: Implement the button to subscribe push notification @tamaina - Client: Implement the toggle to or not to close push notifications when notifications or messages are read @tamaina +- Client: Improve RSS widget @tamaina - Client: show Unicode emoji tooltip with its name in MkReactionsViewer.reaction @saschanaz - Client: OpenSearch support @SoniEx2 @chaoticryptidz - Client: add user list widget @syuilo - Client: add heatmap of daily active users to about page @syuilo - Client: introduce fluent emoji @syuilo +- Client: show fireworks when visit user who today is birthday @syuilo - Client: show bot warning on screen when logged in as bot account @syuilo - Client: improve overall performance of client @syuilo - Client: ui tweaks @syuilo @@ -73,10 +92,13 @@ You should also include the user name that made the change. - Server: trim long text of note from ap @syuilo - Server: Ap inboxの最大ペイロードサイズを64kbに制限 @syuilo - Server: アンテナの作成数上限を追加 @syuilo +- Server: pages/likeのエラーIDが重複しているのを修正 @syuilo +- Server: pages/updateのパラメータによってはsummaryの値が更新されないのを修正 @syuilo - Client: case insensitive emoji search @saschanaz - Client: InAppウィンドウが操作できなくなることがあるのを修正 @tamaina - Client: use proxied image for instance icon @syuilo - Client: Webhookの編集画面で、内容を保存することができない問題を修正 @m-hayabusa +- Client: Page編集でブロックの移動が行えない問題を修正 @syuilo - Client: update emoji picker immediately on all input @saschanaz - Client: チャートのツールチップが画面に残ることがあるのを修正 @syuilo - Client: fix wrong link in tutorial @syuilo diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index eefb41007b..161a393bc2 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -164,7 +164,6 @@ annotation: "التعليقات" federation: "الفديرالية" instances: "مثيل الخادم" registeredAt: "مسجل منذ" -latestRequestSentAt: "آخر طلب أرسِل في" latestRequestReceivedAt: "آخر طلب تُلقي في" latestStatus: "الحالات الأخيرة" storageUsage: "مساحة التخزين المستخدمة" @@ -381,6 +380,7 @@ administrator: "المدير" token: "الرمز المميز" twoStepAuthentication: "الإستيثاق بعاملَيْن" moderator: "مشرِف" +moderation: "الإشراف" nUsersMentioned: "{n} مستخدمين أُشير إليهم" securityKey: "مفتاح الأمان" securityKeyName: "اسم المفتاح" @@ -814,6 +814,9 @@ colored: "ملوّن" label: "التسمية" localOnly: "المحلي فقط" account: "الحسابات" +cannotLoad: "تعذر التحميل" +like: "أعجبني" +show: "المظهر" _emailUnavailable: used: "هذا البريد الإلكتروني مستخدم" format: "صيغة البريد الإلكتروني غير صالحة" @@ -1229,6 +1232,11 @@ _timelines: local: "المحلي" social: "الاجتماعي" global: "الشامل" +_play: + viewSource: "اظهر المصدر" + featured: "الأكثر شعبية" + title: "العنوان" + summary: "الوصف" _pages: newPage: "أنشئ صفحة جديدة" editPage: "عدّل الصفحة" @@ -1294,6 +1302,7 @@ _notification: yourFollowRequestAccepted: "قُبل طلب المتابعة" youWereInvitedToGroup: "دُعيت إلى فريقٍ" pollEnded: "ظهرت نتائج الاستطلاع" + unreadAntennaNote: "هوائي {name}" _types: all: "الكل" follow: "متابِعون جدد" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index 85ec1d9935..593cbb1b32 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -164,7 +164,6 @@ annotation: "মন্তব্য" federation: "ফেডিভার্স" instances: "ইন্সট্যান্স" registeredAt: "যোগ দিয়েছেন" -latestRequestSentAt: "শেষ রিকুয়েস্ট পাঠানো হয়েছে" latestRequestReceivedAt: "শেষ রিকুয়েস্ট গৃহীত হয়েছে" latestStatus: "সর্বশেষ অবস্থা" storageUsage: "স্টোরেজের ব্যাবহার" @@ -852,6 +851,8 @@ colored: "রঙ্গিন" label: "লেবেল" localOnly: "শুধুমাত্র লোকাল" account: "অ্যাকাউন্টগুলি" +like: "পছন্দ করা" +show: "প্রদর্শন" _emailUnavailable: used: "এই ইমেইল ঠিকানাটি ইতোমধ্যে ব্যবহৃত হয়েছে" format: "এই ইমেল ঠিকানাটি সঠিকভাবে লিখা হয়নি" @@ -1320,6 +1321,12 @@ _timelines: local: "স্থানীয়" social: "সামাজিক" global: "গ্লোবাল" +_play: + viewSource: "উৎস দেখুন" + featured: "জনপ্রিয়" + title: "শিরোনাম" + script: "স্ক্রিপ্ট" + summary: "বর্ণনা" _pages: newPage: "নতুন পৃষ্ঠা বানান" editPage: "পৃষ্ঠাটি সম্পাদনা করুন" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 406fdff0b4..5127803ebc 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -165,7 +165,6 @@ annotation: "Comentaris" federation: "Federació" instances: "Servidors" registeredAt: "Registrat a" -latestRequestSentAt: "Darrera petició enviada" latestRequestReceivedAt: "Última petició rebuda" latestStatus: "Últim estat" storageUsage: "Emmagatzematge utilitzat" diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 552b56a430..2d80008c47 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -161,7 +161,6 @@ annotation: "Komentáře" federation: "Federace" instances: "Instance" registeredAt: "Registrován" -latestRequestSentAt: "Poslední požadavek poslán" latestRequestReceivedAt: "Poslední požadavek přijat" latestStatus: "Poslední status" storageUsage: "Využití úložiště" @@ -611,6 +610,7 @@ speed: "Rychlost" slow: "Pomalá" fast: "Rychlá" account: "Účty" +show: "Zobrazit" _ad: back: "Zpět" _gallery: @@ -749,6 +749,9 @@ _charts: _timelines: home: "Domů" global: "Globální" +_play: + script: "Skript" + summary: "Popis" _pages: newPage: "Vytvořit novou stránku" editPage: "Upravit stránku" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index dfac4fb791..db6bd9ab05 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -167,7 +167,6 @@ annotation: "Anmerkung" federation: "Föderation" instances: "Instanzen" registeredAt: "Registriert am" -latestRequestSentAt: "Letzte Anfrage gesendet" latestRequestReceivedAt: "Letzte Anfrage erhalten" latestStatus: "Neuster Status" storageUsage: "Verbrauchter Speicherplatz" @@ -610,7 +609,7 @@ regexpErrorDescription: "Im regulären Ausdruck deiner {tab}en Wortstummschaltun instanceMute: "Instanzstummschaltungen" userSaysSomething: "{name} hat etwas gesagt" makeActive: "Aktivieren" -display: "Anzeigeart" +display: "Anzeigen" copy: "Kopieren" metrics: "Metriken" overview: "Übersicht" @@ -916,6 +915,11 @@ caption: "Beschreibung" loggedInAsBot: "Momentan als Bot angemeldet" tools: "Werkzeuge" cannotLoad: "Kann nicht geladen werden" +numberOfProfileView: "Profilaufrufe" +like: "Gefällt mir" +unlike: "\"Gefällt mir\" entfernen" +numberOfLikes: "\"Gefällt mir\"-Anzahl" +show: "Anzeigen" _sensitiveMediaDetection: description: "Ermöglicht eine Erleichterung der Servermoderation durch die automatische Erkennungen von NSFW-Medien unter Verwendung von Machine Learning. Hierdurch wird die Serverlast etwas erhöht." sensitivity: "Erkennungssensitivität" @@ -1315,6 +1319,7 @@ _widgets: jobQueue: "Job-Warteschlange" serverMetric: "Servermetriken" aiscript: "AiScript-Konsole" + aiscriptApp: "AiScript-Anwendung" aichan: "Ai" userList: "Benutzerliste" _userList: @@ -1420,6 +1425,21 @@ _timelines: local: "Lokal" social: "Sozial" global: "Global" +_play: + new: "Play erstellen" + edit: "Play bearbeiten" + created: "Play erfolgreich erstellt" + updated: "Play erfolgreich aktualisiert" + deleted: "Play erfolgreich gelöscht" + pageSetting: "Play-Einstellungen" + editThisPage: "Dieses Play bearbeiten" + viewSource: "Quelltext anzeigen" + my: "Meine Plays" + liked: "Mit \"Gefällt mir\" markierte Plays" + featured: "Beliebt" + title: "Titel" + script: "Skript" + summary: "Beschreibung" _pages: newPage: "Seite erstellen" editPage: "Seite bearbeiten" diff --git a/locales/en-US.yml b/locales/en-US.yml index 414bc1df51..e2a7b32be8 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -167,7 +167,6 @@ annotation: "Comments" federation: "Federation" instances: "Instances" registeredAt: "Registered at" -latestRequestSentAt: "Last request sent" latestRequestReceivedAt: "Last request received" latestStatus: "Latest status" storageUsage: "Storage usage" @@ -916,6 +915,11 @@ caption: "Caption" loggedInAsBot: "Currently logged in as bot" tools: "Tools" cannotLoad: "Unable to load" +numberOfProfileView: "Profile views" +like: "Like" +unlike: "Unlike" +numberOfLikes: "Likes" +show: "Show" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing NSFW media via Machine Learning. This will slightly increase the load on the server." sensitivity: "Detection sensitivity" @@ -1315,6 +1319,7 @@ _widgets: jobQueue: "Job Queue" serverMetric: "Server metrics" aiscript: "AiScript console" + aiscriptApp: "AiScript App" aichan: "Ai" userList: "User list" _userList: @@ -1420,6 +1425,21 @@ _timelines: local: "Local" social: "Social" global: "Global" +_play: + new: "Create Play" + edit: "Edit Play" + created: "Play created" + updated: "Play edited" + deleted: "Play deleted" + pageSetting: "Play settings" + editThisPage: "Edit this Play" + viewSource: "View source" + my: "My Plays" + liked: "Liked Plays" + featured: "Popular" + title: "Title" + script: "Script" + summary: "Description" _pages: newPage: "Create a new Page" editPage: "Edit this Page" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 50db3fe306..c328737c4b 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -13,6 +13,7 @@ fetchingAsApObject: "Buscando en el fediverso" ok: "OK" gotIt: "¡Lo tengo!" cancel: "Cancelar" +noThankYou: "No gracias" enterUsername: "Introduce el nombre de usuario" renotedBy: "Renotado por {user}" noNotes: "No hay notas" @@ -48,6 +49,7 @@ deleteAndEdit: "Borrar y editar" deleteAndEditConfirm: "¿Estás seguro de que quieres borrar esta nota y editarla? Perderás todas las reacciones, renotas y respuestas." addToList: "Agregar a lista" sendMessage: "Enviar un mensaje" +copyRSS: "Copiar RSS" copyUsername: "Copiar nombre de usuario" searchUser: "Buscar un usuario" reply: "Responder" @@ -165,7 +167,6 @@ annotation: "Anotación" federation: "Federación" instances: "Instancia" registeredAt: "Registrado en" -latestRequestSentAt: "Ultimo pedido enviado" latestRequestReceivedAt: "Ultimo pedido recibido" latestStatus: "Último status" storageUsage: "Almacenamiento usado" @@ -455,6 +456,8 @@ language: "Idioma" uiLanguage: "Idioma de visualización de la interfaz" groupInvited: "Invitado al grupo" aboutX: "Acerca de {x}" +emojiStyle: "Estilo de emoji" +native: "Nativo" disableDrawer: "No mostrar los menús en cajones" youHaveNoGroups: "Sin grupos" joinOrCreateGroup: "Obtenga una invitación para unirse al grupos o puede crear su propio grupo." @@ -713,6 +716,7 @@ accentColor: "Acento" textColor: "Texto" saveAs: "Guardar como…" advanced: "Avanzado" +advancedSettings: "Configuración avanzada" value: "Valores" createdAt: "Fecha de creación" updatedAt: "Actualizado" @@ -898,6 +902,22 @@ navbar: "Barra de navegación" shuffle: "Aleatorio" account: "Cuentas" move: "Mover" +pushNotification: "Alerta emergente" +subscribePushNotification: "Activar las notificaciones emergentes" +unsubscribePushNotification: "Desactivar las notificaciones emergentes" +pushNotificationAlreadySubscribed: "Notificaciones emergentes ya activadas" +pushNotificationNotSupported: "El navegador o la instancia no admiten notificaciones push" +sendPushNotificationReadMessage: "Eliminar las notificaciones push después de leer las notificaciones y los mensajes" +sendPushNotificationReadMessageCaption: "La notificación \"{emptyPushNotificationMessage}\" aparecerá momentáneamente. Esto puede aumentar el consumo de batería del dispositivo." +windowMaximize: "Maximizar" +windowRestore: "Regresar" +caption: "Pie de foto" +loggedInAsBot: "Inicio sesión como cuenta bot." +tools: "Utilidades" +cannotLoad: "No se puede cargar." +numberOfProfileView: "Número de vistas de perfil" +like: "¡Muy bien!" +show: "Apariencia" _sensitiveMediaDetection: description: "Reduce el esfuerzo de la moderación el el servidor a través del reconocimiento automático de contenido NSFW usando 'Machine Learning'. Esto puede incrementar ligeramente la carga en el servidor." sensitivity: "Sensibilidad de detección" @@ -1208,6 +1228,9 @@ _tutorial: step7_1: "Así terminó la explicación del funcionamiento básico de Misskey. Eso fue todo." step7_2: "Si quieres conocer más sobre Misskey, prueba con la sección {help}." step7_3: "Así, disfruta de Misskey 🚀" + step8_1: "Por último, ¿por qué no activar las notificaciones emergentes?" + step8_2: "Al recibir notificaciones emergentes, estarás al tanto de reacciones, seguimientos y menciones incluso cuando Misskey no esté abierto." + step8_3: "La configuración de las notificaciones puede modificarse posteriormente." _2fa: alreadyRegistered: "Ya has completado la configuración." registerDevice: "Registrar dispositivo" @@ -1295,6 +1318,7 @@ _widgets: serverMetric: "Estadísticas del servidor" aiscript: "Consola de AiScript" aichan: "indigo" + userList: "Lista de usuarios" _userList: chooseList: "Seleccione una lista" _cw: @@ -1360,6 +1384,7 @@ _profile: changeBanner: "Cambiar banner" _exportOrImport: allNotes: "Todas las notas" + favoritedNotes: "Notas favoritas" followingList: "Siguiendo" muteList: "Silenciados" blockingList: "Bloqueados" @@ -1397,6 +1422,12 @@ _timelines: local: "Local" social: "Social" global: "Global" +_play: + viewSource: "Ver la fuente" + featured: "Popular" + title: "Título" + script: "Script" + summary: "Descripción" _pages: newPage: "Crear página" editPage: "Editar página" @@ -1464,6 +1495,7 @@ _notification: yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada" youWereInvitedToGroup: "Invitado al grupo" pollEnded: "Estan disponibles los resultados de la encuesta" + unreadAntennaNote: "Antena {name}" emptyPushNotificationMessage: "Se han actualizado las notificaciones push" _types: all: "Todo" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 0df7ee2e12..0d7399533d 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -2,6 +2,7 @@ _lang_: "Français" headlineMisskey: "Réseau relié par des notes" introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé, libre et ouvert.\nÉcrivez des « notes » et partagez ce qui se passe à l’instant présent, autour de vous avec les autres 📡\nLa fonction « réactions », vous permet également d’ajouter une réaction rapide aux notes des autres utilisateur·rice·s 👍\nExplorons un nouveau monde 🚀" +poweredByMisskeyDescription: "{nom} est l'un des services propulsés par la plateforme ouverte Misskey (appelée \"instance Misskey\")." monthAndDay: "{day}/{month}" search: "Rechercher" notifications: "Notifications" @@ -12,6 +13,7 @@ fetchingAsApObject: "Récupération depuis le fédiverse …" ok: "OK" gotIt: "J’ai compris !" cancel: "Annuler" +noThankYou: "Pas maintenant" enterUsername: "Entrer un nom d’utilisateur·rice" renotedBy: "Renoté par {user}" noNotes: "Aucune note" @@ -47,6 +49,7 @@ deleteAndEdit: "Supprimer et réécrire" deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note et la reformuler ? Vous perdrez toutes les réactions, renotes et réponses y afférentes." addToList: "Ajouter à une liste" sendMessage: "Envoyer un message" +copyRSS: "Copier le RSS" copyUsername: "Copier le nom d’utilisateur·rice" searchUser: "Chercher un·e utilisateur·rice" reply: "Répondre" @@ -143,6 +146,7 @@ flagAsBotDescription: "Si ce compte est géré de manière automatisée, choisis flagAsCat: "Ce compte est un chat" flagAsCatDescription: "Activer l'option \" Je suis un chat \" pour ce compte." flagShowTimelineReplies: "Afficher les réponses dans le fil" +flagShowTimelineRepliesDescription: "Affiche les réponses des utilisateurs aux notes des autres utilisateurs dans la timeline si cette option est activée." autoAcceptFollowed: "Accepter automatiquement les demandes d’abonnement venant d’utilisateur·rice·s que vous suivez" addAccount: "Ajouter un compte" loginFailed: "Échec de la connexion" @@ -163,7 +167,6 @@ annotation: "Commentaires" federation: "Fédération" instances: "Instance" registeredAt: "Premier contact le" -latestRequestSentAt: "Dernière requête envoyée" latestRequestReceivedAt: "Dernière requête reçue" latestStatus: "Dernier statut" storageUsage: "Stockage utilisé" @@ -453,6 +456,8 @@ language: "Langue" uiLanguage: "Langue d’affichage de l’interface" groupInvited: "Invité au groupe" aboutX: "À propos de {x}" +emojiStyle: "Style des émojis" +native: "Natif" disableDrawer: "Les menus ne s'affichent pas dans le tiroir" youHaveNoGroups: "Vous n’avez aucun groupe" joinOrCreateGroup: "Vous pouvez être invité·e à rejoindre des groupes existants ou créer votre propre nouveau groupe." @@ -600,6 +605,7 @@ smtpSecureInfo: "Désactiver cette option lorsque STARTTLS est utilisé" testEmail: "Tester la distribution de courriel" wordMute: "Filtre de mots" regexpError: "Erreur d’expression régulière" +regexpErrorDescription: "Une erreur s'est produite dans l'expression régulière sur la ligne {ligne} de votre mot muet {tab} :" instanceMute: "Instance en sourdine" userSaysSomething: "{name} a dit quelque chose" makeActive: "Activer" @@ -708,6 +714,7 @@ accentColor: "Accentuation" textColor: "Texte" saveAs: "Enregistrer sous ..." advanced: "Avancé" +advancedSettings: "Paramètres avancés" value: "Valeur" createdAt: "Date de création" updatedAt: "Mis à jour le" @@ -852,6 +859,7 @@ rateLimitExceeded: "Limite de taux dépassée" cropImage: "Recadrer l'image" cropImageAsk: "Voulez-vous recadrer cette image ?" file: "Fichiers" +recentNHours: "Dernières {n} heures" noEmailServerWarning: "Serveur de courrier non configuré." thereIsUnresolvedAbuseReportWarning: "Il n’y a aucun rapport non résolu." recommended: "Recommandé" @@ -891,6 +899,19 @@ navbar: "Barre de navigation" shuffle: "Lecture aléatoire" account: "Comptes" move: "Déplacer" +pushNotification: "Notifications push" +subscribePushNotification: "Autoriser les notifications push" +unsubscribePushNotification: "Désactiver les notifications push" +pushNotificationAlreadySubscribed: "Les notifications push sont déjà activées" +pushNotificationNotSupported: "Votre navigateur ou votre instance ne prend pas en charge les notifications push" +sendPushNotificationReadMessage: "Supprimer les notifications push une fois que les notifications ou messages pertinents ont été lus." +windowRestore: "Restaurer" +caption: "Libellé" +loggedInAsBot: "Connecté actuellement en tant que bot" +tools: "Outils" +cannotLoad: "Chargement impossible" +like: "J'aime" +show: "Affichage" _sensitiveMediaDetection: description: "L'apprentissage automatique peut être utilisé pour détecter automatiquement les médias sensibles à modérer. La sollicitation des serveurs augmente légèrement." sensitivity: "Sensibilité de la détection" @@ -1201,6 +1222,8 @@ _tutorial: step7_1: "Félicitations ! Vous avez atteint la fin du tutoriel de base pour l’utilisation de Misskey." step7_2: "Si vous désirez en savoir plus sur Misskey, jetez un œil sur la section {help}." step7_3: "Bon courage et amusez-vous bien sur Misskey ! 🚀" + step8_1: "Enfin, souhaitez-vous activer les notifications push ?" + step8_2: "En les activant, vous recevrez des notifications pour les mentions, les réactions, les suivis, etc., même lorsque Misskey n'est pas ouvert." _2fa: alreadyRegistered: "Configuration déjà achevée." registerDevice: "Ajouter un nouvel appareil" @@ -1287,6 +1310,7 @@ _widgets: serverMetric: "Statistiques du serveur" aiscript: "Console AiScript" aichan: "Ai" + userList: "Liste utilisateur" _userList: chooseList: "Sélectionner une liste" _cw: @@ -1389,6 +1413,12 @@ _timelines: local: "Local" social: "Social" global: "Global" +_play: + viewSource: "Afficher la source" + featured: "Populaire" + title: "Titre" + script: "Script" + summary: "Description" _pages: newPage: "Créer une page" editPage: "Modifier une page" @@ -1456,6 +1486,7 @@ _notification: yourFollowRequestAccepted: "Votre demande d’abonnement a été accepté" youWereInvitedToGroup: "Invité·e au groupe" pollEnded: "Les résultats du sondage sont disponibles" + unreadAntennaNote: "Antenne {name}" emptyPushNotificationMessage: "Les notifications push ont été mises à jour" _types: all: "Toutes" @@ -1490,6 +1521,7 @@ _deck: newProfile: "Nouveau profil" deleteProfile: "Supprimer le profil" introduction: "Créez l’interface parfaite qui vous sied en arrangeant librement les colonnes !" + introduction2: "Cliquez sur le + à droite de l'écran pour ajouter de nouvelles colonnes quand vous le souhaitez." _columns: main: "Principale" widgets: "Widgets" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index a73e108d7f..3a2bf69a72 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -164,7 +164,6 @@ annotation: "Keterangan konten" federation: "Federasi" instances: "Instansi" registeredAt: "Terdaftar" -latestRequestSentAt: "Permintaan terakhir dikirim pada" latestRequestReceivedAt: "Permintaan terakhir diterima pada" latestStatus: "Status terakhir" storageUsage: "Penggunaan penyimpanan" @@ -856,6 +855,10 @@ colored: "Diwarnai" label: "Label" localOnly: "Hanya lokal" account: "Akun" +like: "Suka" +unlike: "Tidak Suka" +numberOfLikes: "Jumlah yang disukai" +show: "Tampilkan" _emailUnavailable: used: "Alamat surel ini telah digunakan" format: "Format tidak valid." @@ -1221,6 +1224,7 @@ _widgets: jobQueue: "Antrian kerja" serverMetric: "Statistik peladen" aiscript: "Konsol AiScript" + aiscriptApp: "Aplikasi AiScript" aichan: "Ai" _userList: chooseList: "Pilih daftar" @@ -1324,6 +1328,21 @@ _timelines: local: "Lokal" social: "Sosial" global: "Global" +_play: + new: "Membuat Permainan" + edit: "Menyunting Permainan" + created: "Permainan sudah dibuat" + updated: "Permainan sudah diperbaharui" + deleted: "Hapus permainan" + pageSetting: "Pengaturan permainan" + editThisPage: "Sunting Permainan ini" + viewSource: "Lihat sumber" + my: "Permainan saya" + liked: "Permainan Disukai" + featured: "Populer" + title: "Judul" + script: "Script" + summary: "Deskripsi" _pages: newPage: "Buat halaman baru" editPage: "Sunting halaman" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 6b1b47f4e2..3fba19985e 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1,7 +1,7 @@ --- _lang_: "Italiano" headlineMisskey: "Rete collegata tramite note" -introMisskey: "Benvenut@! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \nScrivi \"note\" per condividere ciò che sta succedendo adesso o per dire a tutti qualcosa di te. 📡\nGrazie alla funzione \"reazioni\" puoi anche mandare reazioni rapide alle note delle altre persone del Fediverso. 👍\nEsplora un nuovo mondo! 🚀" +introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n🚀 Esplora un nuovo mondo insieme a noi!" poweredByMisskeyDescription: "{name} è uno dei servizi (chiamati istanze) che utilizzano la piattaforma open source Misskey." monthAndDay: "{day}/{month}" search: "Cerca" @@ -49,6 +49,7 @@ deleteAndEdit: "Elimina e modifica" deleteAndEditConfirm: "Vuoi davvero cancellare questa nota e scriverla di nuovo? Verrano eliminate anche tutte le reazioni, Rinote e risposte collegate." addToList: "Aggiungi alla lista" sendMessage: "Invia messaggio" +copyRSS: "Copia RSS" copyUsername: "Copia nome utente" searchUser: "Cerca utente" reply: "Rispondi" @@ -166,7 +167,6 @@ annotation: "Descrizione" federation: "Federazione" instances: "Istanza" registeredAt: "Registrato presso" -latestRequestSentAt: "Ultima richiesta inviata" latestRequestReceivedAt: "Ultima richiesta ricevuta" latestStatus: "Ultimo stato" storageUsage: "Capienza dei dischi" @@ -456,6 +456,8 @@ language: "Lingua" uiLanguage: "Lingua di visualizzazione dell'interfaccia" groupInvited: "Invitat@ al gruppo" aboutX: "Informazioni su {x}" +emojiStyle: "Stile emoji" +native: "Nativo" disableDrawer: "Non mostrare il menù sul drawer" youHaveNoGroups: "Nessun gruppo" joinOrCreateGroup: "Puoi creare il tuo gruppo o essere invitat@ a gruppi che già esistono." @@ -714,6 +716,7 @@ accentColor: "Colore principale" textColor: "Testo" saveAs: "Salva con nome" advanced: "Avanzato" +advancedSettings: "Impostazioni avanzate" value: "Valore" createdAt: "Data di creazione" updatedAt: "Aggiornato il" @@ -873,7 +876,7 @@ deleteAccount: "Eliminazione profilo" document: "Documento" numberOfPageCache: "Numero di pagine cache" numberOfPageCacheDescription: "Aumenta l'usabilità, ma aumenta anche il carico e l'utilizzo della memoria." -logoutConfirm: "Sei sicuro di voler effettuare il logout?" +logoutConfirm: "Vuoi davvero uscire da Misskey? " lastActiveDate: "Data dell'ultimo utilizzo" statusbar: "Barra di stato" pleaseSelect: "Scegli un'opzione" @@ -910,6 +913,11 @@ windowMaximize: "Ingrandisci" windowRestore: "Ripristina" caption: "Didascalia" loggedInAsBot: "Connessione come Bot" +tools: "Strumenti" +cannotLoad: "Caricamento impossibile" +numberOfProfileView: "Visualizzazioni profilo" +like: "Mi piace!" +show: "Visualizza" _sensitiveMediaDetection: description: "L'apprendimento automatico può essere utilizzato per individuare automaticamente i media sensibili da moderare. Il carico del server aumenta leggermente." sensitivity: "Sensibilità di rilevamento" @@ -1061,7 +1069,7 @@ _mfm: sparkleDescription: "Aggiungere effetti particellari scintillanti." rotate: "Ruota" rotateDescription: "Ruota con un angolo specificato." - plain: "aereo" + plain: "Testo semplice" plainDescription: "Disattiva tutta la sintassi interna." _instanceTicker: none: "Nascondi" @@ -1199,13 +1207,13 @@ _time: day: "giorni" _tutorial: title: "Come usare Misskey" - step1_1: "Benvenuto/a!" + step1_1: "Eccoci!" step1_2: "Questa pagina si chiama una \" Timeline \". Mostra in ordine cronologico le \" note \" delle persone che segui." step1_3: "Attualmente la tua Timeline è vuota perché non segui alcun profilo e non hai pubblicato alcuna nota ancora." - step2_1: "Prima di scrivere una nota o di seguire altri profili, imposta il tuo di profilo!" + step2_1: "Prima di scrivere una «Nota» o di seguire altri profili, prepara il tuo profilo!" step2_2: "Aggiungere qualche informazione su di te aumenterà le tue possibilità di essere seguit@ da altre persone. " step3_1: "Hai finito di impostare il tuo profilo?" - step3_2: "Ora, puoi pubblicare una nota. Facciamo una prova! Premi il pulsante a forma di penna in cima allo schermo per aprire una finestra di dialogo. " + step3_2: "Ora puoi pubblicare una «Nota». Proviamo subito! Premi il bottone con l'icona «penna» per iniziare a scrivere in una finestra di dialogo. " step3_3: "Scritto il testo della nota, puoi pubblicarla premendo il pulsante nella parte superiore destra della finestra di dialogo." step3_4: "Non ti viene niente in mente? Perché non scrivi semplicemente \"Ho appena cominciato a usare Misskey\"?" step4_1: "Hai pubblicato qualcosa?" @@ -1217,7 +1225,7 @@ _tutorial: step6_1: "Adesso, dovresti essere in grado di vedere le note dagli altri profili sulla tua timeline." step6_2: "Puoi anche rispondere alle note con un click, scegliendo le reazioni immediate." step6_3: "Per inviare una reazione, premi l'icona + della nota e scegli l'emoji che vuoi mandare." - step7_1: "Complimenti! Sei arrivat@ alla fine dell'esercitazione di base su come usare Misskey. " + step7_1: "Congratulazioni! Hai completato l'esercitazione iniziale su come usare Misskey." step7_2: "Se vuoi saperne di più su Misskey, puoi dare un'occhiata alla sezione {help}." step7_3: "Da ultimo, buon divertimento su Misskey! 🚀" step8_1: "Per concludere, vuoi attivare le notifiche push?" @@ -1309,7 +1317,8 @@ _widgets: jobQueue: "Coda di lavoro" serverMetric: "Statistiche server" aiscript: "Console AiScript" - aichan: "indaco (tintura)" + aichan: "Mascotte Ai" + userList: "Elenco utenti" _userList: chooseList: "Seleziona una lista" _cw: @@ -1375,6 +1384,7 @@ _profile: changeBanner: "Cambia intestazione" _exportOrImport: allNotes: "Tutte le note" + favoritedNotes: "Note preferite" followingList: "Follows" muteList: "Elenco profili silenziati" blockingList: "Elenco profili bloccati" @@ -1412,6 +1422,12 @@ _timelines: local: "Locale" social: "Sociale" global: "Federata" +_play: + viewSource: "Visualizza sorgente" + featured: "Popolari" + title: "Titolo" + script: "Script" + summary: "Descrizione" _pages: newPage: "Crea pagina" editPage: "Modifica pagina" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d6a5518196..b49d872a0b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -916,6 +916,14 @@ loggedInAsBot: "Botアカウントでログイン中" tools: "ツール" cannotLoad: "読み込めません" numberOfProfileView: "プロフィール表示回数" +like: "いいね!" +unlike: "いいねを解除" +numberOfLikes: "いいね数" +show: "表示" +neverShow: "今後表示しない" +remindMeLater: "また後で" +didYouLikeMisskey: "Misskeyを気に入っていただけましたか?" +pleaseDonate: "Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。" @@ -1348,6 +1356,7 @@ _widgets: jobQueue: "ジョブキュー" serverMetric: "サーバーメトリクス" aiscript: "AiScriptコンソール" + aiscriptApp: "AiScript App" aichan: "藍" userList: "ユーザーリスト" _userList: @@ -1463,6 +1472,22 @@ _timelines: social: "ソーシャル" global: "グローバル" +_play: + new: "Playの作成" + edit: "Playの編集" + created: "Playを作成しました" + updated: "Playを更新しました" + deleted: "Playを削除しました" + pageSetting: "Play設定" + editThisPage: "このPlayを編集" + viewSource: "ソースを表示" + my: "自分のPlay" + liked: "いいねしたPlay" + featured: "人気" + title: "タイトル" + script: "スクリプト" + summary: "説明" + _pages: newPage: "ページの作成" editPage: "ページの編集" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 994fe9a195..f8c045db00 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -167,7 +167,6 @@ annotation: "注釈" federation: "連合" instances: "インスタンス" registeredAt: "初観測" -latestRequestSentAt: "ちょっと前のリクエスト送信" latestRequestReceivedAt: "ちょっと前のリクエスト受信" latestStatus: "ちょっと前のステータス" storageUsage: "ストレージ使うた量" @@ -916,6 +915,8 @@ caption: "キャプション" loggedInAsBot: "Botアカウントでログイン中やで" tools: "ツール" cannotLoad: "読み込めへんで" +like: "ええやん!" +show: "表示" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出して、モデレーションに役立てることができるで。サーバーの負荷が少し増えてまうなあ。" sensitivity: "検出感度やで" @@ -1419,6 +1420,12 @@ _timelines: local: "ローカル" social: "ソーシャル" global: "グローバル" +_play: + viewSource: "ソースを表示" + featured: "人気" + title: "タイトル" + script: "スクリプト" + summary: "説明" _pages: newPage: "ページを作る" editPage: "ページの編集" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index fa73d49a34..d3a4a40b49 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -167,7 +167,6 @@ annotation: "내용에 대한 주석" federation: "연합" instances: "인스턴스" registeredAt: "등록 날짜" -latestRequestSentAt: "마지막으로 요청을 보낸 시간" latestRequestReceivedAt: "마지막으로 요청을 받은 시간" latestStatus: "마지막 상태" storageUsage: "스토리지 사용량" @@ -916,6 +915,11 @@ caption: "캡션" loggedInAsBot: "봇 계정으로 로그인중" tools: "도구" cannotLoad: "불러오지 못했습니다" +numberOfProfileView: "프로필 뷰 수" +like: "좋아요!" +unlike: "좋아요 취소" +numberOfLikes: "좋아요 수" +show: "표시" _sensitiveMediaDetection: description: "기계학습을 통해 자동으로 민감한 미디어를 탐지하여, 모더레이션에 참고할 수 있도록 합니다. 서버의 부하를 약간 증가시킵니다." sensitivity: "탐지 민감도" @@ -1315,6 +1319,7 @@ _widgets: jobQueue: "작업 대기열" serverMetric: "서버 통계" aiscript: "AiScript 콘솔" + aiscriptApp: "AiScript 앱" aichan: "아이" userList: "사용자 목록" _userList: @@ -1382,6 +1387,7 @@ _profile: changeBanner: "배너 이미지 변경" _exportOrImport: allNotes: "모든 노트" + favoritedNotes: "즐겨찾기한 노트" followingList: "팔로잉" muteList: "뮤트" blockingList: "차단" @@ -1419,6 +1425,21 @@ _timelines: local: "로컬" social: "소셜" global: "글로벌" +_play: + new: "Play 만들기" + edit: "Play 수정하기" + created: "Play를 생성했습니다" + updated: "Play를 갱신했습니다" + deleted: "Play를 삭제했습니다" + pageSetting: "Play 설정" + editThisPage: "이 Play를 수정" + viewSource: "소스 보기" + my: "나의 Play" + liked: "좋아요 한 Play" + featured: "인기" + title: "제목" + script: "스크립트" + summary: "설명" _pages: newPage: "페이지 만들기" editPage: "페이지 수정" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index ad7ab9723e..93ed3fa7e2 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -165,7 +165,6 @@ annotation: "Reacties" federation: "Federatie" instances: "Server" registeredAt: "Geregistreerd op" -latestRequestSentAt: "Laatste aanvraag verstuurd" latestRequestReceivedAt: "Laatste aanvraag ontvangen" latestStatus: "Laatste status" storageUsage: "Gebruikte opslagruimte" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 6c3b100885..712c05bb78 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -165,7 +165,6 @@ annotation: "Komentarze" federation: "Federacja" instances: "Instancja" registeredAt: "Zarejestrowano" -latestRequestSentAt: "Ostatnie żądanie wysłano o" latestRequestReceivedAt: "Ostatnie żądanie otrzymano o" latestStatus: "Najnowszy status" storageUsage: "Użycie pamięci" @@ -867,6 +866,8 @@ pushNotificationNotSupported: "Przeglądarka lub instancja nie obsługuje powiad sendPushNotificationReadMessage: "Usuń powiadomienia push po przeczytaniu powiadomień i wiadomości." sendPushNotificationReadMessageCaption: "Chwilowo pojawi się powiadomienie \"{emptyPushNotificationMessage}\". Może wzrosnąć zużycie baterii urządzenia." loggedInAsBot: "Jesteś obecnie zalogowany/a jako bot" +like: "Polub" +show: "Wyświetlanie" _sensitiveMediaDetection: description: "Zmniejsza wysiłek związany z moderacją serwera dzięki automatycznemu rozpoznawaniu zawartości NSFW za pomocą uczenia maszynowego. To nieznacznie zwiększy obciążenie serwera." setSensitiveFlagAutomatically: "Oznacz jako NSFW" @@ -1314,6 +1315,12 @@ _timelines: local: "Lokalne" social: "Społeczność" global: "Globalna" +_play: + viewSource: "Zobacz źródło" + featured: "Wyróżnione" + title: "Tytuł" + script: "Skrypt" + summary: "Opis" _pages: newPage: "Utwórz stronę" editPage: "Edytuj tę stronę" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index d333405316..dd1c2954b7 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -164,7 +164,6 @@ annotation: "Anotação" federation: "União" instances: "Instância" registeredAt: "Registrado em" -latestRequestSentAt: "Enviar a solicitação mais recente" latestRequestReceivedAt: "Recebeu a última solicitação" latestStatus: "Status mais recente" storageUsage: "Uso de armazenamento" diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index 4bb1d4f09a..3c85045e5d 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -164,7 +164,6 @@ annotation: "Adnotări" federation: "Federație" instances: "Instanțe" registeredAt: "Înregistrat în" -latestRequestSentAt: "Ultima cerere trimisă" latestRequestReceivedAt: "Ultima cerere primită" latestStatus: "Ultimul status" storageUsage: "Utilizare stocare" @@ -648,6 +647,7 @@ middle: "Mediu" sent: "Trimite" searchByGoogle: "Caută" file: "Fișiere" +show: "Arată" _email: _follow: title: "te-a urmărit" @@ -691,6 +691,9 @@ _charts: federation: "Federație" _timelines: home: "Acasă" +_play: + script: "Script" + summary: "Descriere" _pages: blocks: image: "Imagini" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 7c256b3bef..553fa9e811 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -164,7 +164,6 @@ annotation: "Описание" federation: "Федерация" instances: "Инстанс" registeredAt: "Первое наблюдение" -latestRequestSentAt: "Последний отправленный запрос" latestRequestReceivedAt: "Последний полученный запрос" latestStatus: "Последний статус" storageUsage: "Использовано" @@ -865,6 +864,8 @@ enableAutoSensitiveDescription: "Если доступно, используйт account: "Учётные записи" windowMaximize: "Развернуть" windowRestore: "Восстановить" +like: "Нравится!" +show: "Отображение" _sensitiveMediaDetection: description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно." setSensitiveFlagAutomatically: "Установить флаг NSFW" @@ -1333,6 +1334,12 @@ _timelines: local: "Местная" social: "Социальная" global: "Всеобщая" +_play: + viewSource: "Просмотр исходника" + featured: "Популярные" + title: "Заголовок" + script: "Скрипт" + summary: "Описание" _pages: newPage: "Создать страницу" editPage: "Править страницу" diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 03a531e63b..3abfd8609d 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -167,7 +167,6 @@ annotation: "Komentáre" federation: "Federácia" instances: "Inštancia" registeredAt: "Registrácia" -latestRequestSentAt: "Posledná odoslaná požiadavka" latestRequestReceivedAt: "Posledná prijatá požiadavka" latestStatus: "Posledný status" storageUsage: "Využité úložisko" @@ -912,6 +911,8 @@ windowRestore: "Obnoviť" caption: "Nadpis" tools: "Nástroje" cannotLoad: "Nedá sa načítať." +like: "Páči sa mi" +show: "Zobraziť" _sensitiveMediaDetection: description: "Strojové učenie sa použije na automatickú detekciu citlivých médií na účely ich moderovania. Mierne sa zvýši zaťaženie servera." sensitivity: "Citlivosť detekcie" @@ -1414,6 +1415,12 @@ _timelines: local: "Lokálne" social: "Sociálne" global: "Globálne" +_play: + viewSource: "Ukázať zdroj" + featured: "Význačné" + title: "Nadpis" + script: "Skript" + summary: "Popis" _pages: newPage: "Vytvoriť novú stránku" editPage: "Upraviť túto stránku" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index b00808d3d0..8b87e36acd 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -2,6 +2,7 @@ _lang_: "Svenska" headlineMisskey: "Ett nätverk kopplat av noter" introMisskey: "Välkommen! Misskey är en öppen och decentraliserad mikrobloggningstjänst.\nSkapa en \"not\" och dela dina tankar med alla runtomkring dig. 📡\nMed \"reaktioner\" kan du snabbt uttrycka dina känslor kring andras noter.👍\nLåt oss utforska en nya värld!🚀" +poweredByMisskeyDescription: "{name} är en tjänst driven av den öppna källkodsplatformen Misskey (benämns \"Misskey instans\")." monthAndDay: "{day}/{month}" search: "Sök" notifications: "Notifikationer" @@ -12,6 +13,7 @@ fetchingAsApObject: "Hämtar från Fediversum..." ok: "OK" gotIt: "Uppfattat!" cancel: "Avbryt" +noThankYou: "Nej tack" enterUsername: "Ange användarnamn" renotedBy: "Omnoterad av {user}" noNotes: "Inga noteringar" @@ -47,11 +49,13 @@ deleteAndEdit: "Radera och ändra" deleteAndEditConfirm: "Är du säker att du vill radera denna not och ändra den? Du kommer förlora alla reaktioner, omnoteringar och svar till den." addToList: "Lägg till i lista" sendMessage: "Skicka ett meddelande" +copyRSS: "Kopiera RSS" copyUsername: "Kopiera användarnamn" searchUser: "Sök användare" reply: "Svara" loadMore: "Ladda mer" showMore: "Visa mer" +showLess: "Stäng" youGotNewFollower: "följde dig" receiveFollowRequest: "Följarförfrågan mottagen" followRequestAccepted: "Följarförfrågan accepterad" @@ -163,7 +167,6 @@ annotation: "Kommentarer" federation: "Federation" instances: "Instanser" registeredAt: "Registrerad på" -latestRequestSentAt: "Senaste förfrågan skickad" latestRequestReceivedAt: "Senaste begäran mottagen" latestStatus: "Senaste status" storageUsage: "Använt lagringsutrymme" @@ -239,6 +242,17 @@ saved: "Sparad" messaging: "Chatt" upload: "Ladda upp" keepOriginalUploading: "Behåll originalbild" +keepOriginalUploadingDescription: "Sparar den originellt uppladdade bilden i sitt i befintliga skick. Om avstängd, kommer en webbversion bli genererad vid uppladdning." +fromDrive: "Från Drive" +fromUrl: "Från en länk" +uploadFromUrl: "Ladda upp från länk" +uploadFromUrlDescription: "Länken av filen du vill ladda upp" +uploadFromUrlRequested: "Uppladdning begärd" +uploadFromUrlMayTakeTime: "Det kan ta tid tills att uppladdningen blir klar." +explore: "Utforska" +messageRead: "Läs" +noMoreHistory: "Det finns ingen mer historik" +startMessaging: "Starta en chatt" nsfw: "Känsligt innehåll" pinnedNotes: "Fästad not" userList: "Listor" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 9dfcf0d2c4..58deeff6f1 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -167,7 +167,6 @@ annotation: "ความคิดเห็น" federation: "เฟดิเวิร์ส" instances: "ตัวอย่าง" registeredAt: "จดทะเบียนที่" -latestRequestSentAt: "ส่งคำขอล่าสุดไปแล้ว" latestRequestReceivedAt: "ได้รับคำขอล่าสุดไปแล้ว" latestStatus: "สถานะล่าสุด" storageUsage: "พื้นที่จัดเก็บข้อมูลที่ใช้ไป" @@ -916,6 +915,9 @@ caption: "รายละเอียด" loggedInAsBot: "ล็อกอินเป็นบอตอยู่ในขณะนี้" tools: "เครื่องมือ" cannotLoad: "ไม่สามารถโหลดได้" +numberOfProfileView: "มุมมองโปรไฟล์" +like: "ชื่นชอบ" +show: "แสดงผล" _sensitiveMediaDetection: description: "ลดความพยายามในการดูแลเซิร์ฟเวอร์ผ่านการจดจำสื่อ NSFW โดยอัตโนมัติผ่านการเรียนรู้ของเครื่อง การทำสิ่งนี้อาจจะเพิ่มภาระบนเซิร์ฟเวอร์เล็กน้อย" sensitivity: "การตรวจจับความไว" @@ -1420,6 +1422,12 @@ _timelines: local: "ในพื้นที่" social: "โซเชี่ยล" global: "ทั่วโลก" +_play: + viewSource: "ดูต้นฉบับ" + featured: "เป็นที่นิยม" + title: "หัวข้อ" + script: "สคริปต์" + summary: "รายละเอียด" _pages: newPage: "สร้างหน้าเพจใหม่" editPage: "แก้ไขหน้าเพจ" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index cb52a86d98..352fb354ee 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -166,7 +166,6 @@ annotation: "Коментарі" federation: "Федіверс" instances: "Інстанс" registeredAt: "Приєднався(лась)" -latestRequestSentAt: "Останній запит надіслано" latestRequestReceivedAt: "Останній запит прийнято" latestStatus: "Останній статус" storageUsage: "Використання простору" @@ -893,6 +892,8 @@ unsubscribePushNotification: "Вимкнути push-сповіщення" windowMaximize: "Розгорнути" windowRestore: "Відновити" caption: "Підпис" +like: "Вподобати" +show: "Відображення" _sensitiveMediaDetection: sensitivity: "Чутливість детектування" setSensitiveFlagAutomatically: "Позначити як NSFW" @@ -1349,6 +1350,12 @@ _timelines: local: "Локальна" social: "Соціальна" global: "Глобальна" +_play: + viewSource: "Переглянути вихідний код" + featured: "Популярні" + title: "Заголовок" + script: "Скрипт" + summary: "Опис" _pages: newPage: "Створити сторінку" editPage: "Редагувати сторінку" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index fdb6ec2647..0070af56f0 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -164,7 +164,6 @@ annotation: "Bình luận" federation: "Liên hợp" instances: "Máy chủ" registeredAt: "Đăng ký vào" -latestRequestSentAt: "Yêu cầu cuối gửi lúc" latestRequestReceivedAt: "Yêu cầu cuối nhận lúc" latestStatus: "Trạng thái cuối cùng" storageUsage: "Dung lượng lưu trữ" @@ -895,6 +894,8 @@ navbar: "Thanh điều hướng" shuffle: "Xáo trộn" account: "Tài khoản của bạn" move: "Di chuyển" +like: "Thích" +show: "Hiển thị" _sensitiveMediaDetection: description: "Giảm nỗ lực kiểm duyệt máy chủ thông qua việc tự động nhận dạng media NSFW thông qua học máy. Điều này sẽ làm tăng một chút áp lực trên máy chủ." sensitivity: "Phát hiện nhạy cảm" @@ -1394,6 +1395,12 @@ _timelines: local: "Máy chủ này" social: "Xã hội" global: "Liên hợp" +_play: + viewSource: "Xem mã nguồn" + featured: "Nổi tiếng" + title: "Tựa đề" + script: "Kịch bản" + summary: "Mô tả" _pages: newPage: "Tạo Trang mới" editPage: "Sửa Trang này" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 80d367a284..7c3efec86c 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -167,7 +167,6 @@ annotation: "注解" federation: "联合" instances: "实例" registeredAt: "初次观测" -latestRequestSentAt: "上次发送的请求" latestRequestReceivedAt: "上次收到的请求" latestStatus: "最后状态" storageUsage: "已用存储" @@ -913,9 +912,14 @@ sendPushNotificationReadMessageCaption: "“{emptyPushNotificationMessage}”的 windowMaximize: "最大化" windowRestore: "还原" caption: "标题" -loggedInAsBot: "已登录的Bot" +loggedInAsBot: "以Bot账户登录" tools: "工具" cannotLoad: "无法加载" +numberOfProfileView: "个人资料展示次数" +like: "点赞!" +unlike: "取消赞" +numberOfLikes: "点赞数" +show: "显示" _sensitiveMediaDetection: description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。" sensitivity: "检测敏感度" @@ -1049,8 +1053,8 @@ _mfm: shakeDescription: "显示摇晃的动画效果。" twitch: "动画(颤抖)" twitchDescription: "显示强烈颤抖的动画效果。" - spin: "动画(回转)" - spinDescription: "显示回转的动画效果。" + spin: "动画(旋转)" + spinDescription: "显示旋转的动画效果。" x2: "大" x2Description: "以大尺寸显示内容。" x3: "非常大" @@ -1315,6 +1319,7 @@ _widgets: jobQueue: "作业队列" serverMetric: "服务器指标" aiscript: "AiScript控制台" + aiscriptApp: "AiScript App" aichan: "小蓝" userList: "用户列表" _userList: @@ -1382,6 +1387,7 @@ _profile: changeBanner: "修改横幅" _exportOrImport: allNotes: "所有帖子" + favoritedNotes: "收藏的帖子" followingList: "关注中" muteList: "屏蔽" blockingList: "拉黑" @@ -1419,6 +1425,21 @@ _timelines: local: "本地" social: "社交" global: "全局" +_play: + new: "创建Play" + edit: "编辑Play" + created: "创建了一个Play" + updated: "更新了Play" + deleted: "删除了Play" + pageSetting: "Play设置" + editThisPage: "编辑此Play" + viewSource: "查看源代码" + my: "我的Play" + liked: "点赞的Play" + featured: "热门" + title: "标题" + script: "脚本" + summary: "描述" _pages: newPage: "创建页面" editPage: "编辑页面" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index a97593e59c..661325d506 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -167,7 +167,6 @@ annotation: "註解" federation: "站台聯邦" instances: "實例" registeredAt: "初次觀測" -latestRequestSentAt: "上次發送的請求" latestRequestReceivedAt: "上次收到的請求" latestStatus: "最後狀態" storageUsage: "已使用容量" @@ -917,6 +916,9 @@ loggedInAsBot: "以機器人帳號登入中" tools: "工具" cannotLoad: "無法載入" numberOfProfileView: "個人檔案檢視次數" +like: "讚" +unlike: "收回讚" +show: "檢視" _sensitiveMediaDetection: description: "您可以使用機器學習自動檢測敏感媒體並將其用於審核。 伺服器的負荷會稍微增加。" sensitivity: "檢測敏感度" @@ -1421,6 +1423,12 @@ _timelines: local: "本地" social: "社群" global: "公開" +_play: + viewSource: "檢視原始碼" + featured: "人氣" + title: "標題" + script: "腳本" + summary: "描述" _pages: newPage: "建立頁面" editPage: "編輯頁面" diff --git a/package.json b/package.json index 1e3bf82a7b..e3d429ec63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.0.0-beta.20", + "version": "13.0.0-beta.27", "codename": "indigo", "repository": { "type": "git", @@ -53,10 +53,10 @@ "devDependencies": { "@types/gulp": "4.0.10", "@types/gulp-rename": "2.0.1", - "@typescript-eslint/eslint-plugin": "5.47.1", - "@typescript-eslint/parser": "5.47.1", + "@typescript-eslint/eslint-plugin": "5.48.0", + "@typescript-eslint/parser": "5.48.0", "cross-env": "7.0.3", - "cypress": "12.2.0", + "cypress": "12.3.0", "eslint": "^8.31.0", "start-server-and-test": "1.15.2", "typescript": "4.9.4" diff --git a/packages/backend/assets/emoji-unknown.png b/packages/backend/assets/emoji-unknown.png new file mode 100644 index 0000000000..ab29bef2b1 Binary files /dev/null and b/packages/backend/assets/emoji-unknown.png differ diff --git a/packages/backend/migration/1672822262496-Flash.js b/packages/backend/migration/1672822262496-Flash.js new file mode 100644 index 0000000000..6c2338fab2 --- /dev/null +++ b/packages/backend/migration/1672822262496-Flash.js @@ -0,0 +1,29 @@ +export class Flash1672822262496 { + name = 'Flash1672822262496' + + async up(queryRunner) { + await queryRunner.query(`CREATE TABLE "flash" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "title" character varying(256) NOT NULL, "summary" character varying(1024) NOT NULL, "userId" character varying(32) NOT NULL, "script" character varying(16384) NOT NULL, "permissions" character varying(256) array NOT NULL DEFAULT '{}', "likedCount" integer NOT NULL DEFAULT '0', CONSTRAINT "PK_0c01a2c1c5f2266942dd1b3fdbc" PRIMARY KEY ("id")); COMMENT ON COLUMN "flash"."createdAt" IS 'The created date of the Flash.'; COMMENT ON COLUMN "flash"."updatedAt" IS 'The updated date of the Flash.'; COMMENT ON COLUMN "flash"."userId" IS 'The ID of author.'`); + await queryRunner.query(`CREATE INDEX "IDX_149d2e44785707548c82999b01" ON "flash" ("createdAt") `); + await queryRunner.query(`CREATE INDEX "IDX_3aa8ea9a8f15214ad91638c0a7" ON "flash" ("updatedAt") `); + await queryRunner.query(`CREATE INDEX "IDX_9b88250fc2fd009b8f1b5623ed" ON "flash" ("userId") `); + await queryRunner.query(`CREATE TABLE "flash_like" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "flashId" character varying(32) NOT NULL, CONSTRAINT "PK_d110109ee310588d63d6183b233" PRIMARY KEY ("id"))`); + await queryRunner.query(`CREATE INDEX "IDX_60c4af1c19a7a75f1592f93b28" ON "flash_like" ("userId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_cfbfeeccb0cbedcd660b17eb07" ON "flash_like" ("userId", "flashId") `); + await queryRunner.query(`ALTER TABLE "flash" ADD CONSTRAINT "FK_9b88250fc2fd009b8f1b5623ed5" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "flash_like" ADD CONSTRAINT "FK_60c4af1c19a7a75f1592f93b287" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "flash_like" ADD CONSTRAINT "FK_6c16fe0e93b7a1951eca624b76a" FOREIGN KEY ("flashId") REFERENCES "flash"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "flash_like" DROP CONSTRAINT "FK_6c16fe0e93b7a1951eca624b76a"`); + await queryRunner.query(`ALTER TABLE "flash_like" DROP CONSTRAINT "FK_60c4af1c19a7a75f1592f93b287"`); + await queryRunner.query(`ALTER TABLE "flash" DROP CONSTRAINT "FK_9b88250fc2fd009b8f1b5623ed5"`); + await queryRunner.query(`DROP INDEX "public"."IDX_cfbfeeccb0cbedcd660b17eb07"`); + await queryRunner.query(`DROP INDEX "public"."IDX_60c4af1c19a7a75f1592f93b28"`); + await queryRunner.query(`DROP TABLE "flash_like"`); + await queryRunner.query(`DROP INDEX "public"."IDX_9b88250fc2fd009b8f1b5623ed"`); + await queryRunner.query(`DROP INDEX "public"."IDX_3aa8ea9a8f15214ad91638c0a7"`); + await queryRunner.query(`DROP INDEX "public"."IDX_149d2e44785707548c82999b01"`); + await queryRunner.query(`DROP TABLE "flash"`); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index d139c1db86..6c1a217b60 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -21,9 +21,9 @@ "@tensorflow/tfjs-node": "4.1.0" }, "dependencies": { - "@bull-board/api": "^4.10.0", - "@bull-board/fastify": "^4.10.0", - "@bull-board/ui": "^4.10.0", + "@bull-board/api": "^4.10.1", + "@bull-board/fastify": "^4.10.1", + "@bull-board/ui": "^4.10.1", "@discordapp/twemoji": "14.0.2", "@fastify/accepts": "4.1.0", "@fastify/cookie": "^8.3.0", @@ -38,10 +38,10 @@ "@peertube/http-signature": "1.7.0", "@sinonjs/fake-timers": "10.0.2", "accepts": "^1.3.8", - "ajv": "8.11.2", + "ajv": "8.12.0", "archiver": "5.3.1", "autwh": "0.1.0", - "aws-sdk": "2.1286.0", + "aws-sdk": "2.1289.0", "bcryptjs": "2.4.3", "blurhash": "2.0.4", "bull": "4.10.2", @@ -109,8 +109,8 @@ "stringz": "2.1.0", "summaly": "2.7.0", "syslog-pro": "git+https://github.com/misskey-dev/SyslogPro#0.2.9-misskey.2", - "systeminformation": "5.16.9", - "tinycolor2": "1.5.1", + "systeminformation": "5.17.1", + "tinycolor2": "1.5.2", "tmp": "0.2.1", "tsc-alias": "1.8.2", "tsconfig-paths": "4.1.2", @@ -128,7 +128,7 @@ }, "devDependencies": { "@redocly/openapi-core": "1.0.0-beta.117", - "@swc/core": "1.3.24", + "@swc/core": "1.3.25", "@swc/jest": "0.2.24", "@types/accepts": "1.3.5", "@types/archiver": "5.3.1", @@ -172,8 +172,8 @@ "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", "@types/ws": "8.5.4", - "@typescript-eslint/eslint-plugin": "5.47.1", - "@typescript-eslint/parser": "5.47.1", + "@typescript-eslint/eslint-plugin": "5.48.0", + "@typescript-eslint/parser": "5.48.0", "cross-env": "7.0.3", "eslint": "8.31.0", "eslint-plugin-import": "2.26.0", diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 7c6d12abf8..2f17fa389a 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -95,6 +95,8 @@ import { UserEntityService } from './entities/UserEntityService.js'; import { UserGroupEntityService } from './entities/UserGroupEntityService.js'; import { UserGroupInvitationEntityService } from './entities/UserGroupInvitationEntityService.js'; import { UserListEntityService } from './entities/UserListEntityService.js'; +import { FlashEntityService } from './entities/FlashEntityService.js'; +import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js'; import { ApAudienceService } from './activitypub/ApAudienceService.js'; import { ApDbResolverService } from './activitypub/ApDbResolverService.js'; import { ApDeliverManagerService } from './activitypub/ApDeliverManagerService.js'; @@ -216,6 +218,8 @@ const $UserEntityService: Provider = { provide: 'UserEntityService', useExisting const $UserGroupEntityService: Provider = { provide: 'UserGroupEntityService', useExisting: UserGroupEntityService }; const $UserGroupInvitationEntityService: Provider = { provide: 'UserGroupInvitationEntityService', useExisting: UserGroupInvitationEntityService }; const $UserListEntityService: Provider = { provide: 'UserListEntityService', useExisting: UserListEntityService }; +const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisting: FlashEntityService }; +const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService }; const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService }; const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService }; @@ -338,6 +342,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserGroupEntityService, UserGroupInvitationEntityService, UserListEntityService, + FlashEntityService, + FlashLikeEntityService, ApAudienceService, ApDbResolverService, ApDeliverManagerService, @@ -455,6 +461,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserGroupEntityService, $UserGroupInvitationEntityService, $UserListEntityService, + $FlashEntityService, + $FlashLikeEntityService, $ApAudienceService, $ApDbResolverService, $ApDeliverManagerService, @@ -572,6 +580,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserGroupEntityService, UserGroupInvitationEntityService, UserListEntityService, + FlashEntityService, + FlashLikeEntityService, ApAudienceService, ApDbResolverService, ApDeliverManagerService, @@ -688,6 +698,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserGroupEntityService, $UserGroupInvitationEntityService, $UserListEntityService, + $FlashEntityService, + $FlashLikeEntityService, $ApAudienceService, $ApDbResolverService, $ApDeliverManagerService, diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts index 667dc9c1fa..b18b7bb2cd 100644 --- a/packages/backend/src/core/PushNotificationService.ts +++ b/packages/backend/src/core/PushNotificationService.ts @@ -47,26 +47,6 @@ function truncateBody(type: T, body: pus return body; } -function truncateUnreadAntennaNote(notification: pushNotificationsTypes['unreadAntennaNote']): pushNotificationsTypes['unreadAntennaNote'] { - if (notification.note) { - return { - ...notification, - note: { - ...notification.note, - // textをgetNoteSummaryしたものに置き換える - text: getNoteSummary(('type' in notification && notification.type === 'renote') ? notification.note.renote as Packed<'Note'> : notification.note), - - cw: undefined, - reply: undefined, - renote: undefined, - user: undefined as any, // 通知を受け取ったユーザーである場合が多いのでこれも捨てる アンテナの場合も不要なのでいらない - }, - }; - } - - return notification; -} - @Injectable() export class PushNotificationService { constructor( diff --git a/packages/backend/src/core/entities/FlashEntityService.ts b/packages/backend/src/core/entities/FlashEntityService.ts new file mode 100644 index 0000000000..61bd18c04f --- /dev/null +++ b/packages/backend/src/core/entities/FlashEntityService.ts @@ -0,0 +1,55 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import { awaitAll } from '@/misc/prelude/await-all.js'; +import type { Packed } from '@/misc/schema.js'; +import type { } from '@/models/entities/Blocking.js'; +import type { User } from '@/models/entities/User.js'; +import type { Flash } from '@/models/entities/Flash.js'; +import { bindThis } from '@/decorators.js'; +import { UserEntityService } from './UserEntityService.js'; + +@Injectable() +export class FlashEntityService { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + @Inject(DI.flashLikesRepository) + private flashLikesRepository: FlashLikesRepository, + + private userEntityService: UserEntityService, + ) { + } + + @bindThis + public async pack( + src: Flash['id'] | Flash, + me?: { id: User['id'] } | null | undefined, + ): Promise> { + const meId = me ? me.id : null; + const flash = typeof src === 'object' ? src : await this.flashsRepository.findOneByOrFail({ id: src }); + + return await awaitAll({ + id: flash.id, + createdAt: flash.createdAt.toISOString(), + updatedAt: flash.updatedAt.toISOString(), + userId: flash.userId, + user: this.userEntityService.pack(flash.user ?? flash.userId, me), // { detail: true } すると無限ループするので注意 + title: flash.title, + summary: flash.summary, + script: flash.script, + likedCount: flash.likedCount, + isLiked: meId ? await this.flashLikesRepository.findOneBy({ flashId: flash.id, userId: meId }).then(x => x != null) : undefined, + }); + } + + @bindThis + public packMany( + flashs: Flash[], + me?: { id: User['id'] } | null | undefined, + ) { + return Promise.all(flashs.map(x => this.pack(x, me))); + } +} + diff --git a/packages/backend/src/core/entities/FlashLikeEntityService.ts b/packages/backend/src/core/entities/FlashLikeEntityService.ts new file mode 100644 index 0000000000..dcf12d53ea --- /dev/null +++ b/packages/backend/src/core/entities/FlashLikeEntityService.ts @@ -0,0 +1,44 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { FlashLikesRepository } from '@/models/index.js'; +import { awaitAll } from '@/misc/prelude/await-all.js'; +import type { Packed } from '@/misc/schema.js'; +import type { } from '@/models/entities/Blocking.js'; +import type { User } from '@/models/entities/User.js'; +import type { FlashLike } from '@/models/entities/FlashLike.js'; +import { bindThis } from '@/decorators.js'; +import { UserEntityService } from './UserEntityService.js'; +import { FlashEntityService } from './FlashEntityService.js'; + +@Injectable() +export class FlashLikeEntityService { + constructor( + @Inject(DI.flashLikesRepository) + private flashLikesRepository: FlashLikesRepository, + + private flashEntityService: FlashEntityService, + ) { + } + + @bindThis + public async pack( + src: FlashLike['id'] | FlashLike, + me?: { id: User['id'] } | null | undefined, + ) { + const like = typeof src === 'object' ? src : await this.flashLikesRepository.findOneByOrFail({ id: src }); + + return { + id: like.id, + flash: await this.flashEntityService.pack(like.flash ?? like.flashId, me), + }; + } + + @bindThis + public packMany( + likes: any[], + me: { id: User['id'] }, + ) { + return Promise.all(likes.map(x => this.pack(x, me))); + } +} + diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index d2a361405f..9719d773ca 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -69,5 +69,7 @@ export const DI = { adsRepository: Symbol('adsRepository'), passwordResetRequestsRepository: Symbol('passwordResetRequestsRepository'), retentionAggregationsRepository: Symbol('retentionAggregationsRepository'), + flashsRepository: Symbol('flashsRepository'), + flashLikesRepository: Symbol('flashLikesRepository'), //#endregion }; diff --git a/packages/backend/src/misc/is-mime-image.ts b/packages/backend/src/misc/is-mime-image.ts index 168a9a7af6..acf5c1ede3 100644 --- a/packages/backend/src/misc/is-mime-image.ts +++ b/packages/backend/src/misc/is-mime-image.ts @@ -3,6 +3,7 @@ import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; const dictionary = { 'safe-file': FILE_TYPE_BROWSERSAFE, 'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/avif', 'image/svg+xml'], + 'sharp-animation-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/svg+xml'], }; export const isMimeImage = (mime: string, type: keyof typeof dictionary): boolean => dictionary[type].includes(mime); diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index e22f0517ca..a5d5a63931 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { User, Note, Announcement, AnnouncementRead, App, NoteFavorite, NoteThreadMuting, NoteReaction, NoteUnread, Notification, Poll, PollVote, UserProfile, UserKeypair, UserPending, AttestationChallenge, UserSecurityKey, UserPublickey, UserList, UserListJoining, UserGroup, UserGroupJoining, UserGroupInvitation, UserNotePining, UserIp, UsedUsername, Following, FollowRequest, Instance, Emoji, DriveFile, DriveFolder, Meta, Muting, Blocking, SwSubscription, Hashtag, AbuseUserReport, RegistrationTicket, AuthSession, AccessToken, Signin, MessagingMessage, Page, PageLike, GalleryPost, GalleryLike, ModerationLog, Clip, ClipNote, Antenna, AntennaNote, PromoNote, PromoRead, Relay, MutedNote, Channel, ChannelFollowing, ChannelNotePining, RegistryItem, Webhook, Ad, PasswordResetRequest, RetentionAggregation } from './index.js'; +import { User, Note, Announcement, AnnouncementRead, App, NoteFavorite, NoteThreadMuting, NoteReaction, NoteUnread, Notification, Poll, PollVote, UserProfile, UserKeypair, UserPending, AttestationChallenge, UserSecurityKey, UserPublickey, UserList, UserListJoining, UserGroup, UserGroupJoining, UserGroupInvitation, UserNotePining, UserIp, UsedUsername, Following, FollowRequest, Instance, Emoji, DriveFile, DriveFolder, Meta, Muting, Blocking, SwSubscription, Hashtag, AbuseUserReport, RegistrationTicket, AuthSession, AccessToken, Signin, MessagingMessage, Page, PageLike, GalleryPost, GalleryLike, ModerationLog, Clip, ClipNote, Antenna, AntennaNote, PromoNote, PromoRead, Relay, MutedNote, Channel, ChannelFollowing, ChannelNotePining, RegistryItem, Webhook, Ad, PasswordResetRequest, RetentionAggregation, FlashLike, Flash } from './index.js'; import type { DataSource } from 'typeorm'; import type { Provider } from '@nestjs/common'; @@ -388,6 +388,18 @@ const $retentionAggregationsRepository: Provider = { inject: [DI.db], }; +const $flashsRepository: Provider = { + provide: DI.flashsRepository, + useFactory: (db: DataSource) => db.getRepository(Flash), + inject: [DI.db], +}; + +const $flashLikesRepository: Provider = { + provide: DI.flashLikesRepository, + useFactory: (db: DataSource) => db.getRepository(FlashLike), + inject: [DI.db], +}; + @Module({ imports: [ ], @@ -456,6 +468,8 @@ const $retentionAggregationsRepository: Provider = { $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, + $flashsRepository, + $flashLikesRepository, ], exports: [ $usersRepository, @@ -522,6 +536,8 @@ const $retentionAggregationsRepository: Provider = { $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, + $flashsRepository, + $flashLikesRepository, ], }) export class RepositoryModule {} diff --git a/packages/backend/src/models/entities/Flash.ts b/packages/backend/src/models/entities/Flash.ts new file mode 100644 index 0000000000..d9a6ac987c --- /dev/null +++ b/packages/backend/src/models/entities/Flash.ts @@ -0,0 +1,60 @@ +import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; +import { id } from '../id.js'; +import { User } from './User.js'; +import { DriveFile } from './DriveFile.js'; + +@Entity() +export class Flash { + @PrimaryColumn(id()) + public id: string; + + @Index() + @Column('timestamp with time zone', { + comment: 'The created date of the Flash.', + }) + public createdAt: Date; + + @Index() + @Column('timestamp with time zone', { + comment: 'The updated date of the Flash.', + }) + public updatedAt: Date; + + @Column('varchar', { + length: 256, + }) + public title: string; + + @Column('varchar', { + length: 1024, + }) + public summary: string; + + @Index() + @Column({ + ...id(), + comment: 'The ID of author.', + }) + public userId: User['id']; + + @ManyToOne(type => User, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public user: User | null; + + @Column('varchar', { + length: 16384, + }) + public script: string; + + @Column('varchar', { + length: 256, array: true, default: '{}', + }) + public permissions: string[]; + + @Column('integer', { + default: 0, + }) + public likedCount: number; +} diff --git a/packages/backend/src/models/entities/FlashLike.ts b/packages/backend/src/models/entities/FlashLike.ts new file mode 100644 index 0000000000..81d39191ca --- /dev/null +++ b/packages/backend/src/models/entities/FlashLike.ts @@ -0,0 +1,33 @@ +import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; +import { id } from '../id.js'; +import { User } from './User.js'; +import { Flash } from './Flash.js'; + +@Entity() +@Index(['userId', 'flashId'], { unique: true }) +export class FlashLike { + @PrimaryColumn(id()) + public id: string; + + @Column('timestamp with time zone') + public createdAt: Date; + + @Index() + @Column(id()) + public userId: User['id']; + + @ManyToOne(type => User, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public user: User | null; + + @Column(id()) + public flashId: Flash['id']; + + @ManyToOne(type => Flash, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public flash: Flash | null; +} diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index ca7a7c9e56..b132475747 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -62,6 +62,8 @@ import { UserSecurityKey } from '@/models/entities/UserSecurityKey.js'; import { Webhook } from '@/models/entities/Webhook.js'; import { Channel } from '@/models/entities/Channel.js'; import { RetentionAggregation } from '@/models/entities/RetentionAggregation.js'; +import { Flash } from '@/models/entities/Flash.js'; +import { FlashLike } from '@/models/entities/FlashLike.js'; import type { Repository } from 'typeorm'; export { @@ -129,6 +131,8 @@ export { Webhook, Channel, RetentionAggregation, + Flash, + FlashLike, }; export type AbuseUserReportsRepository = Repository; @@ -195,3 +199,5 @@ export type UserSecurityKeysRepository = Repository; export type WebhooksRepository = Repository; export type ChannelsRepository = Repository; export type RetentionAggregationsRepository = Repository; +export type FlashsRepository = Repository; +export type FlashLikesRepository = Repository; diff --git a/packages/backend/src/postgre.ts b/packages/backend/src/postgre.ts index 4b4490a0c3..4f6b157d80 100644 --- a/packages/backend/src/postgre.ts +++ b/packages/backend/src/postgre.ts @@ -70,6 +70,8 @@ import { UserSecurityKey } from '@/models/entities/UserSecurityKey.js'; import { Webhook } from '@/models/entities/Webhook.js'; import { Channel } from '@/models/entities/Channel.js'; import { RetentionAggregation } from '@/models/entities/RetentionAggregation.js'; +import { Flash } from '@/models/entities/Flash.js'; +import { FlashLike } from '@/models/entities/FlashLike.js'; import { Config } from '@/config.js'; import MisskeyLogger from '@/logger.js'; @@ -184,6 +186,8 @@ export const entities = [ Webhook, UserIp, RetentionAggregation, + Flash, + FlashLike, ...charts, ]; diff --git a/packages/backend/src/server/MediaProxyServerService.ts b/packages/backend/src/server/MediaProxyServerService.ts index 4491a17545..5b76f15020 100644 --- a/packages/backend/src/server/MediaProxyServerService.ts +++ b/packages/backend/src/server/MediaProxyServerService.ts @@ -79,10 +79,18 @@ export class MediaProxyServerService { const { mime, ext } = await this.fileInfoService.detectType(path); const isConvertibleImage = isMimeImage(mime, 'sharp-convertible-image'); + const isAnimationConvertibleImage = isMimeImage(mime, 'sharp-animation-convertible-image'); let image: IImage; if ('emoji' in request.query && isConvertibleImage) { - const data = await sharp(path, { animated: !('static' in request.query) }) + if (!isAnimationConvertibleImage && !('static' in request.query)) { + image = { + data: fs.readFileSync(path), + ext, + type: mime, + }; + } else { + const data = await sharp(path, { animated: !('static' in request.query) }) .resize({ height: 128, withoutEnlargement: true, @@ -90,11 +98,12 @@ export class MediaProxyServerService { .webp(webpDefault) .toBuffer(); - image = { - data, - ext: 'webp', - type: 'image/webp', - }; + image = { + data, + ext: 'webp', + type: 'image/webp', + }; + } } else if ('static' in request.query && isConvertibleImage) { image = await this.imageProcessingService.convertToWebp(path, 498, 280); } else if ('preview' in request.query && isConvertibleImage) { diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index beb26e43d1..fac8497b5e 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -1,12 +1,11 @@ import cluster from 'node:cluster'; import * as fs from 'node:fs'; -import * as http from 'node:http'; import { Inject, Injectable } from '@nestjs/common'; import Fastify from 'fastify'; import { IsNull } from 'typeorm'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { Config } from '@/config.js'; -import type { UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { EmojisRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { envOption } from '@/env.js'; @@ -39,6 +38,9 @@ export class ServerService { @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, + @Inject(DI.emojisRepository) + private emojisRepository: EmojisRepository, + private userEntityService: UserEntityService, private apiServerService: ApiServerService, private streamingApiServerService: StreamingApiServerService, @@ -77,6 +79,43 @@ export class ServerService { fastify.register(this.nodeinfoServerService.createServer); fastify.register(this.wellKnownServerService.createServer); + fastify.get<{ Params: { path: string }; Querystring: { static?: any; }; }>('/emoji/:path(.*)', async (request, reply) => { + const path = request.params.path; + + if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) { + reply.code(404); + return; + } + + reply.header('Cache-Control', 'public, max-age=86400'); + + const name = path.split('@')[0].replace('.webp', ''); + const host = path.split('@')[1]?.replace('.webp', ''); + + const emoji = await this.emojisRepository.findOneBy({ + // `@.` is the spec of ReactionService.decodeReaction + host: (host == null || host === '.') ? IsNull() : host, + name: name, + }); + + reply.header('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\''); + + if (emoji == null) { + return await reply.redirect('/static-assets/emoji-unknown.png'); + } + + const url = new URL('/proxy/emoji.webp', this.config.url); + // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ) + url.searchParams.set('url', emoji.publicUrl || emoji.originalUrl); + url.searchParams.set('emoji', '1'); + if ('static' in request.query) url.searchParams.set('static', '1'); + + return await reply.redirect( + 301, + url.toString(), + ); + }); + fastify.get<{ Params: { acct: string } }>('/avatar/@:acct', async (request, reply) => { const { username, host } = Acct.parse(request.params.acct); const user = await this.usersRepository.findOne({ diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 32eff7f312..60beca4f47 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -266,6 +266,15 @@ import * as ep___pages_like from './endpoints/pages/like.js'; import * as ep___pages_show from './endpoints/pages/show.js'; import * as ep___pages_unlike from './endpoints/pages/unlike.js'; import * as ep___pages_update from './endpoints/pages/update.js'; +import * as ep___flash_create from './endpoints/flash/create.js'; +import * as ep___flash_delete from './endpoints/flash/delete.js'; +import * as ep___flash_featured from './endpoints/flash/featured.js'; +import * as ep___flash_like from './endpoints/flash/like.js'; +import * as ep___flash_show from './endpoints/flash/show.js'; +import * as ep___flash_unlike from './endpoints/flash/unlike.js'; +import * as ep___flash_update from './endpoints/flash/update.js'; +import * as ep___flash_my from './endpoints/flash/my.js'; +import * as ep___flash_myLikes from './endpoints/flash/my-likes.js'; import * as ep___ping from './endpoints/ping.js'; import * as ep___pinnedUsers from './endpoints/pinned-users.js'; import * as ep___promo_read from './endpoints/promo/read.js'; @@ -587,6 +596,15 @@ const $pages_like: Provider = { provide: 'ep:pages/like', useClass: ep___pages_l const $pages_show: Provider = { provide: 'ep:pages/show', useClass: ep___pages_show.default }; const $pages_unlike: Provider = { provide: 'ep:pages/unlike', useClass: ep___pages_unlike.default }; const $pages_update: Provider = { provide: 'ep:pages/update', useClass: ep___pages_update.default }; +const $flash_create: Provider = { provide: 'ep:flash/create', useClass: ep___flash_create.default }; +const $flash_delete: Provider = { provide: 'ep:flash/delete', useClass: ep___flash_delete.default }; +const $flash_featured: Provider = { provide: 'ep:flash/featured', useClass: ep___flash_featured.default }; +const $flash_like: Provider = { provide: 'ep:flash/like', useClass: ep___flash_like.default }; +const $flash_show: Provider = { provide: 'ep:flash/show', useClass: ep___flash_show.default }; +const $flash_unlike: Provider = { provide: 'ep:flash/unlike', useClass: ep___flash_unlike.default }; +const $flash_update: Provider = { provide: 'ep:flash/update', useClass: ep___flash_update.default }; +const $flash_my: Provider = { provide: 'ep:flash/my', useClass: ep___flash_my.default }; +const $flash_myLikes: Provider = { provide: 'ep:flash/my-likes', useClass: ep___flash_myLikes.default }; const $ping: Provider = { provide: 'ep:ping', useClass: ep___ping.default }; const $pinnedUsers: Provider = { provide: 'ep:pinned-users', useClass: ep___pinnedUsers.default }; const $promo_read: Provider = { provide: 'ep:promo/read', useClass: ep___promo_read.default }; @@ -912,6 +930,15 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $pages_show, $pages_unlike, $pages_update, + $flash_create, + $flash_delete, + $flash_featured, + $flash_like, + $flash_show, + $flash_unlike, + $flash_update, + $flash_my, + $flash_myLikes, $ping, $pinnedUsers, $promo_read, @@ -1231,6 +1258,15 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $pages_show, $pages_unlike, $pages_update, + $flash_create, + $flash_delete, + $flash_featured, + $flash_like, + $flash_show, + $flash_unlike, + $flash_update, + $flash_my, + $flash_myLikes, $ping, $pinnedUsers, $promo_read, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 49dc3b224f..d4f8be5b85 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -265,6 +265,15 @@ import * as ep___pages_like from './endpoints/pages/like.js'; import * as ep___pages_show from './endpoints/pages/show.js'; import * as ep___pages_unlike from './endpoints/pages/unlike.js'; import * as ep___pages_update from './endpoints/pages/update.js'; +import * as ep___flash_create from './endpoints/flash/create.js'; +import * as ep___flash_delete from './endpoints/flash/delete.js'; +import * as ep___flash_featured from './endpoints/flash/featured.js'; +import * as ep___flash_like from './endpoints/flash/like.js'; +import * as ep___flash_show from './endpoints/flash/show.js'; +import * as ep___flash_unlike from './endpoints/flash/unlike.js'; +import * as ep___flash_update from './endpoints/flash/update.js'; +import * as ep___flash_my from './endpoints/flash/my.js'; +import * as ep___flash_myLikes from './endpoints/flash/my-likes.js'; import * as ep___ping from './endpoints/ping.js'; import * as ep___pinnedUsers from './endpoints/pinned-users.js'; import * as ep___promo_read from './endpoints/promo/read.js'; @@ -584,6 +593,15 @@ const eps = [ ['pages/show', ep___pages_show], ['pages/unlike', ep___pages_unlike], ['pages/update', ep___pages_update], + ['flash/create', ep___flash_create], + ['flash/delete', ep___flash_delete], + ['flash/featured', ep___flash_featured], + ['flash/like', ep___flash_like], + ['flash/show', ep___flash_show], + ['flash/unlike', ep___flash_unlike], + ['flash/update', ep___flash_update], + ['flash/my', ep___flash_my], + ['flash/my-likes', ep___flash_myLikes], ['ping', ep___ping], ['pinned-users', ep___pinnedUsers], ['promo/read', ep___promo_read], diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts index 53a37cb691..8a4498d5fa 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts @@ -8,7 +8,7 @@ import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.j export const meta = { tags: ['admin'], - requireCredential: false, + requireCredential: true, requireModerator: true, res: { diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 180887285a..5e2f204661 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -64,8 +64,8 @@ export default class extends Endpoint { case '-followers': query.orderBy('instance.followersCount', 'ASC'); break; case '+caughtAt': query.orderBy('instance.caughtAt', 'DESC'); break; case '-caughtAt': query.orderBy('instance.caughtAt', 'ASC'); break; - case '+latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'DESC'); break; - case '-latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'ASC'); break; + case '+latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'DESC', 'NULLS LAST'); break; + case '-latestRequestReceivedAt': query.orderBy('instance.latestRequestReceivedAt', 'ASC', 'NULLS FIRST'); break; default: query.orderBy('instance.id', 'DESC'); break; } diff --git a/packages/backend/src/server/api/endpoints/flash/create.ts b/packages/backend/src/server/api/endpoints/flash/create.ts new file mode 100644 index 0000000000..a652047d98 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/create.ts @@ -0,0 +1,66 @@ +import ms from 'ms'; +import { Inject, Injectable } from '@nestjs/common'; +import type { DriveFilesRepository, FlashsRepository, PagesRepository } from '@/models/index.js'; +import { IdService } from '@/core/IdService.js'; +import { Page } from '@/models/entities/Page.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { PageEntityService } from '@/core/entities/PageEntityService.js'; +import { DI } from '@/di-symbols.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: true, + + kind: 'write:flash', + + limit: { + duration: ms('1hour'), + max: 10, + }, + + errors: { + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + title: { type: 'string' }, + summary: { type: 'string' }, + script: { type: 'string' }, + permissions: { type: 'array', items: { + type: 'string', + } }, + }, + required: ['title', 'summary', 'script', 'permissions'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + private flashEntityService: FlashEntityService, + private idService: IdService, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.insert({ + id: this.idService.genId(), + userId: me.id, + createdAt: new Date(), + updatedAt: new Date(), + title: ps.title, + summary: ps.summary, + script: ps.script, + permissions: ps.permissions, + }).then(x => this.flashsRepository.findOneByOrFail(x.identifiers[0])); + + return await this.flashEntityService.pack(flash); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/delete.ts b/packages/backend/src/server/api/endpoints/flash/delete.ts new file mode 100644 index 0000000000..e94ede9f68 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/delete.ts @@ -0,0 +1,56 @@ +import { Inject, Injectable } from '@nestjs/common'; +import type { FlashsRepository } from '@/models/index.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flashs'], + + requireCredential: true, + + kind: 'write:flash', + + errors: { + noSuchFlash: { + message: 'No such flash.', + code: 'NO_SUCH_FLASH', + id: 'de1623ef-bbb3-4289-a71e-14cfa83d9740', + }, + + accessDenied: { + message: 'Access denied.', + code: 'ACCESS_DENIED', + id: '1036ad7b-9f92-4fff-89c3-0e50dc941704', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + flashId: { type: 'string', format: 'misskey:id' }, + }, + required: ['flashId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); + if (flash == null) { + throw new ApiError(meta.errors.noSuchFlash); + } + if (flash.userId !== me.id) { + throw new ApiError(meta.errors.accessDenied); + } + + await this.flashsRepository.delete(flash.id); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/featured.ts b/packages/backend/src/server/api/endpoints/flash/featured.ts new file mode 100644 index 0000000000..570aef96d2 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/featured.ts @@ -0,0 +1,48 @@ +import { Inject, Injectable } from '@nestjs/common'; +import type { FlashsRepository } from '@/models/index.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; +import { DI } from '@/di-symbols.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: false, + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + ref: 'Flash', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + private flashEntityService: FlashEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + const query = this.flashsRepository.createQueryBuilder('flash') + .andWhere('flash.likedCount > 0') + .orderBy('flash.likedCount', 'DESC'); + + const flashs = await query.take(10).getMany(); + + return await this.flashEntityService.packMany(flashs, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/like.ts b/packages/backend/src/server/api/endpoints/flash/like.ts new file mode 100644 index 0000000000..5581b8ec60 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/like.ts @@ -0,0 +1,87 @@ +import { Inject, Injectable } from '@nestjs/common'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import { IdService } from '@/core/IdService.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: true, + + kind: 'write:flash-likes', + + errors: { + noSuchFlash: { + message: 'No such flash.', + code: 'NO_SUCH_FLASH', + id: 'c07c1491-9161-4c5c-9d75-01906f911f73', + }, + + yourFlash: { + message: 'You cannot like your flash.', + code: 'YOUR_FLASH', + id: '3fd8a0e7-5955-4ba9-85bb-bf3e0c30e13b', + }, + + alreadyLiked: { + message: 'The flash has already been liked.', + code: 'ALREADY_LIKED', + id: '010065cf-ad43-40df-8067-abff9f4686e3', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + flashId: { type: 'string', format: 'misskey:id' }, + }, + required: ['flashId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + @Inject(DI.flashLikesRepository) + private flashLikesRepository: FlashLikesRepository, + + private idService: IdService, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); + if (flash == null) { + throw new ApiError(meta.errors.noSuchFlash); + } + + if (flash.userId === me.id) { + throw new ApiError(meta.errors.yourFlash); + } + + // if already liked + const exist = await this.flashLikesRepository.findOneBy({ + flashId: flash.id, + userId: me.id, + }); + + if (exist != null) { + throw new ApiError(meta.errors.alreadyLiked); + } + + // Create like + await this.flashLikesRepository.insert({ + id: this.idService.genId(), + createdAt: new Date(), + flashId: flash.id, + userId: me.id, + }); + + this.flashsRepository.increment({ id: flash.id }, 'likedCount', 1); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/my-likes.ts b/packages/backend/src/server/api/endpoints/flash/my-likes.ts new file mode 100644 index 0000000000..f7716ea74a --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/my-likes.ts @@ -0,0 +1,68 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { FlashLikesRepository } from '@/models/index.js'; +import { QueryService } from '@/core/QueryService.js'; +import { FlashLikeEntityService } from '@/core/entities/FlashLikeEntityService.js'; +import { DI } from '@/di-symbols.js'; + +export const meta = { + tags: ['account', 'flash'], + + requireCredential: true, + + kind: 'read:flash-likes', + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + flash: { + type: 'object', + optional: false, nullable: false, + ref: 'Flash', + }, + }, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashLikesRepository) + private flashLikesRepository: FlashLikesRepository, + + private flashLikeEntityService: FlashLikeEntityService, + private queryService: QueryService, + ) { + super(meta, paramDef, async (ps, me) => { + const query = this.queryService.makePaginationQuery(this.flashLikesRepository.createQueryBuilder('like'), ps.sinceId, ps.untilId) + .andWhere('like.userId = :meId', { meId: me.id }) + .leftJoinAndSelect('like.flash', 'flash'); + + const likes = await query + .take(ps.limit) + .getMany(); + + return this.flashLikeEntityService.packMany(likes, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/my.ts b/packages/backend/src/server/api/endpoints/flash/my.ts new file mode 100644 index 0000000000..baed7f000f --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/my.ts @@ -0,0 +1,57 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { FlashsRepository } from '@/models/index.js'; +import { QueryService } from '@/core/QueryService.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; +import { DI } from '@/di-symbols.js'; + +export const meta = { + tags: ['account', 'flash'], + + requireCredential: true, + + kind: 'read:flash', + + res: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + ref: 'Flash', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + private flashEntityService: FlashEntityService, + private queryService: QueryService, + ) { + super(meta, paramDef, async (ps, me) => { + const query = this.queryService.makePaginationQuery(this.flashsRepository.createQueryBuilder('flash'), ps.sinceId, ps.untilId) + .andWhere('flash.userId = :meId', { meId: me.id }); + + const flashs = await query + .take(ps.limit) + .getMany(); + + return await this.flashEntityService.packMany(flashs); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/show.ts b/packages/backend/src/server/api/endpoints/flash/show.ts new file mode 100644 index 0000000000..48114c5a60 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/show.ts @@ -0,0 +1,60 @@ +import { IsNull } from 'typeorm'; +import { Inject, Injectable } from '@nestjs/common'; +import type { UsersRepository, FlashsRepository } from '@/models/index.js'; +import type { Flash } from '@/models/entities/Flash.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flashs'], + + requireCredential: false, + + res: { + type: 'object', + optional: false, nullable: false, + ref: 'Flash', + }, + + errors: { + noSuchFlash: { + message: 'No such flash.', + code: 'NO_SUCH_FLASH', + id: 'f0d34a1a-d29a-401d-90ba-1982122b5630', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + flashId: { type: 'string', format: 'misskey:id' }, + }, + required: ['flashId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + private flashEntityService: FlashEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); + + if (flash == null) { + throw new ApiError(meta.errors.noSuchFlash); + } + + return await this.flashEntityService.pack(flash, me); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/unlike.ts b/packages/backend/src/server/api/endpoints/flash/unlike.ts new file mode 100644 index 0000000000..b994f5d347 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/unlike.ts @@ -0,0 +1,68 @@ +import { Inject, Injectable } from '@nestjs/common'; +import type { FlashsRepository, FlashLikesRepository } from '@/models/index.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: true, + + kind: 'write:flash-likes', + + errors: { + noSuchFlash: { + message: 'No such flash.', + code: 'NO_SUCH_FLASH', + id: 'afe8424a-a69e-432d-a5f2-2f0740c62410', + }, + + notLiked: { + message: 'You have not liked that flash.', + code: 'NOT_LIKED', + id: '755f25a7-9871-4f65-9f34-51eaad9ae0ac', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + flashId: { type: 'string', format: 'misskey:id' }, + }, + required: ['flashId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + @Inject(DI.flashLikesRepository) + private flashLikesRepository: FlashLikesRepository, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); + if (flash == null) { + throw new ApiError(meta.errors.noSuchFlash); + } + + const exist = await this.flashLikesRepository.findOneBy({ + flashId: flash.id, + userId: me.id, + }); + + if (exist == null) { + throw new ApiError(meta.errors.notLiked); + } + + // Delete like + await this.flashLikesRepository.delete(exist.id); + + this.flashsRepository.decrement({ id: flash.id }, 'likedCount', 1); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/flash/update.ts b/packages/backend/src/server/api/endpoints/flash/update.ts new file mode 100644 index 0000000000..9ab17a61e8 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/update.ts @@ -0,0 +1,78 @@ +import ms from 'ms'; +import { Not } from 'typeorm'; +import { Inject, Injectable } from '@nestjs/common'; +import type { FlashsRepository, DriveFilesRepository } from '@/models/index.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../error.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: true, + + kind: 'write:flash', + + limit: { + duration: ms('1hour'), + max: 300, + }, + + errors: { + noSuchFlash: { + message: 'No such flash.', + code: 'NO_SUCH_FLASH', + id: '611e13d2-309e-419a-a5e4-e0422da39b02', + }, + + accessDenied: { + message: 'Access denied.', + code: 'ACCESS_DENIED', + id: '08e60c88-5948-478e-a132-02ec701d67b2', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + flashId: { type: 'string', format: 'misskey:id' }, + title: { type: 'string' }, + summary: { type: 'string' }, + script: { type: 'string' }, + permissions: { type: 'array', items: { + type: 'string', + } }, + }, + required: ['flashId', 'title', 'summary', 'script', 'permissions'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + @Inject(DI.driveFilesRepository) + private driveFilesRepository: DriveFilesRepository, + ) { + super(meta, paramDef, async (ps, me) => { + const flash = await this.flashsRepository.findOneBy({ id: ps.flashId }); + if (flash == null) { + throw new ApiError(meta.errors.noSuchFlash); + } + if (flash.userId !== me.id) { + throw new ApiError(meta.errors.accessDenied); + } + + await this.flashsRepository.update(flash.id, { + updatedAt: new Date(), + title: ps.title, + summary: ps.summary, + script: ps.script, + permissions: ps.permissions, + }); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts index 41a11d1a31..d27990f7e1 100644 --- a/packages/backend/src/server/api/endpoints/pages/like.ts +++ b/packages/backend/src/server/api/endpoints/pages/like.ts @@ -28,7 +28,7 @@ export const meta = { alreadyLiked: { message: 'The page has already been liked.', code: 'ALREADY_LIKED', - id: 'cc98a8a2-0dc3-4123-b198-62c71df18ed3', + id: 'd4c1edbe-7da2-4eae-8714-1acfd2d63941', }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index 4db0f80b26..35b402ec56 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -111,7 +111,7 @@ export default class extends Endpoint { updatedAt: new Date(), title: ps.title, name: ps.name === undefined ? page.name : ps.name, - summary: ps.name === undefined ? page.summary : ps.summary, + summary: ps.summary === undefined ? page.summary : ps.summary, content: ps.content, variables: ps.variables, script: ps.script, diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 7ef178403b..c69975fd79 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -1,6 +1,5 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; -import { PathOrFileDescriptor, readFileSync } from 'node:fs'; import { Inject, Injectable } from '@nestjs/common'; import { createBullBoard } from '@bull-board/api'; import { BullAdapter } from '@bull-board/api/bullAdapter.js'; @@ -26,9 +25,10 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; -import type { ChannelsRepository, ClipsRepository, EmojisRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { ChannelsRepository, ClipsRepository, EmojisRepository, FlashsRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import { deepClone } from '@/misc/clone.js'; import { bindThis } from '@/decorators.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import manifest from './manifest.json' assert { type: 'json' }; import { FeedService } from './FeedService.js'; import { UrlPreviewService } from './UrlPreviewService.js'; @@ -70,9 +70,10 @@ export class ClientServerService { @Inject(DI.pagesRepository) private pagesRepository: PagesRepository, - @Inject(DI.emojisRepository) - private emojisRepository: EmojisRepository, + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + private flashEntityService: FlashEntityService, private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, private pageEntityService: PageEntityService, @@ -220,44 +221,6 @@ export class ClientServerService { return reply.sendFile('/apple-touch-icon.png', staticAssets); }); - fastify.get<{ Params: { path: string }; Querystring: { static?: any; }; }>('/emoji/:path(.*)', async (request, reply) => { - const path = request.params.path; - - if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) { - reply.code(404); - return; - } - - reply.header('Cache-Control', 'public, max-age=86400'); - - const name = path.split('@')[0].replace('.webp', ''); - const host = path.split('@')[1]?.replace('.webp', ''); - - const emoji = await this.emojisRepository.findOneBy({ - // `@.` is the spec of ReactionService.decodeReaction - host: (host == null || host === '.') ? IsNull() : host, - name: name, - }); - - if (emoji == null) { - reply.code(404); - return; - } - - reply.header('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\''); - - const url = new URL('/proxy/emoji.webp', this.config.url); - // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ) - url.searchParams.set('url', emoji.publicUrl || emoji.originalUrl); - url.searchParams.set('emoji', '1'); - if ('static' in request.query) url.searchParams.set('static', '1'); - - return await reply.redirect( - 301, - url.toString(), - ); - }); - fastify.get<{ Params: { path: string } }>('/fluent-emoji/:path(.*)', async (request, reply) => { const path = request.params.path; @@ -352,7 +315,7 @@ export class ClientServerService { const name = meta.name || 'Misskey'; let content = ''; content += ''; - content += `${name} Search`; + content += `${name}`; content += `${name} Search`; content += 'UTF-8'; content += `${this.config.url}/favicon.ico`; @@ -545,6 +508,30 @@ export class ClientServerService { } }); + // Flash + fastify.get<{ Params: { id: string; } }>('/play/:id', async (request, reply) => { + const flash = await this.flashsRepository.findOneBy({ + id: request.params.id, + }); + + if (flash) { + const _flash = await this.flashEntityService.pack(flash); + const profile = await this.userProfilesRepository.findOneByOrFail({ userId: flash.userId }); + const meta = await this.metaService.fetch(); + reply.header('Cache-Control', 'public, max-age=15'); + return await reply.view('flash', { + flash: _flash, + profile, + avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: flash.userId })), + instanceName: meta.name ?? 'Misskey', + icon: meta.iconUrl, + themeColor: meta.themeColor, + }); + } else { + return await renderBase(reply); + } + }); + // Clip // TODO: 非publicなclipのハンドリング fastify.get<{ Params: { clip: string; } }>('/clips/:clip', async (request, reply) => { diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index b472cff899..b27bbcbce0 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -31,7 +31,7 @@ html link(rel='icon' href= icon || '/favicon.ico') link(rel='apple-touch-icon' href= icon || '/apple-touch-icon.png') link(rel='manifest' href='/manifest.json') - link(rel='search' type='application/opensearchdescription+xml' title=((title || "Misskey") + " Search") href=`${url}/opensearch.xml`) + link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`) link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg') diff --git a/packages/backend/src/server/web/views/flash.pug b/packages/backend/src/server/web/views/flash.pug new file mode 100644 index 0000000000..5166855ea2 --- /dev/null +++ b/packages/backend/src/server/web/views/flash.pug @@ -0,0 +1,31 @@ +extends ./base + +block vars + - const user = flash.user; + - const title = flash.title; + - const url = `${config.url}/play/${flash.id}`; + +block title + = `${title} | ${instanceName}` + +block desc + meta(name='description' content= flash.summary) + +block og + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= flash.summary) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) + +block meta + if profile.noCrawle + meta(name='robots' content='noindex') + + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:flash-id' content=flash.id) + + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 2506e8e9d3..234490e506 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -11,7 +11,7 @@ "@rollup/plugin-alias": "4.0.2", "@rollup/plugin-json": "6.0.0", "@rollup/pluginutils": "5.0.2", - "@syuilo/aiscript": "0.12.0", + "@syuilo/aiscript": "0.12.2", "@tabler/icons": "^1.118.0", "@vitejs/plugin-vue": "4.0.0", "@vue/compiler-sfc": "3.2.45", @@ -20,7 +20,8 @@ "blurhash": "2.0.4", "broadcast-channel": "4.19.1", "browser-image-resizer": "git+https://github.com/misskey-dev/browser-image-resizer#v2.2.1-misskey.3", - "chart.js": "4.1.1", + "canvas-confetti": "^1.6.0", + "chart.js": "4.1.2", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-matrix": "^1.3.0", "chartjs-plugin-gradient": "0.6.1", @@ -35,7 +36,7 @@ "insert-text-at-cursor": "0.3.0", "is-file-animated": "1.0.2", "json5": "2.2.3", - "katex": "0.15.6", + "katex": "0.16.4", "matter-js": "0.18.0", "mfm-js": "0.23.0", "misskey-js": "0.0.14", @@ -44,7 +45,7 @@ "punycode": "2.1.1", "querystring": "0.2.1", "rndstr": "1.0.0", - "rollup": "3.9.0", + "rollup": "3.9.1", "s-age": "1.1.2", "sanitize-html": "^2.8.1", "sass": "1.57.1", @@ -55,14 +56,14 @@ "textarea-caret": "3.1.0", "three": "0.148.0", "throttle-debounce": "5.0.0", - "tinycolor2": "1.5.1", + "tinycolor2": "1.5.2", "tsc-alias": "1.8.2", "tsconfig-paths": "4.1.2", "twemoji-parser": "14.0.0", "typescript": "4.9.4", "uuid": "9.0.0", "vanilla-tilt": "1.8.0", - "vite": "4.0.3", + "vite": "4.0.4", "vue": "3.2.45", "vue-prism-editor": "2.0.0-alpha.2", "vuedraggable": "next" @@ -72,7 +73,7 @@ "@types/glob": "8.0.0", "@types/gulp": "4.0.10", "@types/gulp-rename": "2.0.1", - "@types/katex": "0.14.0", + "@types/katex": "0.16.0", "@types/matter-js": "0.18.2", "@types/punycode": "2.1.0", "@types/sanitize-html": "^2.8.0", @@ -82,16 +83,16 @@ "@types/uuid": "9.0.0", "@types/websocket": "1.0.5", "@types/ws": "8.5.4", - "@typescript-eslint/eslint-plugin": "5.47.1", - "@typescript-eslint/parser": "5.47.1", + "@typescript-eslint/eslint-plugin": "5.48.0", + "@typescript-eslint/parser": "5.48.0", "@vue/runtime-core": "3.2.45", "cross-env": "7.0.3", - "cypress": "12.2.0", + "cypress": "12.3.0", "eslint": "8.31.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-vue": "9.8.0", "start-server-and-test": "1.15.2", "vue-eslint-parser": "^9.1.0", - "vue-tsc": "^1.0.19" + "vue-tsc": "^1.0.22" } } diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index 0e991cdfb5..93916ccf2f 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -6,12 +6,13 @@ import { del, get, set } from '@/scripts/idb-proxy'; import { apiUrl } from '@/config'; import { waiting, api, popup, popupMenu, success, alert } from '@/os'; import { unisonReload, reloadChannel } from '@/scripts/unison-reload'; +import { miLocalStorage } from './local-storage'; // TODO: 他のタブと永続化されたstateを同期 type Account = misskey.entities.MeDetailed; -const accountData = localStorage.getItem('account'); +const accountData = miLocalStorage.getItem('account'); // TODO: 外部からはreadonlyに export const $i = accountData ? reactive(JSON.parse(accountData) as Account) : null; @@ -21,7 +22,7 @@ export const iAmAdmin = $i != null && $i.isAdmin; export async function signout() { waiting(); - localStorage.removeItem('account'); + miLocalStorage.removeItem('account'); await removeAccount($i.id); @@ -119,7 +120,7 @@ export function updateAccount(accountData) { for (const [key, value] of Object.entries(accountData)) { $i[key] = value; } - localStorage.setItem('account', JSON.stringify($i)); + miLocalStorage.setItem('account', JSON.stringify($i)); } export function refreshAccount() { @@ -130,7 +131,7 @@ export async function login(token: Account['token'], redirect?: string) { waiting(); if (_DEV_) console.log('logging as token ', token); const me = await fetchAccount(token); - localStorage.setItem('account', JSON.stringify(me)); + miLocalStorage.setItem('account', JSON.stringify(me)); document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う await addAccount(me.id, token); diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue index c065792882..96f58269c4 100644 --- a/packages/frontend/src/components/MkAbuseReport.vue +++ b/packages/frontend/src/components/MkAbuseReport.vue @@ -1,5 +1,5 @@ + + diff --git a/packages/frontend/src/components/MkDriveSelectDialog.vue b/packages/frontend/src/components/MkDriveSelectDialog.vue index 6a96e758fa..8d2b19c013 100644 --- a/packages/frontend/src/components/MkDriveSelectDialog.vue +++ b/packages/frontend/src/components/MkDriveSelectDialog.vue @@ -1,5 +1,5 @@ - + - diff --git a/packages/frontend/src/components/MkFileCaptionEditWindow.vue b/packages/frontend/src/components/MkFileCaptionEditWindow.vue index b3bd194dc3..95eef45df0 100644 --- a/packages/frontend/src/components/MkFileCaptionEditWindow.vue +++ b/packages/frontend/src/components/MkFileCaptionEditWindow.vue @@ -1,5 +1,5 @@ - + + + diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue index 5a406c8635..dc10c7d3f3 100644 --- a/packages/frontend/src/components/MkFolder.vue +++ b/packages/frontend/src/components/MkFolder.vue @@ -25,8 +25,9 @@ diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue index 2c0a30a888..b92e6d2360 100644 --- a/packages/frontend/src/components/MkPagination.vue +++ b/packages/frontend/src/components/MkPagination.vue @@ -14,14 +14,14 @@
-
+
{{ i18n.ts.loadMore }}
-
+
{{ i18n.ts.loadMore }} diff --git a/packages/frontend/src/components/MkPlusOneEffect.vue b/packages/frontend/src/components/MkPlusOneEffect.vue index 5c85d2b3e5..3e4f2059fd 100644 --- a/packages/frontend/src/components/MkPlusOneEffect.vue +++ b/packages/frontend/src/components/MkPlusOneEffect.vue @@ -1,14 +1,18 @@ diff --git a/packages/frontend/src/components/form/split.vue b/packages/frontend/src/components/form/split.vue index 301a8a84e5..3cee41e3d6 100644 --- a/packages/frontend/src/components/form/split.vue +++ b/packages/frontend/src/components/form/split.vue @@ -1,5 +1,5 @@ diff --git a/packages/frontend/src/components/global/MkSpacer.vue b/packages/frontend/src/components/global/MkSpacer.vue index 1ddb230bd6..78e9a1a9c2 100644 --- a/packages/frontend/src/components/global/MkSpacer.vue +++ b/packages/frontend/src/components/global/MkSpacer.vue @@ -38,13 +38,13 @@ const forceSpacerMin = inject('forceSpacerMin', false) || deviceKind === 'smartp container-type: inline-size; } -@container (max-width: 360px) { +@container (max-width: 450px) { .root { padding: v-bind('props.marginMin + "px"'); } } -@container (min-width: 361px) { +@container (min-width: 451px) { .root { padding: v-bind('props.marginMax + "px"'); } diff --git a/packages/frontend/src/components/global/MkTime.vue b/packages/frontend/src/components/global/MkTime.vue index 0bbb0f5399..66c0bd5135 100644 --- a/packages/frontend/src/components/global/MkTime.vue +++ b/packages/frontend/src/components/global/MkTime.vue @@ -36,22 +36,21 @@ const relative = $computed(() => { i18n.ts._ago.future); }); -function tick() { - // TODO: パフォーマンス向上のため、このコンポーネントが画面内に表示されている場合のみ更新する - now = new Date(); - - tickId = window.setTimeout(() => { - window.requestAnimationFrame(tick); - }, 10000); -} - let tickId: number; +function tick() { + now = new Date(); + const ago = (now.getTime() - _time.getTime()) / 1000/*ms*/; + const next = ago < 60 ? 10000 : ago < 3600 ? 60000 : 180000; + + tickId = window.setTimeout(tick, next); +} + if (props.mode === 'relative' || props.mode === 'detail') { - tickId = window.requestAnimationFrame(tick); + tick(); onUnmounted(() => { - window.cancelAnimationFrame(tickId); + window.clearTimeout(tickId); }); } diff --git a/packages/frontend/src/components/page/page.number-input.vue b/packages/frontend/src/components/page/page.number-input.vue index 50cf6d0770..4c5aae1040 100644 --- a/packages/frontend/src/components/page/page.number-input.vue +++ b/packages/frontend/src/components/page/page.number-input.vue @@ -8,7 +8,7 @@ + + diff --git a/packages/frontend/src/pages/flash/flash-index.vue b/packages/frontend/src/pages/flash/flash-index.vue new file mode 100644 index 0000000000..fb377be579 --- /dev/null +++ b/packages/frontend/src/pages/flash/flash-index.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue new file mode 100644 index 0000000000..c1afaa2d29 --- /dev/null +++ b/packages/frontend/src/pages/flash/flash.vue @@ -0,0 +1,293 @@ + + + + + + + diff --git a/packages/frontend/src/pages/gallery/edit.vue b/packages/frontend/src/pages/gallery/edit.vue index c8111d7890..f47632c85f 100644 --- a/packages/frontend/src/pages/gallery/edit.vue +++ b/packages/frontend/src/pages/gallery/edit.vue @@ -3,28 +3,28 @@ - + - + - + - +
{{ file.name }}
- {{ i18n.ts.attachFile }} + {{ i18n.ts.attachFile }}
- {{ i18n.ts.markAsSensitive }} + {{ i18n.ts.markAsSensitive }} - {{ i18n.ts.save }} - {{ i18n.ts.publish }} + {{ i18n.ts.save }} + {{ i18n.ts.publish }} - {{ i18n.ts.delete }} + {{ i18n.ts.delete }}
@@ -32,10 +32,10 @@ + + diff --git a/packages/frontend/src/pages/user/activity.pv.vue b/packages/frontend/src/pages/user/activity.pv.vue index 7715b66673..d74b641dac 100644 --- a/packages/frontend/src/pages/user/activity.pv.vue +++ b/packages/frontend/src/pages/user/activity.pv.vue @@ -11,7 +11,6 @@ diff --git a/packages/frontend/src/widgets/federation.vue b/packages/frontend/src/widgets/federation.vue index a701ca5673..23f7cd4411 100644 --- a/packages/frontend/src/widgets/federation.vue +++ b/packages/frontend/src/widgets/federation.vue @@ -8,7 +8,7 @@
- {{ instance.host }} + {{ instance.host }}

{{ instance.softwareName || '?' }} {{ instance.softwareVersion }}

diff --git a/packages/frontend/src/widgets/index.ts b/packages/frontend/src/widgets/index.ts index 39826f13c8..3966649da4 100644 --- a/packages/frontend/src/widgets/index.ts +++ b/packages/frontend/src/widgets/index.ts @@ -22,6 +22,7 @@ export default function(app: App) { app.component('MkwInstanceCloud', defineAsyncComponent(() => import('./instance-cloud.vue'))); app.component('MkwButton', defineAsyncComponent(() => import('./button.vue'))); app.component('MkwAiscript', defineAsyncComponent(() => import('./aiscript.vue'))); + app.component('MkwAiscriptApp', defineAsyncComponent(() => import('./aiscript-app.vue'))); app.component('MkwAichan', defineAsyncComponent(() => import('./aichan.vue'))); app.component('MkwUserList', defineAsyncComponent(() => import('./user-list.vue'))); } @@ -48,6 +49,7 @@ export const widgets = [ 'jobQueue', 'button', 'aiscript', + 'aiscriptApp', 'aichan', 'userList', ]; diff --git a/packages/frontend/src/widgets/rss-ticker.vue b/packages/frontend/src/widgets/rss-ticker.vue index c2d6dd2873..37672e13cf 100644 --- a/packages/frontend/src/widgets/rss-ticker.vue +++ b/packages/frontend/src/widgets/rss-ticker.vue @@ -3,13 +3,15 @@ -
- -
- +
+
+ +
+
+ - - {{ item.title }} + + {{ item.title }} @@ -19,14 +21,14 @@ - diff --git a/packages/frontend/src/widgets/rss.vue b/packages/frontend/src/widgets/rss.vue index c0338c8e47..554413cd1e 100644 --- a/packages/frontend/src/widgets/rss.vue +++ b/packages/frontend/src/widgets/rss.vue @@ -5,19 +5,24 @@
-
- {{ item.title }} +
+ +
{{ i18n.ts.nothing }}
+
+
- diff --git a/scripts/clean-all.js b/scripts/clean-all.js index c65a1c3a32..563b6bc922 100644 --- a/scripts/clean-all.js +++ b/scripts/clean-all.js @@ -1,3 +1,4 @@ +const { execSync } = require('child_process'); const fs = require('fs'); (async () => { @@ -12,5 +13,9 @@ const fs = require('fs'); fs.rmSync(__dirname + '/../built', { recursive: true, force: true }); fs.rmSync(__dirname + '/../node_modules', { recursive: true, force: true }); - fs.rmSync(__dirname + '/../.yarn/cache', { recursive: true, force: true }); + + execSync('yarn cache clean --all', { + cwd: __dirname + '/../', + stdio: 'inherit', + }); })(); diff --git a/yarn.lock b/yarn.lock index 9eaf29f1b3..2fc62d0878 100644 --- a/yarn.lock +++ b/yarn.lock @@ -417,34 +417,34 @@ __metadata: languageName: node linkType: hard -"@bull-board/api@npm:4.10.0, @bull-board/api@npm:^4.10.0": - version: 4.10.0 - resolution: "@bull-board/api@npm:4.10.0" +"@bull-board/api@npm:4.10.1, @bull-board/api@npm:^4.10.1": + version: 4.10.1 + resolution: "@bull-board/api@npm:4.10.1" dependencies: redis-info: ^3.0.8 - checksum: 886ee7955283056fd40b75bfa63bd174c06bedd8086a3a54804548015ebfc1ba9ff8ec5e76ed2f0a3beeda4b5b5ab32531f35cd77cd6ab5ed7e4978fe426ae84 + checksum: 32c9e88df3dd73f513f8d917df3896a58f182417d75bf43d3446c00cb3c0d17a27ef26a6da40d2304350a614ed1be8d1de30002184a03c6c334c6f84faa85a83 languageName: node linkType: hard -"@bull-board/fastify@npm:^4.10.0": - version: 4.10.0 - resolution: "@bull-board/fastify@npm:4.10.0" +"@bull-board/fastify@npm:^4.10.1": + version: 4.10.1 + resolution: "@bull-board/fastify@npm:4.10.1" dependencies: - "@bull-board/api": 4.10.0 - "@bull-board/ui": 4.10.0 + "@bull-board/api": 4.10.1 + "@bull-board/ui": 4.10.1 "@fastify/static": ^6.4.0 "@fastify/view": ^7.0.0 ejs: ^3.1.8 - checksum: c71d52a49bae6025a1ef4bd3b76bf6a15fb12d8e52f89128c6a9bbbd0e71195d55b3e9b7ccb4608476ac99befe334c6d7fbbea9a7227662047ad7e30ea9174a1 + checksum: e6a0597fc682ff89a31a09d61861f0ec84941538a1ca10f55ffaef1f53b8989c16923725515b1e74112ea169a74fb357765a64e7e75d78d1628edb586958bc0f languageName: node linkType: hard -"@bull-board/ui@npm:4.10.0, @bull-board/ui@npm:^4.10.0": - version: 4.10.0 - resolution: "@bull-board/ui@npm:4.10.0" +"@bull-board/ui@npm:4.10.1, @bull-board/ui@npm:^4.10.1": + version: 4.10.1 + resolution: "@bull-board/ui@npm:4.10.1" dependencies: - "@bull-board/api": 4.10.0 - checksum: 0322523c486ebeae7c31af26e286ce253ed01f09808b4370bde12ba19ac1b0cc888ecc099dc6dba74a63e65b1b14664dd216f1f9880dc893396b24a7a4b1ea90 + "@bull-board/api": 4.10.1 + checksum: b221444ccd836d26a66501b5cd1702710f65ab7a5f0f6d92a0168b91ffde11a75a41ef334ea77a7f0c2b1caa7b5e136fe489242028eca1a5c7ed11ace24365d9 languageName: node linkType: hard @@ -1850,90 +1850,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-darwin-arm64@npm:1.3.24" +"@swc/core-darwin-arm64@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-darwin-arm64@npm:1.3.25" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-darwin-x64@npm:1.3.24" +"@swc/core-darwin-x64@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-darwin-x64@npm:1.3.25" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.24" +"@swc/core-linux-arm-gnueabihf@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.25" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.24" +"@swc/core-linux-arm64-gnu@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.25" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.24" +"@swc/core-linux-arm64-musl@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.25" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.24" +"@swc/core-linux-x64-gnu@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.25" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-linux-x64-musl@npm:1.3.24" +"@swc/core-linux-x64-musl@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-linux-x64-musl@npm:1.3.25" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.24" +"@swc/core-win32-arm64-msvc@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.25" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.24" +"@swc/core-win32-ia32-msvc@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.25" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.24" +"@swc/core-win32-x64-msvc@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.25" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:1.3.24": - version: 1.3.24 - resolution: "@swc/core@npm:1.3.24" +"@swc/core@npm:1.3.25": + version: 1.3.25 + resolution: "@swc/core@npm:1.3.25" dependencies: - "@swc/core-darwin-arm64": 1.3.24 - "@swc/core-darwin-x64": 1.3.24 - "@swc/core-linux-arm-gnueabihf": 1.3.24 - "@swc/core-linux-arm64-gnu": 1.3.24 - "@swc/core-linux-arm64-musl": 1.3.24 - "@swc/core-linux-x64-gnu": 1.3.24 - "@swc/core-linux-x64-musl": 1.3.24 - "@swc/core-win32-arm64-msvc": 1.3.24 - "@swc/core-win32-ia32-msvc": 1.3.24 - "@swc/core-win32-x64-msvc": 1.3.24 + "@swc/core-darwin-arm64": 1.3.25 + "@swc/core-darwin-x64": 1.3.25 + "@swc/core-linux-arm-gnueabihf": 1.3.25 + "@swc/core-linux-arm64-gnu": 1.3.25 + "@swc/core-linux-arm64-musl": 1.3.25 + "@swc/core-linux-x64-gnu": 1.3.25 + "@swc/core-linux-x64-musl": 1.3.25 + "@swc/core-win32-arm64-msvc": 1.3.25 + "@swc/core-win32-ia32-msvc": 1.3.25 + "@swc/core-win32-x64-msvc": 1.3.25 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -1955,9 +1955,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - bin: - swcx: run_swcx.js - checksum: a27b842be129b83c116f804e63deaa51dbd5d9b77d6260888d549f6408df1dd05aeef20046ceacc9fd7458e6afda6723545249bd77f77086b98bd9bf84738c19 + checksum: de45a7dd871cc9497ad998d6a320d3c95cb9c74fdcb70590ff1f631e75001820d021bbfd5c463e9172afcb5ee47bffaa8fb893230e1329538c9f7afbd5ed45cf languageName: node linkType: hard @@ -1973,15 +1971,15 @@ __metadata: languageName: node linkType: hard -"@syuilo/aiscript@npm:0.12.0": - version: 0.12.0 - resolution: "@syuilo/aiscript@npm:0.12.0" +"@syuilo/aiscript@npm:0.12.2": + version: 0.12.2 + resolution: "@syuilo/aiscript@npm:0.12.2" dependencies: autobind-decorator: 2.4.0 seedrandom: 3.0.5 stringz: 2.1.0 - uuid: 8.3.2 - checksum: 82b52a6c602a8c3090b9457a0e9de99898b03cd8f054855b2f57439534257ef2780013a53eaeeef68c9893d96d3ec02fc6d0ede56396c2bcf054cf43b2297b67 + uuid: 9.0.0 + checksum: 66c93157fe19d89c565db6a5576fd3b6f832d45d5b1ef62dc04ddd2fe11cbfb2f53e938f6566da82a562d4b4016208d50039de1301e62ff42cbab26bc6805e15 languageName: node linkType: hard @@ -2447,10 +2445,10 @@ __metadata: languageName: node linkType: hard -"@types/katex@npm:0.14.0": - version: 0.14.0 - resolution: "@types/katex@npm:0.14.0" - checksum: 330e0d0337ba48c87f5b793965fbad673653789bf6e50dfe8d726a7b0cbefd37195055e31503aae629814aa79447e4f23a4b87ad1ac565c0d9a9d9978836f39b +"@types/katex@npm:0.16.0": + version: 0.16.0 + resolution: "@types/katex@npm:0.16.0" + checksum: f93ceb2496621d18a28252264c0b7f5b0bdf125f9dc92d1adfbd9bf00942cd2918de336fae628d3929e615aaf84b7adb1781711c4e4605664be0827b1013ec14 languageName: node linkType: hard @@ -2886,13 +2884,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/eslint-plugin@npm:5.47.1" +"@typescript-eslint/eslint-plugin@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.48.0" dependencies: - "@typescript-eslint/scope-manager": 5.47.1 - "@typescript-eslint/type-utils": 5.47.1 - "@typescript-eslint/utils": 5.47.1 + "@typescript-eslint/scope-manager": 5.48.0 + "@typescript-eslint/type-utils": 5.48.0 + "@typescript-eslint/utils": 5.48.0 debug: ^4.3.4 ignore: ^5.2.0 natural-compare-lite: ^1.4.0 @@ -2905,24 +2903,24 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 59fe719a8fbad14c37b8ce0dd292f6b8066bba370090f5e40eeab03033b97a12df1f1d0963c7070ac8cf4f7f319974fa6747e70932660055d222fa993c239b6a + checksum: cb9cd62fd56670414795e30d30c9fa11ec7ad3a8b0abda48dd17625053a1c26ba1767184b096149bdd0ccb457bec6392306f22211b75f802f4b27366398d16eb languageName: node linkType: hard -"@typescript-eslint/parser@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/parser@npm:5.47.1" +"@typescript-eslint/parser@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/parser@npm:5.48.0" dependencies: - "@typescript-eslint/scope-manager": 5.47.1 - "@typescript-eslint/types": 5.47.1 - "@typescript-eslint/typescript-estree": 5.47.1 + "@typescript-eslint/scope-manager": 5.48.0 + "@typescript-eslint/types": 5.48.0 + "@typescript-eslint/typescript-estree": 5.48.0 debug: ^4.3.4 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 36806686a2c5cc60558c09b13e885861aa21ec6250539d8d3d3c8abb90b321662e57dacec44915c87726a5a0d74187b58a65880a0613024eaeeb7ad0197a345d + checksum: 41d5ce5c8742d286fb083523295a4f186e57bbe4e3da63b6b2de1edbafbcbf6d5225ed3405da2c56e2b0fe1d52bb72babc37508d2ee9b86f6fadad3c4a7950d0 languageName: node linkType: hard @@ -2953,22 +2951,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/scope-manager@npm:5.47.1" +"@typescript-eslint/scope-manager@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/scope-manager@npm:5.48.0" dependencies: - "@typescript-eslint/types": 5.47.1 - "@typescript-eslint/visitor-keys": 5.47.1 - checksum: 73e2e2949b6e0122d89cfd44e1d24eda38d774899b834746700a4f1eb096effd1432c953f8be743a3ea3c7fc8fbf6e0882b11ee0f39b7ced6d8abf6a8665f1c8 + "@typescript-eslint/types": 5.48.0 + "@typescript-eslint/visitor-keys": 5.48.0 + checksum: 96c0ce33d613490690ae6f34e4152f05dbddf3196a6dec89afba4a63cd2d828ae23a98262920b521fe461e7655d38f3a01e9e43588c12392a27bf8cb4f8ae201 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/type-utils@npm:5.47.1" +"@typescript-eslint/type-utils@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/type-utils@npm:5.48.0" dependencies: - "@typescript-eslint/typescript-estree": 5.47.1 - "@typescript-eslint/utils": 5.47.1 + "@typescript-eslint/typescript-estree": 5.48.0 + "@typescript-eslint/utils": 5.48.0 debug: ^4.3.4 tsutils: ^3.21.0 peerDependencies: @@ -2976,7 +2974,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 84a1e6c8fd47d419dc66430e31b818774d4c0329a5f355a5a9e8af94378be4c0c24a89916d5cc1380fdbb640693527b906c2e6adee486a2e6786cb5e08bd9eb3 + checksum: 0d57e3bbcaa46e29b588b86b2271341b264f063e71ff5b6d4d35f50f2fe11bd6cdc3c4c95d78493fd17673ecdbd712992b84da1600947ed3bf6ae09de7b99464 languageName: node linkType: hard @@ -2987,10 +2985,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/types@npm:5.47.1" - checksum: 9b3df8661862a8927ec29d21d6b5826cae7dd8b4797b5b54d66289d8abcf46081453a5cbaf9cc0a5b6c8249ca381dda61c2623da2a704e47f9d86175639a8cea +"@typescript-eslint/types@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/types@npm:5.48.0" + checksum: fa27bd9ec7ec5f256b79a371bb05cfbc26902b6a395f38b0cff0e281633ebd76775ad18e41be1bb156868859287295f6833a2a671da57c6347ac7c6bc08a553b languageName: node linkType: hard @@ -3012,12 +3010,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/typescript-estree@npm:5.47.1" +"@typescript-eslint/typescript-estree@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.48.0" dependencies: - "@typescript-eslint/types": 5.47.1 - "@typescript-eslint/visitor-keys": 5.47.1 + "@typescript-eslint/types": 5.48.0 + "@typescript-eslint/visitor-keys": 5.48.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -3026,25 +3024,25 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 803214a53fd4faf19b6b325dd4e8ddaa5bb1ebb9b52358d26ebeaeb86b431cea5bc09f3b43ca8abfdd3a72fdea667467a1abfda50cbad866696ec5739afae2ac + checksum: 2444632243111e51bc83b56140514cb5978bef4d7151fede0dfcff8808afc1ad335b0c60ca86c2811bcc82273b87e59e2e0360bf1b8c014825ff818a1731d127 languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/utils@npm:5.47.1" +"@typescript-eslint/utils@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/utils@npm:5.48.0" dependencies: "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.47.1 - "@typescript-eslint/types": 5.47.1 - "@typescript-eslint/typescript-estree": 5.47.1 + "@typescript-eslint/scope-manager": 5.48.0 + "@typescript-eslint/types": 5.48.0 + "@typescript-eslint/typescript-estree": 5.48.0 eslint-scope: ^5.1.1 eslint-utils: ^3.0.0 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 5167d26b8d5579de4d9aae36e18f980b33e01006ecc87cff59b761e15f69234092ac555bcf64a9f18d7c3e68a971df2a37b3912fc523c2586c2ba3f4544cc3d3 + checksum: 53f512ae61f72c2b29f2daf8adbc1f37c400cc71156557f69f0745b62c1265d99917a168245e2ee3d88ae458144818d1bf41ced4a764d7d9534b466b29d362fd languageName: node linkType: hard @@ -3058,13 +3056,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.47.1": - version: 5.47.1 - resolution: "@typescript-eslint/visitor-keys@npm:5.47.1" +"@typescript-eslint/visitor-keys@npm:5.48.0": + version: 5.48.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.48.0" dependencies: - "@typescript-eslint/types": 5.47.1 + "@typescript-eslint/types": 5.48.0 eslint-visitor-keys: ^3.3.0 - checksum: b4d1f4daa67e962d22c41325d9dcb6b2efde1caf354a2edb5bf682b92ab8c6205435d0b12f39ce9771955250e26f2a6f03adabb37e62e5aac8225691a59ef153 + checksum: 8d41fb7c93b79df415b43c31da7c9007074d78ab6f16c2d318c23e7974b578ce510f466a9584bd67c526367666974091cb5cfbf6670d29e36fb4ab2e57137515 languageName: node linkType: hard @@ -3085,57 +3083,57 @@ __metadata: languageName: node linkType: hard -"@volar/language-core@npm:1.0.19": - version: 1.0.19 - resolution: "@volar/language-core@npm:1.0.19" +"@volar/language-core@npm:1.0.22": + version: 1.0.22 + resolution: "@volar/language-core@npm:1.0.22" dependencies: - "@volar/source-map": 1.0.19 + "@volar/source-map": 1.0.22 muggle-string: ^0.1.0 - checksum: f49f235e07a2393337c679afaa232d9fd70bf6b6eb0752d574cb99f75c5996af70d3344fe324f3553117b7650c8b3e31331c81fabf8fde6289f2a5f97459e686 + checksum: 809b697a3349ed2ee735c684ee796492b6dab6c7bfe0a82fce2b4c3139b7bb32e7ad9339a1aaf1ce3aa15ccc0826eae27ac77d02dfe73d61a6ce3d20d45fbf92 languageName: node linkType: hard -"@volar/source-map@npm:1.0.19": - version: 1.0.19 - resolution: "@volar/source-map@npm:1.0.19" +"@volar/source-map@npm:1.0.22": + version: 1.0.22 + resolution: "@volar/source-map@npm:1.0.22" dependencies: muggle-string: ^0.1.0 - checksum: a80596333f7ebba33caa2c007ab1b442e5c3ce1d9990364aa10da8e46ebdc736d939b562b5095f268151a02fc45cd09671d8ca8f377b615f3d9d8b876cbcd407 + checksum: 40b33138fd6fe7189a5782c69283d4320e9ab7aa68e9546ce245e4b73035c6d284bb4aa0736080e7c5c7e1532966585cb674fa4c8adba941a6c68f0cbb3905f3 languageName: node linkType: hard -"@volar/typescript@npm:1.0.19": - version: 1.0.19 - resolution: "@volar/typescript@npm:1.0.19" +"@volar/typescript@npm:1.0.22": + version: 1.0.22 + resolution: "@volar/typescript@npm:1.0.22" dependencies: - "@volar/language-core": 1.0.19 - checksum: 1dcce9a6386a205c8708308e664ebb76b846a076a0726a833f6e9416af323e666b6061b28a5a0351e56021be83374af07cb93cb5990e26b6e31a4808a4821847 + "@volar/language-core": 1.0.22 + checksum: d88cb63b32e22ca924853964f2989db894ef4325ee66591be0a5c5e9f2546a8d964b63ee9481d6d6f2e1d2b6d4492a09e9d1e400ef7637583b2f49601087f3e5 languageName: node linkType: hard -"@volar/vue-language-core@npm:1.0.19": - version: 1.0.19 - resolution: "@volar/vue-language-core@npm:1.0.19" +"@volar/vue-language-core@npm:1.0.22": + version: 1.0.22 + resolution: "@volar/vue-language-core@npm:1.0.22" dependencies: - "@volar/language-core": 1.0.19 - "@volar/source-map": 1.0.19 + "@volar/language-core": 1.0.22 + "@volar/source-map": 1.0.22 "@vue/compiler-dom": ^3.2.45 "@vue/compiler-sfc": ^3.2.45 "@vue/reactivity": ^3.2.45 "@vue/shared": ^3.2.45 minimatch: ^5.1.1 vue-template-compiler: ^2.7.14 - checksum: a3efd990c2cfe661b21c3d0b2536dae504a98358d29cc8ae77a93c37468feafc47b326f20e9cb6ac936fb8dc0d9fc602a1ab25d1f8783791090d76fa3e073828 + checksum: e0eeb347af5f99a5c93bd4cd18b3e5f984ecaec04a21e59f319f466c344feecb79bcc64b3389b8c5e338ac6b57aff2dc02dfaba67505910f09775930f815f37e languageName: node linkType: hard -"@volar/vue-typescript@npm:1.0.19": - version: 1.0.19 - resolution: "@volar/vue-typescript@npm:1.0.19" +"@volar/vue-typescript@npm:1.0.22": + version: 1.0.22 + resolution: "@volar/vue-typescript@npm:1.0.22" dependencies: - "@volar/typescript": 1.0.19 - "@volar/vue-language-core": 1.0.19 - checksum: 01ab7eab3e4c237beca10280c1c79b93579791db37f14874c78c9129f6a8e34f8ed794828129e0114d087f59826e34ae0066c1efc4548e1094eb5b2bdbb5c09f + "@volar/typescript": 1.0.22 + "@volar/vue-language-core": 1.0.22 + checksum: fc63ba3d579305e0aa8642b76494b12b56c10f63dfd3a225e4d1d094769f0e7de62494a3a9c2443724ccfd8de49df651a866f305f9953de6ccb9f96f2cf5e51c languageName: node linkType: hard @@ -3411,15 +3409,15 @@ __metadata: languageName: node linkType: hard -"ajv@npm:8.11.2, ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0": - version: 8.11.2 - resolution: "ajv@npm:8.11.2" +"ajv@npm:8.12.0": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" dependencies: fast-deep-equal: ^3.1.1 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 uri-js: ^4.2.2 - checksum: 53435bf79ee7d1eabba8085962dba4c08d08593334b304db7772887f0b7beebc1b3d957432f7437ed4b60e53b5d966a57b439869890209c50fed610459999e3e + checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 languageName: node linkType: hard @@ -3435,6 +3433,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0": + version: 8.11.2 + resolution: "ajv@npm:8.11.2" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 53435bf79ee7d1eabba8085962dba4c08d08593334b304db7772887f0b7beebc1b3d957432f7437ed4b60e53b5d966a57b439869890209c50fed610459999e3e + languageName: node + linkType: hard + "alphanum-sort@npm:^1.0.1, alphanum-sort@npm:^1.0.2": version: 1.0.2 resolution: "alphanum-sort@npm:1.0.2" @@ -3960,9 +3970,9 @@ __metadata: languageName: node linkType: hard -"aws-sdk@npm:2.1286.0": - version: 2.1286.0 - resolution: "aws-sdk@npm:2.1286.0" +"aws-sdk@npm:2.1289.0": + version: 2.1289.0 + resolution: "aws-sdk@npm:2.1289.0" dependencies: buffer: 4.9.2 events: 1.1.1 @@ -3974,7 +3984,7 @@ __metadata: util: ^0.12.4 uuid: 8.0.0 xml2js: 0.4.19 - checksum: 589494899ee008c2acb5dde44c036501dcfe51bfc537eddb4dcbf6c8a937fb5bd29fb4f2433d75ef080bef79c4ead486d230ba558ab89f54e2cc92b88a500de7 + checksum: e4985b3bf4d06b56711012ed2a05949e51ebc82e3316039268ef54ff774e7b8ba8fa6780a6ca0be222b11b5329b92ca08f27bdc6d410177d9675a45e53a62eb3 languageName: node linkType: hard @@ -4116,9 +4126,9 @@ __metadata: version: 0.0.0-use.local resolution: "backend@workspace:packages/backend" dependencies: - "@bull-board/api": ^4.10.0 - "@bull-board/fastify": ^4.10.0 - "@bull-board/ui": ^4.10.0 + "@bull-board/api": ^4.10.1 + "@bull-board/fastify": ^4.10.1 + "@bull-board/ui": ^4.10.1 "@discordapp/twemoji": 14.0.2 "@fastify/accepts": 4.1.0 "@fastify/cookie": ^8.3.0 @@ -4133,7 +4143,7 @@ __metadata: "@peertube/http-signature": 1.7.0 "@redocly/openapi-core": 1.0.0-beta.117 "@sinonjs/fake-timers": 10.0.2 - "@swc/core": 1.3.24 + "@swc/core": 1.3.25 "@swc/jest": 0.2.24 "@tensorflow/tfjs": ^4.1.0 "@tensorflow/tfjs-node": 4.1.0 @@ -4179,13 +4189,13 @@ __metadata: "@types/web-push": 3.3.2 "@types/websocket": 1.0.5 "@types/ws": 8.5.4 - "@typescript-eslint/eslint-plugin": 5.47.1 - "@typescript-eslint/parser": 5.47.1 + "@typescript-eslint/eslint-plugin": 5.48.0 + "@typescript-eslint/parser": 5.48.0 accepts: ^1.3.8 - ajv: 8.11.2 + ajv: 8.12.0 archiver: 5.3.1 autwh: 0.1.0 - aws-sdk: 2.1286.0 + aws-sdk: 2.1289.0 bcryptjs: 2.4.3 blurhash: 2.0.4 bull: 4.10.2 @@ -4260,8 +4270,8 @@ __metadata: stringz: 2.1.0 summaly: 2.7.0 syslog-pro: "git+https://github.com/misskey-dev/SyslogPro#0.2.9-misskey.2" - systeminformation: 5.16.9 - tinycolor2: 1.5.1 + systeminformation: 5.17.1 + tinycolor2: 1.5.2 tmp: 0.2.1 tsc-alias: 1.8.2 tsconfig-paths: 4.1.2 @@ -4834,6 +4844,13 @@ __metadata: languageName: node linkType: hard +"canvas-confetti@npm:^1.6.0": + version: 1.6.0 + resolution: "canvas-confetti@npm:1.6.0" + checksum: be19e3be736ab28aa8af7b53cba9f4146f5714edadbf4d5a7d7b1899914dc59a8ac5574260fe6b7d9995c51df5787b0b707adfbb72dbacbc61fc03f9f2b25291 + languageName: node + linkType: hard + "caseless@npm:~0.12.0": version: 0.12.0 resolution: "caseless@npm:0.12.0" @@ -4925,12 +4942,12 @@ __metadata: languageName: node linkType: hard -"chart.js@npm:4.1.1": - version: 4.1.1 - resolution: "chart.js@npm:4.1.1" +"chart.js@npm:4.1.2": + version: 4.1.2 + resolution: "chart.js@npm:4.1.2" dependencies: "@kurkle/color": ^0.3.0 - checksum: e195abc7b1271a0d4f616b90ac56465b639bffef8e965d26bf1fd65050011bf359fdc25e43dac1576420c1173dc1430c576fd0f953ae8b62bf257ec571424882 + checksum: 938ac88baf04eb8d784a8d89064696375bc12545421186f5ec9b69ba9b6f7b7da960754f351b59b1df2b1c314dfa848aab44267076888e664d5253bc6a4059dd languageName: node linkType: hard @@ -5782,9 +5799,9 @@ __metadata: languageName: node linkType: hard -"cypress@npm:12.2.0": - version: 12.2.0 - resolution: "cypress@npm:12.2.0" +"cypress@npm:12.3.0": + version: 12.3.0 + resolution: "cypress@npm:12.3.0" dependencies: "@cypress/request": ^2.88.10 "@cypress/xvfb": ^1.2.4 @@ -5830,7 +5847,7 @@ __metadata: yauzl: ^2.10.0 bin: cypress: bin/cypress - checksum: fae721114f2001705cdd59a031d5d41d93092e4bc66561021e7890cd01004ac8e037dbd22e22fe0fac325e8e4420a52e1d75254f4e8b7f7a63e84d3fdb86626c + checksum: 00658996bcca918254348eb42bc03079ccf2d583e5c9c04190267edcbc542d4a22835d7399711c99f7aa7334412104b23cc5a1aa7f02b8b541c12298bf3f63f0 languageName: node linkType: hard @@ -8027,13 +8044,13 @@ __metadata: "@rollup/plugin-alias": 4.0.2 "@rollup/plugin-json": 6.0.0 "@rollup/pluginutils": 5.0.2 - "@syuilo/aiscript": 0.12.0 + "@syuilo/aiscript": 0.12.2 "@tabler/icons": ^1.118.0 "@types/escape-regexp": 0.0.1 "@types/glob": 8.0.0 "@types/gulp": 4.0.10 "@types/gulp-rename": 2.0.1 - "@types/katex": 0.14.0 + "@types/katex": 0.16.0 "@types/matter-js": 0.18.2 "@types/punycode": 2.1.0 "@types/sanitize-html": ^2.8.0 @@ -8043,8 +8060,8 @@ __metadata: "@types/uuid": 9.0.0 "@types/websocket": 1.0.5 "@types/ws": 8.5.4 - "@typescript-eslint/eslint-plugin": 5.47.1 - "@typescript-eslint/parser": 5.47.1 + "@typescript-eslint/eslint-plugin": 5.48.0 + "@typescript-eslint/parser": 5.48.0 "@vitejs/plugin-vue": 4.0.0 "@vue/compiler-sfc": 3.2.45 "@vue/runtime-core": 3.2.45 @@ -8053,7 +8070,8 @@ __metadata: blurhash: 2.0.4 broadcast-channel: 4.19.1 browser-image-resizer: "git+https://github.com/misskey-dev/browser-image-resizer#v2.2.1-misskey.3" - chart.js: 4.1.1 + canvas-confetti: ^1.6.0 + chart.js: 4.1.2 chartjs-adapter-date-fns: 3.0.0 chartjs-chart-matrix: ^1.3.0 chartjs-plugin-gradient: 0.6.1 @@ -8061,7 +8079,7 @@ __metadata: compare-versions: 5.0.1 cropperjs: 2.0.0-beta.2 cross-env: 7.0.3 - cypress: 12.2.0 + cypress: 12.3.0 date-fns: 2.29.3 escape-regexp: 0.0.1 eslint: 8.31.0 @@ -8073,7 +8091,7 @@ __metadata: insert-text-at-cursor: 0.3.0 is-file-animated: 1.0.2 json5: 2.2.3 - katex: 0.15.6 + katex: 0.16.4 matter-js: 0.18.0 mfm-js: 0.23.0 misskey-js: 0.0.14 @@ -8082,7 +8100,7 @@ __metadata: punycode: 2.1.1 querystring: 0.2.1 rndstr: 1.0.0 - rollup: 3.9.0 + rollup: 3.9.1 s-age: 1.1.2 sanitize-html: ^2.8.1 sass: 1.57.1 @@ -8094,18 +8112,18 @@ __metadata: textarea-caret: 3.1.0 three: 0.148.0 throttle-debounce: 5.0.0 - tinycolor2: 1.5.1 + tinycolor2: 1.5.2 tsc-alias: 1.8.2 tsconfig-paths: 4.1.2 twemoji-parser: 14.0.0 typescript: 4.9.4 uuid: 9.0.0 vanilla-tilt: 1.8.0 - vite: 4.0.3 + vite: 4.0.4 vue: 3.2.45 vue-eslint-parser: ^9.1.0 vue-prism-editor: 2.0.0-alpha.2 - vue-tsc: ^1.0.19 + vue-tsc: ^1.0.22 vuedraggable: next languageName: unknown linkType: soft @@ -10904,14 +10922,14 @@ __metadata: languageName: node linkType: hard -"katex@npm:0.15.6": - version: 0.15.6 - resolution: "katex@npm:0.15.6" +"katex@npm:0.16.4": + version: 0.16.4 + resolution: "katex@npm:0.16.4" dependencies: commander: ^8.0.0 bin: katex: cli.js - checksum: 2da808bbd1d3be27715006cd86767dd3fcce3e317fb3bbd64d407328d2d90de17b5d83062b2cfd0e0d0de32e340efbac214862bc96892a5d1492462e553728d4 + checksum: 94eaf1fbd8365792308527695c09baa6d2d84e2d0170e4af44fb12be3ed403fb3430caff2410117f2f1a9dfdb329f61ab9611d97e645d9c89ee60940698a45cc languageName: node linkType: hard @@ -11822,10 +11840,10 @@ __metadata: dependencies: "@types/gulp": 4.0.10 "@types/gulp-rename": 2.0.1 - "@typescript-eslint/eslint-plugin": 5.47.1 - "@typescript-eslint/parser": 5.47.1 + "@typescript-eslint/eslint-plugin": 5.48.0 + "@typescript-eslint/parser": 5.48.0 cross-env: 7.0.3 - cypress: 12.2.0 + cypress: 12.3.0 eslint: ^8.31.0 execa: 5.1.1 gulp: 4.0.2 @@ -14790,9 +14808,9 @@ __metadata: languageName: node linkType: hard -"rollup@npm:3.9.0": - version: 3.9.0 - resolution: "rollup@npm:3.9.0" +"rollup@npm:3.9.1": + version: 3.9.1 + resolution: "rollup@npm:3.9.1" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -14800,7 +14818,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: b0ce4baa8db8ee77ab096a4e066b20fb0719efb9cbd84f230838517d35bf159311487112852cfa687126896b58084c8e6cb9ab222f7559c4b6138ca693d63439 + checksum: 929cfab6b8bb2e20c28d7a4c3909b53729f4a63d8cc14f3b1a217d5f8e550737ee0903124ba58a1f2e7efd45c596e044a968aa379411731d0e76c910621d7d3f languageName: node linkType: hard @@ -15953,12 +15971,12 @@ __metadata: languageName: node linkType: hard -"systeminformation@npm:5.16.9": - version: 5.16.9 - resolution: "systeminformation@npm:5.16.9" +"systeminformation@npm:5.17.1": + version: 5.17.1 + resolution: "systeminformation@npm:5.17.1" bin: systeminformation: lib/cli.js - checksum: e590134391ba727b4988ae828483344ae90ee03551ffb578defd3d6d489a8faa519aee563df18fea5f98c2b9e74ca55d29f1ad096d3a70933672338b9a78f03c + checksum: f13052ef52be86431a045d545f2b641a80e1becd46a0610dacd3f5773ebca0866b0087bf7706c1539e61945007354c4da344479f09a69b6dffe7a4f42d712a90 conditions: (os=darwin | os=linux | os=win32 | os=freebsd | os=openbsd | os=netbsd | os=sunos | os=android) languageName: node linkType: hard @@ -16182,10 +16200,10 @@ __metadata: languageName: node linkType: hard -"tinycolor2@npm:1.5.1": - version: 1.5.1 - resolution: "tinycolor2@npm:1.5.1" - checksum: 0fffbe217217f819e0ef79524fda8813c20dac89b647bfc0f1bc0c7d5a80884dad0d74a414b865d2ce867d76d2303f251f7527eaebfe2838251e195fc4b0287c +"tinycolor2@npm:1.5.2": + version: 1.5.2 + resolution: "tinycolor2@npm:1.5.2" + checksum: 9df1ea9a986b03f1aebb1c1ac17fc561e358493f61b56d73ef2d7207fe7bd74eb71cf745b70487b2b5bb1ce33c9e8af7101088bb0b5fc532eaa1f9d1eda4ef31 languageName: node linkType: hard @@ -16913,15 +16931,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:8.3.2, uuid@npm:^8.3.0, uuid@npm:^8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df - languageName: node - linkType: hard - "uuid@npm:9.0.0": version: 9.0.0 resolution: "uuid@npm:9.0.0" @@ -16940,6 +16949,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^8.3.0, uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df + languageName: node + linkType: hard + "v8-to-istanbul@npm:^9.0.1": version: 9.0.1 resolution: "v8-to-istanbul@npm:9.0.1" @@ -17072,9 +17090,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:4.0.3": - version: 4.0.3 - resolution: "vite@npm:4.0.3" +"vite@npm:4.0.4": + version: 4.0.4 + resolution: "vite@npm:4.0.4" dependencies: esbuild: ^0.16.3 fsevents: ~2.3.2 @@ -17106,7 +17124,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 7df71d955f78cbe0dd8e1eb0851fc75070346a0426b8e3e913bf2e05d1053ca8a50619d550fab4f1ed52c68dfcc2921e6421504e9669fc5ed77497a77f84e33e + checksum: eb86c8cdfe8dcb6644005486b31cb60bc596f2aa683cb194abb5c0afca7c2a5dfdb02bbc7f83f419ad170227ac9c3b898f4406a6d1433105fb61d79d78e47d52 languageName: node linkType: hard @@ -17153,17 +17171,17 @@ __metadata: languageName: node linkType: hard -"vue-tsc@npm:^1.0.19": - version: 1.0.19 - resolution: "vue-tsc@npm:1.0.19" +"vue-tsc@npm:^1.0.22": + version: 1.0.22 + resolution: "vue-tsc@npm:1.0.22" dependencies: - "@volar/vue-language-core": 1.0.19 - "@volar/vue-typescript": 1.0.19 + "@volar/vue-language-core": 1.0.22 + "@volar/vue-typescript": 1.0.22 peerDependencies: typescript: "*" bin: vue-tsc: bin/vue-tsc.js - checksum: 7fe6287d7a12b906f8b7a111cc5b88e3df09f919bbfc04dff1d5c46edcdd925b7650e51fc2de819fbc9ae7bc081807ca27d8f86bd3141886ee9f3fff6cdf417a + checksum: 630a372fef2cd6ce830c540fe81b29c657f1b8caaffb181a84af5c10c9daec9c977860ab30cdfb7c80166c5211d3cbfa912f9212f87a763b20d3e91887b1318c languageName: node linkType: hard