diff --git a/CHANGELOG.md b/CHANGELOG.md index e15c6d646..e363abe2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ --> +## 12.101.0 (2021/12/29) + +### Improvements +- クライアント: ノートプレビューの精度を改善 +- クライアント: MFM sparkleエフェクトの改善 +- クライアント: デザインの調整 +- セキュリティの向上 + +### Bugfixes +- クライアント: 一部のコンポーネントが裏に隠れるのを修正 +- fix html blockquote conversion + ## 12.100.2 (2021/12/18) ### Bugfixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe3df853b..633995c94 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,7 +87,7 @@ Configuration files are located in [`/.github/workflows`](/.github/workflows). ## Vue Misskey uses Vue(v3) as its front-end framework. -**When creating a new component, please use the Composition API instead of the Options API.** +**When creating a new component, please use the Composition API (and [setup sugar](https://v3.vuejs.org/api/sfc-script-setup.html)) instead of the Options API.** Some of the existing components are implemented in the Options API, but it is an old implementation. Refactors that migrate those components to the Composition API are also welcome. ## Adding MisskeyRoom items diff --git a/cypress/support/index.js b/cypress/support/index.js index d68db96df..a9ac34476 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -18,3 +18,9 @@ import './commands' // Alternatively you can use CommonJS syntax: // require('./commands') + +Cypress.on('uncaught:exception', (err, runnable) => { + if (err.message.includes('ResizeObserver loop limit exceeded')) { + return false + } +}); diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 95592d4f3..8942f9a55 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -580,7 +580,6 @@ regenerateLoginToken: "أعد توليد الرمز" regenerateLoginTokenDescription: "ينشئ رمز استيثاق جديد في العادة هذا ليس ضروريًا ؛ عند إنشاء رمز جديد ستُخرج جميع الأجهزة." setMultipleBySeparatingWithSpace: "يمكنك ادخال أكثر من مدخل واحد وذلك بفصلها بمسافات." fileIdOrUrl: "معرف الملف أو رابط" -chatOpenBehavior: "سلوك نفاذة المحادثة عند فتحها" behavior: "السلوك" sample: "مثال" abuseReports: "البلاغات" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 1e655f2a1..240a67778 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -448,6 +448,7 @@ uiLanguage: "Sprache der Benutzeroberfläche" groupInvited: "Du wurdest in eine Gruppe eingeladen" aboutX: "Über {x}" useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen" +disableDrawer: "Keine ausfahrbaren Menüs verwenden" youHaveNoGroups: "Keine Gruppen vorhanden" joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene." noHistory: "Kein Verlauf" @@ -613,7 +614,6 @@ regenerateLoginToken: "Anmeldungstoken regenerieren" regenerateLoginTokenDescription: "Den zur Anmeldung intern verwendeten Token regenerieren. Normalerweise wird dies nicht benötigt. Bei Regeneration werden alle Geräte ausgeloggt." setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren." fileIdOrUrl: "Datei-ID oder URL" -chatOpenBehavior: "Verhalten des Chatfensters bei Öffnung" behavior: "Verhalten" sample: "Beispiel" abuseReports: "Meldungen" @@ -818,6 +818,7 @@ leaveGroup: "Gruppe verlassen" leaveGroupConfirm: "Möchtest du \"{name}\" wirklich verlassen?" useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen" welcomeBackWithName: "Willkommen zurück, {name}" +clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen." _emailUnavailable: used: "Diese Email-Adresse wird bereits verwendet" format: "Das Format dieser Email-Adresse ist ungültig" diff --git a/locales/en-US.yml b/locales/en-US.yml index 8ae1671cf..9286e78cc 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -448,6 +448,7 @@ uiLanguage: "User interface language" groupInvited: "You've been invited to a group" aboutX: "About {x}" useOsNativeEmojis: "Use OS native Emoji" +disableDrawer: "Don't use drawer-style menus" youHaveNoGroups: "You have no groups" joinOrCreateGroup: "Get invited to a group or create your own." noHistory: "No history available" @@ -613,7 +614,6 @@ regenerateLoginToken: "Regenerate login token" regenerateLoginTokenDescription: "Regenerate the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out." setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces." fileIdOrUrl: "File-ID or URL" -chatOpenBehavior: "Behavior of the chat window when opened" behavior: "Behavior" sample: "Sample" abuseReports: "Reports" @@ -817,6 +817,7 @@ leaveGroup: "Leave Group" leaveGroupConfirm: "Are you sure you want to leave \"{name}\"?" useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile" welcomeBackWithName: "Welcome back, {name}" +clickToFinishEmailVerification: "Please click [{ok}] to complete email verification." _emailUnavailable: used: "This email address is already being used" format: "The format of this email address is invalid" diff --git a/locales/eo-UY.yml b/locales/eo-UY.yml index 38e07ba1f..15a8440a2 100644 --- a/locales/eo-UY.yml +++ b/locales/eo-UY.yml @@ -23,7 +23,7 @@ otherSettings: "Aliaj agordoj" openInWindow: "Malfermi en nova fenestro" profile: "Profilo" timeline: "Templinio" -noAccountDescription: "Neniu priskribo" +noAccountDescription: "La uzanto ankoraŭ ne skribis la sinprezenton en sia profilo." login: "Saluti" loggingIn: "Salutado…" logout: "Adiaŭi" @@ -101,7 +101,8 @@ clickToShow: "Klaku por malkaŝu" sensitive: "Enhavo ne estas deca por laborejo (NSFW)" add: "Aldoni" reaction: "Reagoj" -rememberNoteVisibility: "Rememori la agordon de videbleco de la laste sendita" +reactionSetting: "Reagoj aperontaj en la elektilo de reagoj" +rememberNoteVisibility: "Rememori la agordon de videbleco de la lasta afiŝado" attachCancel: "Deigi aldonaĵon" markAsSensitive: "Troviĝi NSFW" unmarkAsSensitive: "Ne troviĝi NSFW" @@ -121,6 +122,7 @@ selectAntenna: "Elekti antenon" selectWidget: "Elekti enestraĵon" editWidgets: "Redakti fenestraĵon" editWidgetsExit: "Fini la redaktadon" +customEmojis: "Federaj emoĵioj" emoji: "Emoĵio" emojis: "Emoĵio" emojiName: "Nomo de la emoĵio" @@ -128,11 +130,12 @@ emojiUrl: "URL de la emoĵio" addEmoji: "Aldoni emoĵion" settingGuide: "Agordaj rekomendoj" cacheRemoteFiles: "Stapli forajn dosierojn" -flagAsBot: "Marki kiel uzata de roboto" -flagAsCat: "Agordi kiel kat-iĝa" -flagAsCatDescription: "Se vi estas kato, ebligu la agordon." +flagAsBot: "Marki kiel esti uzanto de roboto" +flagAsCat: "Marki kiel esti kato" +flagAsCatDescription: "Se vi estas kato, faru ĉi tiun flagon" autoAcceptFollowed: "Aŭtomate akcepti la peton de sekvado far uzantoj kiujn vi sekvas" addAccount: "Aldoni konton" +loginFailed: "Saluto malsukcesis" showOnRemote: "Vidi ĉe la surloka nodo" general: "Ĝenerala" wallpaper: "Ekranfonoj" @@ -148,6 +151,7 @@ recipient: "Ricevonton" annotation: "Komentarioj" federation: "Federaĵo" instances: "Nodoj" +registeredAt: "Registrita je" latestRequestSentAt: "La laste sendita peto" latestRequestReceivedAt: "La laste ricevita peto " latestStatus: "Laŭstato" @@ -319,8 +323,11 @@ antennas: "Antenoj" manageAntennas: "Administri antenojn" name: "Nomo" antennaSource: "Fonto de la anteno" +antennaKeywords: "Ricevi per ĉefterminoj" +antennaExcludeKeywords: "Krom ĉefterminoj" notifyAntenna: "Oni sciigos novajn notojn" withFileAntenna: "Nur kun aldonaĵo" +enableServiceworker: "Aktivigi ServiceWorker" withReplies: "Inkluzive respondoj" connectedTo: "Sekva konto estas konektita" notesAndReplies: "Kun respondoj" @@ -452,9 +459,9 @@ nothing: "Neniu" installedDate: "Dato de instalado" lastUsedDate: "Lastfoje uzita je" state: "Stato" -sort: "Ordigado" -ascendingOrder: "Kreski" -descendingOrder: "Malkreski" +sort: "Ordigi laŭ" +ascendingOrder: "Kreska ordo" +descendingOrder: "Malkreska ordo" scratchpad: "Malneta redaktilo" output: "Elmeto" script: "Skripto" @@ -506,7 +513,7 @@ smtpPort: "Pordo" smtpUser: "Uzantnomo" smtpPass: "Pasvorto" wordMute: "Silentigi specifajn vortojn" -userSaysSomething: "{name} parolis ion" +userSaysSomething: "{name} diras ion" makeActive: "Aktivigi" display: "Vidi" copy: "Kopii" @@ -522,7 +529,6 @@ useGlobalSetting: "Oni uzas malloka agordo" other: "Aliaj" regenerateLoginToken: "Regeneri la aŭtentikigan pecon" fileIdOrUrl: "Dosiera identigilo aŭ URL" -chatOpenBehavior: "Konduto por malfermi la fenestron de babilejo" behavior: "Konduto" sample: "Ekzemplo" abuseReports: "Signaloj" @@ -569,6 +575,7 @@ left: "Maldekstra" center: "Centra" wide: "Vasta" narrow: "Malvasta" +needReloadToApply: "Tiu agordo estos aplikita nur poste reŝargi." showTitlebar: "Videbligi titolan stangon" clearCache: "Malplenigi staplon" onlineUsersCount: "{n} uzantoj estas surlineaj" @@ -633,12 +640,15 @@ unread: "Nelegita" controlPanel: "Ŝaltpodio" manageAccounts: "Bonteni la kontojn" classic: "Klasika" -ffVisibility: "Videbleco pri viaj sekvataro/sekvantaro\n" -ffVisibilityDescription: "Agordi la videblecon kiu povas vidi tiujn kiujn vi sekvas kaj tiujn kiuj sekvas vin." -continueThread: "Vidi pli mesaĝarojn" +muteThread: "Silentigi la mesaĝaron" +unmuteThread: "Malsilentigi la mesaĝaron" +ffVisibility: "Videbleco de la sekvadoj pri vi" +ffVisibilityDescription: "Tie ĉi vi povas agordi la videblecon pri kiuj povas vidi tiujn, kiujn vi sekvas kaj kiuj sekvas vin." +continueThread: "Pli vidi la mesaĝaron" incorrectPassword: "Nevalida pasvorto" leaveGroup: "Eliĝi el la grupo" leaveGroupConfirm: "Ĉu vi certas ke vi volas eliĝi el la grupo {name}?" +welcomeBackWithName: "Alvenbenon! {name}" _emailUnavailable: used: "La retpoŝto jam estas uzita." format: "Nevalida formato." @@ -646,7 +656,7 @@ _emailUnavailable: smtp: "Tiu retpoŝta servilo ne respondas" _ffVisibility: public: "Publika" - followers: "Afiŝi nur al sekvantoj" + followers: "Nur al sekvantoj" private: "Malpublikigita" _signup: emailAddressInfo: "Entajpu vian retpoŝton" @@ -693,6 +703,7 @@ _mfm: inlineMath: "Formulo (en linio)" blockMath: "Formulo (bloko)" quote: "Citi" + emoji: "Federaj emoĵioj" search: "Serĉi" flip: "Inversa" x2: "Granda" @@ -717,6 +728,8 @@ _channel: following: "Sekvante" usersCount: "{n} partoprenantoj" _menuDisplay: + sideFull: "Flanko" + sideIcon: "Flanko (bildsimbolo)" top: "Supro" hide: "Kaŝi" _wordMute: @@ -730,6 +743,7 @@ _theme: description: "Priskribo" defaultValue: "Implicitaĵa valoro" color: "Koloro" + func: "Funkcio" darken: "Malbrileco" lighten: "Brileco" keys: @@ -782,8 +796,8 @@ _permissions: "write:drive": "Ĉia operacio por skribi, forviŝi, aŭ alimaniere ŝanĝi la informon de dosiero en via disko de Misskey" "read:favorites": "Vidi vian liston de preferaĵoj" "write:favorites": "Redakti vian liston de preferaĵoj" - "read:following": "Vidi la infomaciojn pri tio, kion vi sekvas" - "write:following": "Sekvi aŭ malsekvi alian uzanton" + "read:following": "Vidi la infomojn pri la sekvadoj pri vi" + "write:following": "Sekvi/Malsekvi alian uzanton" "read:messaging": "Vidi viajn retbabiladojn" "write:messaging": "Administri viajn retbabiladojn" "read:mutes": "Vidi vian liston de silentigitoj" @@ -798,7 +812,7 @@ _permissions: "read:channels": "Vidi kanalojn" _antennaSources: all: "Ĉiuj notoj" - homeTimeline: "Notoj far uzantoj kiujn vi sekvas" + homeTimeline: "Notoj de uzantoj kiujn vi sekvas" _weekday: sunday: "Dimanĉo" monday: "Lundo" @@ -830,19 +844,25 @@ _poll: closed: "Oni jam balotis ĝin" _visibility: public: "Publika" - publicDescription: "Afiŝi al ĉiuj en la Fediverso" + publicDescription: "Publikigi al ĉiuj en la Fediverso" home: "Hejma" homeDescription: "Dissendi nur sur hejma templinio" followers: "Nur al sekvantoj" - followersDescription: "Afiŝi nur al sekvantoj" - specified: "Rekte" - specifiedDescription: "Afiŝi nur al specifaj uzantoj" + followersDescription: "Videbligi nur al sekvantoj" + specified: "Rekte montrita" + specifiedDescription: "Montri nur al specifaj uzantoj" localOnly: "Nur loka" - localOnlyDescription: "Ne afiŝi al foraj uzantoj" + localOnlyDescription: "Ne videbligi al foraj uzantoj" _postForm: replyPlaceholder: "Respondi la noton…" quotePlaceholder: "Citi la noton…" channelPlaceholder: "Mencii en la kanalo…" + _placeholders: + a: "Kiel vi fartas?" + b: "Kio okazis ĉirkaŭ vi?" + c: "Kion vi pensas?" + d: "Kion vi parolos?" + e: "Komencu skribi…" _profile: name: "Nomo" username: "Uzantnomo" @@ -951,6 +971,9 @@ _pages: default: "Implicitaĵa valoro" script: categories: + random: "Hazardo" + value: "Valoro" + fn: "Funkcio" text: "Manipulo de teksto" list: "Listoj" blocks: @@ -968,6 +991,7 @@ _pages: _join: arg1: "Listoj" arg2: "apartigilo" + random: "Hazardo" _randomPick: arg1: "Listoj" _dailyRandomPick: @@ -985,6 +1009,7 @@ _pages: arg1: "Teksto" _splitStrByLine: arg1: "Teksto" + fn: "Funkcio" _fn: slots: "Juntoj" arg1: "Elmeto" @@ -1008,7 +1033,7 @@ _notification: youGotPoll: "{name} balotis" youGotMessagingMessageFromUser: "{name} sendis al vi mesaĝon" youGotMessagingMessageFromGroup: "Oni sendis al la grupo {name} mesaĝon" - youWereFollowed: "eksekvis vin" + youWereFollowed: "Eksekvis vin" youReceivedFollowRequest: "Vi ricevis peton de sekvado" yourFollowRequestAccepted: "Via peto de sekvado estis akceptita." youWereInvitedToGroup: "Invitita al grupo" @@ -1021,7 +1046,7 @@ _notification: quote: "Citi" reaction: "Reagoj" receiveFollowRequest: "Ricevi peton de sekvado" - followRequestAccepted: "Akceptita peto por sekvado" + followRequestAccepted: "Akceptita peto de sekvado" groupInvited: "Invitita al grupo" _deck: profile: "Agordaro" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 84b24603f..a8b2f5b72 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -609,7 +609,6 @@ regenerateLoginToken: "Regenerar token de login" regenerateLoginTokenDescription: "Regenerar el token usado internamente durante el login. No siempre es necesario hacerlo. Al hacerlo de nuevo, se deslogueará en todos los dispositivos." setMultipleBySeparatingWithSpace: "Puedes añadir mas de uno, separado por espacios." fileIdOrUrl: "Id del archivo o URL" -chatOpenBehavior: "Comportamiento al abrir el chat" behavior: "Comportamiento" sample: "Muestra" abuseReports: "Reportes" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index fd89ecb17..d7e436492 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -611,7 +611,6 @@ regenerateLoginToken: "Régénérer le jeton de connexion" regenerateLoginTokenDescription: "Générer un nouveau jeton d'authentification. Cette opération ne devrait pas être nécessaire ; lors de la génération d'un nouveau jeton, tous les appareils seront déconnectés. " setMultipleBySeparatingWithSpace: "Vous pouvez en définir plusieurs, en les séparant par des espaces." fileIdOrUrl: "ID du fichier ou URL" -chatOpenBehavior: "Comportement de la fenêtre de discussion lors de son ouverture" behavior: "Comportement" sample: "Exemple" abuseReports: "Signalements" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index e083c27b2..f4f0ec8ce 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -611,7 +611,6 @@ regenerateLoginToken: "Perbarui token login" regenerateLoginTokenDescription: "Perbarui token yang digunakan secara internal saat login. Normalnya aksi ini tidak diperlukan. Jika diperbarui, semua perangkat akan dilogout." setMultipleBySeparatingWithSpace: "Kamu dapat menyetel banyak dengan memisahkannya menggunakan spasi." fileIdOrUrl: "File-ID atau URL" -chatOpenBehavior: "Perilaku jendelan obrolan ketika dibuka" behavior: "Perilaku" sample: "Contoh" abuseReports: "Laporkan" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 236568e2f..ff5b01a58 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -590,7 +590,6 @@ other: "Avanzate" regenerateLoginToken: "Genera di nuovo un token di connessione" regenerateLoginTokenDescription: "Genera un nuovo token di autenticazione. Solitamente questa operazione non è necessaria: quando si genera un nuovo token, tutti i dispositivi vanno disconnessi." fileIdOrUrl: "ID o URL del file" -chatOpenBehavior: "Comportamento della finestra di chat quando viene aperta" behavior: "Comportamento" abuseReports: "Segnalazioni" reportAbuse: "Segnalazioni" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 72c20819e..62aade568 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -448,6 +448,7 @@ uiLanguage: "UIの表示言語" groupInvited: "グループに招待されました" aboutX: "{x}について" useOsNativeEmojis: "OSネイティブの絵文字を使用" +disableDrawer: "メニューをドロワーで表示しない" youHaveNoGroups: "グループがありません" joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。" noHistory: "履歴はありません" @@ -613,7 +614,6 @@ regenerateLoginToken: "ログイントークンを再生成" regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。" setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。" fileIdOrUrl: "ファイルIDまたはURL" -chatOpenBehavior: "チャットを開くときの動作" behavior: "動作" sample: "サンプル" abuseReports: "通報" @@ -818,6 +818,7 @@ leaveGroup: "グループから抜ける" leaveGroupConfirm: "「{name}」から抜けますか?" useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示" welcomeBackWithName: "おかえりなさい、{name}さん" +clickToFinishEmailVerification: "[{ok}]を押して、メールアドレスの確認を完了してください。" _emailUnavailable: used: "既に使用されています" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 8b7513ffa..1fee5f572 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -612,7 +612,6 @@ regenerateLoginToken: "로그인 토큰을 재생성" regenerateLoginTokenDescription: "로그인할 때 사용되는 내부 토큰을 재생성합니다. 일반적으로 이 작업을 실행할 필요는 없습니다. 이 기능을 사용하면 이 계정으로 로그인한 모든 기기에서 로그아웃됩니다." setMultipleBySeparatingWithSpace: "공백으로 구분하여 여러 개 설정할 수 있습니다." fileIdOrUrl: "파일 ID 또는 URL" -chatOpenBehavior: "대화를 열 때의 동작" behavior: "동작" sample: "예시" abuseReports: "신고" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index ca2af6647..a4f8f3efe 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -81,6 +81,8 @@ somethingHappened: "Coś poszło nie tak" retry: "Spróbuj ponownie" pageLoadError: "Nie udało się załadować strony" pageLoadErrorDescription: "Zwykle jest to spowodowane problemem z siecią lub cache przeglądarki. Spróbuj wyczyścić cache i sprawdź jeszcze raz za chwilę." +serverIsDead: "Serwer nie odpowiada. Zaczekaj chwilę i spróbuj ponownie." +youShouldUpgradeClient: "Odśwież stronę, by zaaktualizować klienta." enterListName: "Nazwa listy" privacy: "Prywatność" makeFollowManuallyApprove: "Prośby o możliwość obserwacji wymagają zatwierdzenia" @@ -104,6 +106,7 @@ clickToShow: "Kliknij, aby wyświetlić" sensitive: "NSFW" add: "Dodaj" reaction: "Reakcja" +reactionSetting: "Reakcje do pokazania w wyborniku reakcji" reactionSettingDescription2: "Przeciągnij aby zmienić kolejność, naciśnij aby usunąć, naciśnij „+” aby dodać" rememberNoteVisibility: "Zapamiętuj ustawienia widoczności wpisu" attachCancel: "Usuń załącznik" @@ -180,6 +183,7 @@ instanceInfo: "Informacje o instancji" statistics: "Statystyki" clearQueue: "Wyczyść kolejkę" clearQueueConfirmTitle: "Czy na pewno chcesz wyczyścić kolejkę?" +clearQueueConfirmText: "Wszystkie niewysłane wpisy z kolejki nie zostaną wysłane. Zwykle to nie jest konieczne." clearCachedFiles: "Wyczyść pamięć podręczną" clearCachedFilesConfirm: "Czy na pewno chcesz usunąć wszystkie zdalne pliki z pamięci podręcznej?" blockedInstances: "Zablokowane instancje" @@ -219,6 +223,7 @@ more: "Więcej!" featured: "Wyróżnione" usernameOrUserId: "Nazwa lub id użytkownika" noSuchUser: "Nie znaleziono użytkownika" +lookup: "Zapytania" announcements: "Ogłoszenia" imageUrl: "Adres URL obrazka" remove: "Usuń" @@ -308,22 +313,28 @@ monthX: "{month}" yearX: "{year}" pages: "Strony" integration: "Integracja" +connectService: "Połącz" +disconnectService: "Rozłącz" enableLocalTimeline: "Włącz lokalną oś czasu" enableGlobalTimeline: "Włącz globalną oś czasu" disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone." registration: "Zarejestruj się" enableRegistration: "Włącz rejestrację nowych użytkowników" invite: "Zaproś" +proxyRemoteFiles: "Przekierowuj pliki obcych instancji przez proxy" +proxyRemoteFilesDescription: "Gdy ta opcja jest włączona, zdalne pliki które nie są przechowywane lokalnie, lub zostały usunięte z powodu przekroczenia limitu miejsca będą kierowane przez proxy, razem z generowaniem miniatur. Nie ma to żadnego wpływu na przestrzeń dyskową serwera." driveCapacityPerLocalAccount: "Powierzchnia dyskowa na lokalnego użytkownika" driveCapacityPerRemoteAccount: "Powierzchnia dyskowa na zdalnego użytkownika" inMb: "W megabajtach" iconUrl: "Adres URL ikony" bannerUrl: "Adres URL banera" +backgroundImageUrl: "Adres URL tła" basicInfo: "Podstawowe informacje" pinnedUsers: "Przypięty użytkownik" pinnedUsersDescription: "Wypisz po jednej nazwie użytkownika w wierszu. Podani użytkownicy zostaną przypięci pod kartą „Eksploruj”." pinnedPages: "Przypięte strony" pinnedPagesDescription: "Wprowadź ścieżki stron które chcesz przypiąć na głównej stronie instancji, oddzielone znakiem nowego wiersza." +pinnedClipId: "ID przypiętego klipu" pinnedNotes: "Przypięty wpis" hcaptcha: "hCaptcha" enableHcaptcha: "Włącz hCaptcha" @@ -338,7 +349,9 @@ antennas: "Anteny" manageAntennas: "Zarządzaj Antenami" name: "Nazwa" antennaSource: "Źródło Anteny" +antennaKeywords: "Słowa kluczowe do obserwacji" antennaExcludeKeywords: "Wykluczone słowa kluczowe" +antennaKeywordsDescription: "Oddziel spacjami dla warunku AND, albo wymuś koniec linii dla warunku OR" notifyAntenna: "Powiadamiaj o nowych wpisach" withFileAntenna: "Filtruj tylko wpisy z załączonym plikiem" enableServiceworker: "Włącz ServiceWorker" @@ -586,8 +599,9 @@ useGlobalSetting: "Użyj globalnych ustawień" useGlobalSettingDesc: "Jeżeli włączone, zostaną wykorzystane ustawienia powiadomień Twojego konta. Jeżeli wyłączone, mogą zostać wykonane oddzielne konfiguracje." other: "Inne" regenerateLoginToken: "Generuj token logowania ponownie" +regenerateLoginTokenDescription: "Regeneruje token używany wewnętrznie podczas logowania. Zazwyczaj nie jest to konieczne. Po regeneracji wszystkie urządzenia zostaną wylogowane." setMultipleBySeparatingWithSpace: "Możesz ustawić wiele, oddzielając je spacjami." -chatOpenBehavior: "Zachowanie okna czatu po otwarciu" +fileIdOrUrl: "ID pliku albo URL" behavior: "Zachowanie" sample: "Przykład" abuseReports: "Zgłoszenia" @@ -595,6 +609,8 @@ reportAbuse: "Zgłoś" reportAbuseOf: "Zgłoś {name}" fillAbuseReportDescription: "Wypełnij szczegóły zgłoszenia. Jeżeli dotyczy ono określonego wpisu, uwzględnij jego adres URL." abuseReported: "Twoje zgłoszenie zostało wysłane. Dziękujemy." +reporteeOrigin: "Pochodzenie zgłoszonego" +reporterOrigin: "Pochodzenie zgłaszającego" send: "Wyślij" abuseMarkAsResolved: "Oznacz zgłoszenie jako rozwiązane" openInNewTab: "Otwórz w nowej karcie" @@ -607,7 +623,7 @@ random: "Losowe" system: "System" switchUi: "Przełącz interfejs użytkownika" desktop: "Pulpit" -createNew: "Utworzy nowy" +createNew: "Utwórz nowy" optional: "Nieobowiązkowe" public: "Publiczny" i18nInfo: "Misskey jest tłumaczone na wiele języków przez wolontariuszy. Możesz pomóc na {link}." @@ -630,6 +646,7 @@ driveFilesCount: "Liczba plików na dysku" driveUsage: "Użycie przestrzeni dyskowej" noCrawle: "Odrzuć indeksowanie przez crawlery" noCrawleDescription: "Proś wyszukiwarki internetowe, aby nie indeksowały Twojego profilu, wpisów, stron itd." +lockedAccountInfo: "Dopóki nie ustawisz widoczności wpisu na \"Obserwujący\", twoje wpisy będą mogli widzieć wszyscy, nawet jeśli ustawisz manualne zatwierdzanie obserwujących." alwaysMarkSensitive: "Oznacz domyślnie jako NSFW" loadRawImages: "Wyświetlaj zdjęcia w załącznikach w całości zamiast miniatur" disableShowingAnimatedImages: "Nie odtwarzaj animowanych obrazów" @@ -653,6 +670,7 @@ center: "Wyśsrodkuj" wide: "Szerokie" narrow: "Wąskie" reloadToApplySetting: "To ustawienie zostanie zastosowane po odświeżeniu strony. Chcesz odświeżyć?" +needReloadToApply: "To ustawienie zostanie zastosowane po odświeżeniu strony" showTitlebar: "Pokazuj pasek tytułowy" clearCache: "Wyczyść pamięć podręczną" onlineUsersCount: "{n} osób jest online" @@ -697,6 +715,8 @@ unlikeConfirm: "Na pewno chcesz usunąć polubienie?" fullView: "Pełny widok" quitFullView: "Opuść pełny widok" addDescription: "Dodaj opis" +userPagePinTip: "Możesz wyświetlać wpisy w tym miejscu po wybraniu \"Przypnij do profilu\" z menu pojedyńczego wpisu" +notSpecifiedMentionWarning: "Ten wpis zawiera wzmianki o użytkownikach niezawartych jako odbiorcy" info: "Informacje" userInfo: "Informacje o użykowniku" unknown: "Nieznane" @@ -734,9 +754,15 @@ middle: "Średnie" low: "Niski" emailNotConfiguredWarning: "Nie podano adresu e-mail" ratio: "Stosunek" +previewNoteText: "Pokaż podgląd" +customCss: "Własny CSS" +customCssWarn: "Używaj tego ustawienia tylko wtedy, gdy wiesz co ono robi. Nieprawidłowe wpisy mogą spowodować, że klient przestanie działać poprawnie." global: "Globalna" +squareAvatars: "Wyświetlaj kwadratowe awatary" sent: "Wyślij" +received: "Otrzymane" hashtags: "Hashtag" +pubSub: "Konta Pub/Sub" hide: "Ukryj" _ffVisibility: public: "Publikuj" @@ -977,6 +1003,7 @@ _tutorial: step1_3: "Twoja oś czasu jest jeszcze pusta, ponieważ nie opublikowałeś(-aś) jeszcze żadnych wpisów i nie obserwujesz jeszcze nikogo." step2_1: "Ukończmy konfigurację profilu zanim utworzymy wpis lub zaczniemy kogoś obserwować." step3_1: "Zakończyłeś(-aś) konfigurację profilu?" + step3_3: "Wypełnij pole i kliknij przycisk w prawym górnym rogu by wysłać post." _2fa: registerDevice: "Zarejestruj nowe urządzenie" step1: "Najpierw, zainstaluj aplikację uwierzytelniającą (taką jak {a} lub {b}) na swoim urządzeniu." @@ -1048,7 +1075,7 @@ _poll: deadlineDate: "Data zakończenia" deadlineTime: "godz." duration: "Czas trwania" - votesCount: "{} głosów" + votesCount: "{n} głosów" totalVotes: "Łącznie {n} głosów" vote: "Głosowanie w ankiecie" showResult: "Pokaż wyniki" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 19fe6a689..588fb91c4 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -611,7 +611,6 @@ regenerateLoginToken: "Создать новый токен для входа" regenerateLoginTokenDescription: "Создаёт новый токен, используемый внутри программы во время входа. Обычно в этом нет необходимости. При создании все устройства будут отключены." setMultipleBySeparatingWithSpace: "Можно написать несколько через пробел" fileIdOrUrl: "Идентификатор файла или ссылка" -chatOpenBehavior: "Поведение окна чата при открытии" behavior: "Поведение" sample: "Пример" abuseReports: "Жалобы" @@ -683,6 +682,7 @@ center: "По центру" wide: "Толстый" narrow: "Тонкий" reloadToApplySetting: "Это настройка вступает в силу при загрузке страницы. Перезагрузить сейчас?" +needReloadToApply: "Чтобы это вступило в силу, требуется перезагрузка." showTitlebar: "Показать заголовок" clearCache: "Очистить кэш" onlineUsersCount: "Пользователей сейчас в сети: {n}" @@ -801,11 +801,16 @@ makeReactionsPublicDescription: "Список сделанных вами реа classic: "Классика" unmuteThread: "Отключить звук" ffVisibilityDescription: "Вы можете установить объем вашей следующей/последней информации." +voteConfirm: "Вы бы проголосовали за \"{choice}\"?" hide: "Спрятать" +leaveGroup: "Покинуть группу" leaveGroupConfirm: "Вы хотите оставить \"{name}\"?" +welcomeBackWithName: "С возвращением, {name}!" +clickToFinishEmailVerification: "Пожалуйста, нажмите [{ok}], чтобы завершить подтверждение адреса электронной почты." _emailUnavailable: used: "Уже используется" format: "Неправильный формат" + mx: "Это неправильный почтовый сервер!" smtp: "Почтовый сервер не отвечает" _ffVisibility: public: "Опубликовать" @@ -1263,6 +1268,7 @@ _exportOrImport: muteList: "Скрытые" blockingList: "Заблокированные" userLists: "Списки" + excludeMutingUsers: "Исключение отключенных пользователей" _charts: federationInstancesIncDec: "Изменение внешних связей" federationInstancesTotal: "Количество внешних связей" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 029f5ef3c..8cb0e2e2a 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -592,7 +592,6 @@ regenerateLoginToken: "Оновити Login Token" regenerateLoginTokenDescription: "Регенерувати внутрішній ключ використовуваний під час входу. Зазвичай цього не потрібно робити. При регенерації всі пристрої вийдуть з системи." setMultipleBySeparatingWithSpace: "Можна вказати кілька значень, відділивши їх пробілом." fileIdOrUrl: "Ідентифікатор файлу або посилання" -chatOpenBehavior: "Поводження вікна переписки під час відкриття" behavior: "Поведінка" sample: "Приклад" abuseReports: "Скарги" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index dd69a3c7c..c842b065a 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -448,6 +448,7 @@ uiLanguage: "显示语言" groupInvited: "您有新的群组邀请" aboutX: "关于 {x}" useOsNativeEmojis: "使用系统的原生表情符号" +disableDrawer: "不显示抽屉菜单" youHaveNoGroups: "没有群组" joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。" noHistory: "没有历史记录" @@ -613,7 +614,6 @@ regenerateLoginToken: "重新生成登录令牌" regenerateLoginTokenDescription: "重新生成用于登录的内部令牌。通常您不需要这样做。重新生成后,您将在所有设备上登出。" setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。" fileIdOrUrl: "文件ID或者URL" -chatOpenBehavior: "聊天窗口打开时的行为" behavior: "行为" sample: "示例" abuseReports: "举报" @@ -685,6 +685,7 @@ center: "中央" wide: "宽" narrow: "窄" reloadToApplySetting: "页面刷新后设置才会生效。是否现在刷新页面?" +needReloadToApply: "重启后应用才会生效。" showTitlebar: "显示标题栏" clearCache: "清除缓存" onlineUsersCount: "{n}人在线" @@ -816,6 +817,8 @@ hide: "隐藏" leaveGroup: "离开群组" leaveGroupConfirm: "确定离开「{name}」?" useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示" +welcomeBackWithName: "欢迎回来,{name}" +clickToFinishEmailVerification: "点击 [{ok}] 完成电子邮件地址认证。" _emailUnavailable: used: "已经被使用过" format: "无效的格式" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 364ef3dd9..ad264822f 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -597,7 +597,6 @@ regenerateLoginToken: "重新產生登入權杖" regenerateLoginTokenDescription: "重新產生用於登入的內部權杖。一般情況下是不需要這樣做的。一旦重產,所有裝置將會被登出。" setMultipleBySeparatingWithSpace: "您可以使用空格分隔多個項目。" fileIdOrUrl: "檔案ID或URL" -chatOpenBehavior: "開啟聊天窗口時的行為" behavior: "行為" sample: "範例" abuseReports: "檢舉" diff --git a/package.json b/package.json index 58df68ca2..0c5becded 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.100.2", + "version": "12.101.0", "codename": "indigo", "repository": { "type": "git", diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 43f59f1e4..b00bd8165 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,2 +1,47 @@ export const USER_ONLINE_THRESHOLD = 1000 * 60 * 10; // 10min export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days + +// ブラウザで直接表示することを許可するファイルの種類のリスト +// ここに含まれないものは application/octet-stream としてレスポンスされる +// SVGはXSSを生むので許可しない +export const FILE_TYPE_BROWSERSAFE = [ + // Images + 'image/png', + 'image/gif', + 'image/jpeg', + 'image/webp', + 'image/apng', + 'image/bmp', + 'image/tiff', + 'image/x-icon', + + // OggS + 'audio/opus', + 'video/ogg', + 'audio/ogg', + 'application/ogg', + + // ISO/IEC base media file format + 'video/quicktime', + 'video/mp4', + 'audio/mp4', + 'video/x-m4v', + 'audio/x-m4a', + 'video/3gpp', + 'video/3gpp2', + + 'video/mpeg', + 'audio/mpeg', + + 'video/webm', + 'audio/webm', + + 'audio/aac', + 'audio/x-flac', + 'audio/vnd.wave', +]; +/* +https://github.com/sindresorhus/file-type/blob/main/supported.js +https://github.com/sindresorhus/file-type/blob/main/core.js +https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers +*/ diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index 43e16d80c..fc6d3b306 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -168,7 +168,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string | null { case 'blockquote': { const t = getText(node); if (t) { - text += '> '; + text += '\n> '; text += t.split('\n').join(`\n> `); } break; diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index f36aa8f96..361cdd295 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -99,7 +99,10 @@ export async function getFileInfo(path: string): Promise { /** * Detect MIME Type and extension */ -export async function detectType(path: string) { +export async function detectType(path: string): Promise<{ + mime: string; + ext: string | null; +}> { // Check 0 byte const fileSize = await getFileSize(path); if (fileSize === 0) { diff --git a/packages/backend/src/server/file/send-drive-file.ts b/packages/backend/src/server/file/send-drive-file.ts index 8bb5655b4..7bfc36e25 100644 --- a/packages/backend/src/server/file/send-drive-file.ts +++ b/packages/backend/src/server/file/send-drive-file.ts @@ -14,6 +14,7 @@ import { detectType } from '@/misc/get-file-info'; import { convertToJpeg, convertToPngOrJpeg } from '@/services/drive/image-processor'; import { GenerateVideoThumbnail } from '@/services/drive/generate-video-thumbnail'; import { StatusError } from '@/misc/fetch'; +import { FILE_TYPE_BROWSERSAFE } from '@/const'; //const _filename = fileURLToPath(import.meta.url); const _filename = __filename; @@ -27,6 +28,7 @@ const commonReadableHandlerGenerator = (ctx: Koa.Context) => (e: Error): void => ctx.set('Cache-Control', 'max-age=300'); }; +// eslint-disable-next-line import/no-default-export export default async function(ctx: Koa.Context) { const key = ctx.params.key; @@ -81,7 +83,7 @@ export default async function(ctx: Koa.Context) { const image = await convertFile(); ctx.body = image.data; - ctx.set('Content-Type', image.type); + ctx.set('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream'); ctx.set('Cache-Control', 'max-age=31536000, immutable'); } catch (e) { serverLogger.error(`${e}`); @@ -112,14 +114,14 @@ export default async function(ctx: Koa.Context) { }).toString(); ctx.body = InternalStorage.read(key); - ctx.set('Content-Type', mime); + ctx.set('Content-Type', FILE_TYPE_BROWSERSAFE.includes(mime) ? mime : 'application/octet-stream'); ctx.set('Cache-Control', 'max-age=31536000, immutable'); ctx.set('Content-Disposition', contentDisposition('inline', filename)); } else { const readable = InternalStorage.read(file.accessKey!); readable.on('error', commonReadableHandlerGenerator(ctx)); ctx.body = readable; - ctx.set('Content-Type', file.type); + ctx.set('Content-Type', FILE_TYPE_BROWSERSAFE.includes(file.type) ? file.type : 'application/octet-stream'); ctx.set('Cache-Control', 'max-age=31536000, immutable'); ctx.set('Content-Disposition', contentDisposition('inline', file.name)); } diff --git a/packages/backend/src/server/proxy/proxy-media.ts b/packages/backend/src/server/proxy/proxy-media.ts index 9e13c0877..b116b4b96 100644 --- a/packages/backend/src/server/proxy/proxy-media.ts +++ b/packages/backend/src/server/proxy/proxy-media.ts @@ -6,6 +6,7 @@ import { createTemp } from '@/misc/create-temp'; import { downloadUrl } from '@/misc/download-url'; import { detectType } from '@/misc/get-file-info'; import { StatusError } from '@/misc/fetch'; +import { FILE_TYPE_BROWSERSAFE } from '@/const'; export async function proxyMedia(ctx: Koa.Context) { const url = 'url' in ctx.query ? ctx.query.url : 'https://' + ctx.params.url; @@ -18,7 +19,7 @@ export async function proxyMedia(ctx: Koa.Context) { const { mime, ext } = await detectType(path); - if (!mime.startsWith('image/')) throw 403; + if (!FILE_TYPE_BROWSERSAFE.includes(mime)) throw 403; let image: IImage; diff --git a/packages/backend/src/server/web/views/note.pug b/packages/backend/src/server/web/views/note.pug index 703093697..fce91bdab 100644 --- a/packages/backend/src/server/web/views/note.pug +++ b/packages/backend/src/server/web/views/note.pug @@ -4,6 +4,7 @@ block vars - const user = note.user; - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; - const url = `${config.url}/notes/${note.id}`; + - const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null; block title = `${title} | ${instanceName}` @@ -19,7 +20,7 @@ block og meta(property='og:image' content= user.avatarUrl) block meta - if user.host || profile.noCrawle + if user.host || isRenote || profile.noCrawle meta(name='robots' content='noindex') meta(name='misskey:user-username' content=user.username) diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index ee4d51a96..a59c9501b 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -20,6 +20,7 @@ import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; import * as S3 from 'aws-sdk/clients/s3'; import { getS3 } from './s3'; import * as sharp from 'sharp'; +import { FILE_TYPE_BROWSERSAFE } from '@/const'; const logger = driveLogger.createSubLogger('register', 'yellow'); @@ -241,6 +242,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool */ async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) { if (type === 'image/apng') type = 'image/png'; + if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream'; const meta = await fetchMeta(); diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index 616bc7441..2133768a9 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -3,10 +3,33 @@ import config from '@/config/index'; import { SwSubscriptions } from '@/models/index'; import { fetchMeta } from '@/misc/fetch-meta'; import { Packed } from '@/misc/schema'; +import { getNoteSummary } from '@/misc/get-note-summary'; type notificationType = 'notification' | 'unreadMessagingMessage'; type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>; +// プッシュメッセージサーバーには文字数制限があるため、内容を削減します +function truncateNotification(notification: Packed<'Notification'>): any { + if (notification.note) { + return { + ...notification, + note: { + ...notification.note, + // textをgetNoteSummaryしたものに置き換える + text: getNoteSummary(notification.type === 'renote' ? notification.note.renote as Packed<'Note'> : notification.note), + ...{ + cw: undefined, + reply: undefined, + renote: undefined, + user: undefined as any, // 通知を受け取ったユーザーである場合が多いのでこれも捨てる + } + } + }; + } + + return notification; +} + export default async function(userId: string, type: notificationType, body: notificationBody) { const meta = await fetchMeta(); @@ -32,7 +55,9 @@ export default async function(userId: string, type: notificationType, body: noti }; push.sendNotification(pushSubscription, JSON.stringify({ - type, body, + type, + body: type === 'notification' ? truncateNotification(body as Packed<'Notification'>) : body, + userId, }), { proxy: config.proxy, }).catch((err: any) => { diff --git a/packages/client/assets/sparkle-spritesheet.png b/packages/client/assets/sparkle-spritesheet.png deleted file mode 100644 index 0defccaf0..000000000 Binary files a/packages/client/assets/sparkle-spritesheet.png and /dev/null differ diff --git a/packages/client/package.json b/packages/client/package.json index 681e22208..198bcbcef 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -27,39 +27,39 @@ "@types/oauth": "0.9.1", "@types/parse5": "6.0.3", "@types/punycode": "2.1.0", - "@types/qrcode": "1.4.1", + "@types/qrcode": "1.4.2", "@types/random-seed": "0.3.3", "@types/request-stats": "3.0.0", "@types/seedrandom": "2.4.28", "@types/throttle-debounce": "2.1.0", "@types/tinycolor2": "1.4.3", - "@types/tmp": "0.2.2", + "@types/tmp": "0.2.3", "@types/uuid": "8.3.3", "@types/web-push": "3.3.2", "@types/webpack": "5.28.0", "@types/webpack-stream": "3.2.12", "@types/websocket": "1.0.4", "@types/ws": "8.2.2", - "@typescript-eslint/parser": "5.6.0", - "@vue/compiler-sfc": "3.2.24", + "@typescript-eslint/parser": "5.8.1", + "@vue/compiler-sfc": "3.2.26", "abort-controller": "3.0.0", "autobind-decorator": "2.4.0", "autosize": "4.0.4", "autwh": "0.1.0", "blurhash": "1.1.4", - "broadcast-channel": "4.7.0", - "chart.js": "3.6.2", + "broadcast-channel": "4.9.0", + "chart.js": "3.7.0", "chartjs-adapter-date-fns": "2.0.0", "chartjs-plugin-zoom": "1.2.0", "compare-versions": "3.6.0", - "content-disposition": "0.5.3", + "content-disposition": "0.5.4", "crc-32": "1.2.0", "css-loader": "6.5.1", - "cssnano": "5.0.12", - "date-fns": "2.27.0", + "cssnano": "5.0.14", + "date-fns": "2.28.0", "dateformat": "4.5.1", "escape-regexp": "0.0.1", - "eslint": "8.4.1", + "eslint": "8.5.0", "eslint-plugin-vue": "8.2.0", "eventemitter3": "4.0.7", "feed": "4.2.2", @@ -80,7 +80,7 @@ "parse5": "6.0.1", "photoswipe": "git://github.com/dimsemenov/photoswipe#v5-beta", "portscanner": "2.2.0", - "postcss": "8.4.4", + "postcss": "8.4.5", "postcss-loader": "6.2.1", "prismjs": "1.25.0", "private-ip": "2.3.3", @@ -94,7 +94,7 @@ "request-stats": "3.0.0", "rndstr": "1.0.0", "s-age": "1.1.2", - "sass": "1.44.0", + "sass": "1.45.1", "sass-loader": "12.4.0", "seedrandom": "3.0.5", "strict-event-emitter-types": "2.0.0", @@ -111,11 +111,11 @@ "tsc-alias": "1.4.2", "tsconfig-paths": "3.12.0", "twemoji-parser": "13.1.0", - "typescript": "4.5.2", + "typescript": "4.5.4", "uuid": "8.3.2", "v-debounce": "0.1.2", "vanilla-tilt": "1.7.2", - "vue": "3.2.24", + "vue": "3.2.26", "vue-loader": "16.8.3", "vue-prism-editor": "2.0.0-alpha.2", "vue-router": "4.0.5", @@ -126,14 +126,14 @@ "webpack": "5.65.0", "webpack-cli": "4.9.1", "websocket": "1.0.34", - "ws": "8.3.0" + "ws": "8.4.0" }, "devDependencies": { "@redocly/openapi-core": "1.0.0-beta.54", "@types/fluent-ffmpeg": "2.1.17", - "@typescript-eslint/eslint-plugin": "5.4.0", + "@typescript-eslint/eslint-plugin": "5.8.1", "cross-env": "7.0.3", - "cypress": "8.5.0", + "cypress": "9.2.0", "eslint-plugin-import": "2.25.3", "start-server-and-test": "1.14.0" } diff --git a/packages/client/src/components/emoji-picker.vue b/packages/client/src/components/emoji-picker.vue index ff450246f..a8eed1ca2 100644 --- a/packages/client/src/components/emoji-picker.vue +++ b/packages/client/src/components/emoji-picker.vue @@ -77,7 +77,7 @@ import { defineComponent, markRaw } from 'vue'; import { emojilist } from '@/scripts/emojilist'; import { getStaticImageUrl } from '@/scripts/get-static-image-url'; -import Particle from '@/components/particle.vue'; +import Ripple from '@/components/ripple.vue'; import * as os from '@/os'; import { isTouchUsing } from '@/scripts/touch'; import { isMobile } from '@/scripts/is-mobile'; @@ -296,9 +296,9 @@ export default defineComponent({ if (ev) { const el = ev.currentTarget || ev.target; const rect = el.getBoundingClientRect(); - const x = rect.left + (el.clientWidth / 2); - const y = rect.top + (el.clientHeight / 2); - os.popup(Particle, { x, y }, {}, 'end'); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(Ripple, { x, y }, {}, 'end'); } const key = this.getKey(emoji); diff --git a/packages/client/src/components/form/input.vue b/packages/client/src/components/form/input.vue index c990b693f..3533f4f27 100644 --- a/packages/client/src/components/form/input.vue +++ b/packages/client/src/components/form/input.vue @@ -5,7 +5,7 @@
input { - border-color: var(--accent); + border-color: var(--accent) !important; //box-shadow: 0 0 0 4px var(--focus); } } diff --git a/packages/client/src/components/form/select.vue b/packages/client/src/components/form/select.vue index 9ecff1aa6..afc53ca9c 100644 --- a/packages/client/src/components/form/select.vue +++ b/packages/client/src/components/form/select.vue @@ -3,7 +3,9 @@
- - - + + - +

@@ -55,16 +64,7 @@ export default defineComponent({ .ziffeoms { position: relative; display: flex; - cursor: pointer; - transition: all 0.3s; - - &:first-child { - margin-top: 0; - } - - &:last-child { - margin-bottom: 0; - } + transition: all 0.2s ease; > * { user-select: none; @@ -80,27 +80,32 @@ export default defineComponent({ > .button { position: relative; - display: inline-block; + display: inline-flex; flex-shrink: 0; margin: 0; - width: 36px; - height: 26px; - background: var(--switchBg); + box-sizing: border-box; + width: 23px; + height: 23px; outline: none; - border-radius: 999px; + background: var(--panel); + border: solid 1px var(--panel); + border-radius: 4px; + cursor: pointer; transition: inherit; - > .handle { - position: absolute; - top: 0; - bottom: 0; - left: 5px; - margin: auto 0; - border-radius: 100%; - transition: background-color 0.3s, transform 0.3s; - width: 16px; - height: 16px; - background-color: #fff; + > .check { + margin: auto; + opacity: 0; + color: var(--fgOnAccent); + font-size: 13px; + transform: scale(0.5); + transition: all 0.2s ease; + } + } + + &:hover { + > .button { + border-color: var(--inputBorderHover) !important; } } @@ -108,13 +113,13 @@ export default defineComponent({ margin-left: 16px; margin-top: 2px; display: block; - cursor: pointer; transition: inherit; color: var(--fg); > span { display: block; line-height: 20px; + cursor: pointer; transition: inherit; } @@ -129,12 +134,6 @@ export default defineComponent({ } } - &:hover { - > .button { - background-color: var(--accentedBg); - } - } - &.disabled { opacity: 0.6; cursor: not-allowed; @@ -142,11 +141,12 @@ export default defineComponent({ &.checked { > .button { - background-color: var(--accent); - border-color: var(--accent); + background-color: var(--accent) !important; + border-color: var(--accent) !important; - > .handle { - transform: translateX(10px); + > .check { + opacity: 1; + transform: scale(1); } } } diff --git a/packages/client/src/components/form/textarea.vue b/packages/client/src/components/form/textarea.vue index 98fd0da94..c9ba9b97a 100644 --- a/packages/client/src/components/form/textarea.vue +++ b/packages/client/src/components/form/textarea.vue @@ -4,7 +4,7 @@