Merge branch 'develop' into chat
This commit is contained in:
commit
ce81855d8e
|
@ -25,6 +25,7 @@
|
||||||
- Fix: プロフィール追加情報で無効なURLに入力された場合に照会エラーを出るのを修正
|
- Fix: プロフィール追加情報で無効なURLに入力された場合に照会エラーを出るのを修正
|
||||||
- Fix: ActivityPubリクエストURLチェック実装は仕様に従っていないのを修正
|
- Fix: ActivityPubリクエストURLチェック実装は仕様に従っていないのを修正
|
||||||
- Fix: 連合無しモードでも外部から照会可能だった問題を修正
|
- Fix: 連合無しモードでも外部から照会可能だった問題を修正
|
||||||
|
- Fix: テスト用WebHookのペイロードの`emojis`パラメータが実際のものと異なる問題を修正
|
||||||
|
|
||||||
## 2025.3.1
|
## 2025.3.1
|
||||||
|
|
||||||
|
|
|
@ -1013,6 +1013,7 @@ flip: "اقلب"
|
||||||
lastNDays: "آخر {n} أيام"
|
lastNDays: "آخر {n} أيام"
|
||||||
surrender: "ألغِ"
|
surrender: "ألغِ"
|
||||||
postForm: "أنشئ ملاحظة"
|
postForm: "أنشئ ملاحظة"
|
||||||
|
information: "عن"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "مُعلّق"
|
stop: "مُعلّق"
|
||||||
_initialAccountSetting:
|
_initialAccountSetting:
|
||||||
|
|
|
@ -853,6 +853,7 @@ renotes: "রিনোট"
|
||||||
sourceCode: "সোর্স কোড"
|
sourceCode: "সোর্স কোড"
|
||||||
flip: "উল্টান"
|
flip: "উল্টান"
|
||||||
postForm: "নোট লিখুন"
|
postForm: "নোট লিখুন"
|
||||||
|
information: "আপনার সম্পর্কে"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "স্থগিত করা হয়েছে"
|
stop: "স্থগিত করা হয়েছে"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1334,6 +1334,7 @@ paste: "Pegar"
|
||||||
emojiPalette: "Calaix d'emojis"
|
emojiPalette: "Calaix d'emojis"
|
||||||
postForm: "Formulari de publicació"
|
postForm: "Formulari de publicació"
|
||||||
textCount: "Nombre de caràcters "
|
textCount: "Nombre de caràcters "
|
||||||
|
information: "Informació"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "Calaixos d'emojis"
|
palettes: "Calaixos d'emojis"
|
||||||
enableSyncBetweenDevicesForPalettes: "Activa la sincronització dels calaixos d'emojis entre dispositius"
|
enableSyncBetweenDevicesForPalettes: "Activa la sincronització dels calaixos d'emojis entre dispositius"
|
||||||
|
@ -2673,10 +2674,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Assegura't que qui distribueix aquest recurs és fiable abans d'instal·lar-ho."
|
checkVendorBeforeInstall: "Assegura't que qui distribueix aquest recurs és fiable abans d'instal·lar-ho."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Vols instal·lar aquest afegit?"
|
title: "Vols instal·lar aquest afegit?"
|
||||||
metaTitle: "Informació de l'afegit "
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Vols instal·lar aquest tema?"
|
title: "Vols instal·lar aquest tema?"
|
||||||
metaTitle: "Informació del tema"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Paleta de colors base"
|
base: "Paleta de colors base"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -169,6 +169,9 @@ addAccount: "Přidat účet"
|
||||||
reloadAccountsList: "Obnovit list účtů"
|
reloadAccountsList: "Obnovit list účtů"
|
||||||
loginFailed: "Přihlášení se nezdařilo."
|
loginFailed: "Přihlášení se nezdařilo."
|
||||||
showOnRemote: "Více na původním profilu"
|
showOnRemote: "Více na původním profilu"
|
||||||
|
continueOnRemote: "Pokračujte na původní profil"
|
||||||
|
chooseServerOnMisskeyHub: "Vyberete si server z Misskey Hubu"
|
||||||
|
inputHostName: "Zadejte doménu"
|
||||||
general: "Obecně"
|
general: "Obecně"
|
||||||
wallpaper: "Obrázek na pozadí"
|
wallpaper: "Obrázek na pozadí"
|
||||||
setWallpaper: "Nastavení obrázku na pozadí"
|
setWallpaper: "Nastavení obrázku na pozadí"
|
||||||
|
@ -193,6 +196,7 @@ perHour: "za hodinu"
|
||||||
perDay: "za den"
|
perDay: "za den"
|
||||||
stopActivityDelivery: "Přestat zasílat aktivitu"
|
stopActivityDelivery: "Přestat zasílat aktivitu"
|
||||||
blockThisInstance: "Blokovat tuto instanci"
|
blockThisInstance: "Blokovat tuto instanci"
|
||||||
|
silenceThisInstance: "Utišit tuto instanci"
|
||||||
operations: "Operace"
|
operations: "Operace"
|
||||||
software: "Software"
|
software: "Software"
|
||||||
version: "Verze"
|
version: "Verze"
|
||||||
|
@ -1099,6 +1103,7 @@ flip: "Otočit"
|
||||||
lastNDays: "Posledních {n} dnů"
|
lastNDays: "Posledních {n} dnů"
|
||||||
surrender: "Zrušit"
|
surrender: "Zrušit"
|
||||||
postForm: "Formulář pro odeslání"
|
postForm: "Formulář pro odeslání"
|
||||||
|
information: "Informace"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Suspendováno"
|
stop: "Suspendováno"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1309,6 +1309,7 @@ availableRoles: "Verfügbare Rollen"
|
||||||
federationSpecified: "Dieser Server arbeitet mit Whitelist-Föderation. Er kann nicht mit anderen als den vom Administrator angegebenen Servern interagieren."
|
federationSpecified: "Dieser Server arbeitet mit Whitelist-Föderation. Er kann nicht mit anderen als den vom Administrator angegebenen Servern interagieren."
|
||||||
federationDisabled: "Föderation ist auf diesem Server deaktiviert. Es ist nicht möglich, mit Benutzern auf anderen Servern zu interagieren."
|
federationDisabled: "Föderation ist auf diesem Server deaktiviert. Es ist nicht möglich, mit Benutzern auf anderen Servern zu interagieren."
|
||||||
postForm: "Notizfenster"
|
postForm: "Notizfenster"
|
||||||
|
information: "Über"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_accountSettings:
|
_accountSettings:
|
||||||
|
@ -2524,10 +2525,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Überprüfe vor Installation die Vertrauenswürdigkeit des Vertreibers."
|
checkVendorBeforeInstall: "Überprüfe vor Installation die Vertrauenswürdigkeit des Vertreibers."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Möchtest du dieses Plugin installieren?"
|
title: "Möchtest du dieses Plugin installieren?"
|
||||||
metaTitle: "Plugininformation"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Möchten du dieses Farbschema installieren?"
|
title: "Möchten du dieses Farbschema installieren?"
|
||||||
metaTitle: "Farbschemainfo"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Farbschemavorlage"
|
base: "Farbschemavorlage"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -289,6 +289,7 @@ icon: "Εικονίδιο"
|
||||||
replies: "Απάντηση"
|
replies: "Απάντηση"
|
||||||
renotes: "Κοινοποίηση σημειώματος"
|
renotes: "Κοινοποίηση σημειώματος"
|
||||||
postForm: "Φόρμα δημοσίευσης"
|
postForm: "Φόρμα δημοσίευσης"
|
||||||
|
information: "Πληροφορίες"
|
||||||
_email:
|
_email:
|
||||||
_follow:
|
_follow:
|
||||||
title: "Έχετε ένα νέο ακόλουθο"
|
title: "Έχετε ένα νέο ακόλουθο"
|
||||||
|
|
|
@ -1317,7 +1317,7 @@ unmarkAsSensitiveConfirm: "Do you want to remove the sensitive designation for t
|
||||||
preferences: "Preferences"
|
preferences: "Preferences"
|
||||||
accessibility: "Accessibility"
|
accessibility: "Accessibility"
|
||||||
preferencesProfile: "Preferences profile"
|
preferencesProfile: "Preferences profile"
|
||||||
copyPreferenceId: "Copy the proference ID"
|
copyPreferenceId: "Copy the preference ID"
|
||||||
resetToDefaultValue: "Revert to default"
|
resetToDefaultValue: "Revert to default"
|
||||||
overrideByAccount: "Override by the account"
|
overrideByAccount: "Override by the account"
|
||||||
untitled: "Untitled"
|
untitled: "Untitled"
|
||||||
|
@ -1334,6 +1334,7 @@ paste: "Paste"
|
||||||
emojiPalette: "Emoji palette"
|
emojiPalette: "Emoji palette"
|
||||||
postForm: "Posting form"
|
postForm: "Posting form"
|
||||||
textCount: "Character count"
|
textCount: "Character count"
|
||||||
|
information: "About"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "Palette"
|
palettes: "Palette"
|
||||||
enableSyncBetweenDevicesForPalettes: "Enable palette sync between devices"
|
enableSyncBetweenDevicesForPalettes: "Enable palette sync between devices"
|
||||||
|
@ -2673,10 +2674,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Make sure the distributor of this resource is trustworthy before installation."
|
checkVendorBeforeInstall: "Make sure the distributor of this resource is trustworthy before installation."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Do you want to install this plugin?"
|
title: "Do you want to install this plugin?"
|
||||||
metaTitle: "Plugin information"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Do you want to install this theme?"
|
title: "Do you want to install this theme?"
|
||||||
metaTitle: "Theme information"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Base color scheme"
|
base: "Base color scheme"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
@ -2877,8 +2876,8 @@ _selfXssPrevention:
|
||||||
description2: "If you do not understand exactly what you are trying to paste, %cstop working right now and close this window."
|
description2: "If you do not understand exactly what you are trying to paste, %cstop working right now and close this window."
|
||||||
description3: "For more information, please refer to this. {link}"
|
description3: "For more information, please refer to this. {link}"
|
||||||
_followRequest:
|
_followRequest:
|
||||||
recieved: "Received application"
|
recieved: "Received request"
|
||||||
sent: "Sent application"
|
sent: "Sent request"
|
||||||
_remoteLookupErrors:
|
_remoteLookupErrors:
|
||||||
_federationNotAllowed:
|
_federationNotAllowed:
|
||||||
title: "Unable to communicate with this server"
|
title: "Unable to communicate with this server"
|
||||||
|
|
|
@ -1300,6 +1300,7 @@ target: "Para"
|
||||||
federationSpecified: "Este servidor opera en una federación de listas blancas. No puede interactuar con otros servidores que no sean los especificados por el administrador."
|
federationSpecified: "Este servidor opera en una federación de listas blancas. No puede interactuar con otros servidores que no sean los especificados por el administrador."
|
||||||
federationDisabled: "La federación está desactivada en este servidor. No puede interactuar con usuarios de otros servidores"
|
federationDisabled: "La federación está desactivada en este servidor. No puede interactuar con usuarios de otros servidores"
|
||||||
postForm: "Formulario"
|
postForm: "Formulario"
|
||||||
|
information: "Información"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_accountSettings:
|
_accountSettings:
|
||||||
|
@ -2521,10 +2522,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Asegúrate de que el distribuidor de este recurso es de confianza antes de proceder a la instalación."
|
checkVendorBeforeInstall: "Asegúrate de que el distribuidor de este recurso es de confianza antes de proceder a la instalación."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "¿Quieres instalar este plugin?"
|
title: "¿Quieres instalar este plugin?"
|
||||||
metaTitle: "Información del plugin"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "¿Quieres instalar este tema?"
|
title: "¿Quieres instalar este tema?"
|
||||||
metaTitle: "Información del tema"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Esquema de color base"
|
base: "Esquema de color base"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1278,6 +1278,7 @@ lockdown: "Verrouiller"
|
||||||
pleaseSelectAccount: "Sélectionner un compte"
|
pleaseSelectAccount: "Sélectionner un compte"
|
||||||
availableRoles: "Rôles disponibles"
|
availableRoles: "Rôles disponibles"
|
||||||
postForm: "Formulaire de publication"
|
postForm: "Formulaire de publication"
|
||||||
|
information: "Informations"
|
||||||
_abuseUserReport:
|
_abuseUserReport:
|
||||||
forward: "Transférer"
|
forward: "Transférer"
|
||||||
forwardDescription: "Transférer le signalement vers une instance distante en tant qu'anonyme."
|
forwardDescription: "Transférer le signalement vers une instance distante en tant qu'anonyme."
|
||||||
|
@ -2295,10 +2296,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Veuillez confirmer que le distributeur est fiable avant l'installation."
|
checkVendorBeforeInstall: "Veuillez confirmer que le distributeur est fiable avant l'installation."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Voulez-vous installer cette extension ?"
|
title: "Voulez-vous installer cette extension ?"
|
||||||
metaTitle: "Informations sur l'extension"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Voulez-vous installer ce thème ?"
|
title: "Voulez-vous installer ce thème ?"
|
||||||
metaTitle: "Informations sur le thème"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Palette de couleurs de base"
|
base: "Palette de couleurs de base"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1262,6 +1262,7 @@ modified: "Diubah"
|
||||||
thereAreNChanges: "Ada {n} perubahan"
|
thereAreNChanges: "Ada {n} perubahan"
|
||||||
prohibitedWordsForNameOfUser: "Kata yang dilarang untuk nama pengguna"
|
prohibitedWordsForNameOfUser: "Kata yang dilarang untuk nama pengguna"
|
||||||
postForm: "Buat catatan"
|
postForm: "Buat catatan"
|
||||||
|
information: "Informasi"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_abuseUserReport:
|
_abuseUserReport:
|
||||||
|
@ -2492,10 +2493,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Pastikan sumber dari sumber daya ini terpercaya sebelum melakukan pemasangan."
|
checkVendorBeforeInstall: "Pastikan sumber dari sumber daya ini terpercaya sebelum melakukan pemasangan."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Apakah kamu ingin memasang plugin ini?"
|
title: "Apakah kamu ingin memasang plugin ini?"
|
||||||
metaTitle: "Informasi plugin"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Apakah kamu ingin memasang tema ini?"
|
title: "Apakah kamu ingin memasang tema ini?"
|
||||||
metaTitle: "Informasi tema"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Skema warna dasar"
|
base: "Skema warna dasar"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -5350,6 +5350,10 @@ export interface Locale extends ILocale {
|
||||||
* 文字数
|
* 文字数
|
||||||
*/
|
*/
|
||||||
"textCount": string;
|
"textCount": string;
|
||||||
|
/**
|
||||||
|
* 情報
|
||||||
|
*/
|
||||||
|
"information": string;
|
||||||
/**
|
/**
|
||||||
* チャット
|
* チャット
|
||||||
*/
|
*/
|
||||||
|
@ -10392,20 +10396,12 @@ export interface Locale extends ILocale {
|
||||||
* このプラグインをインストールしますか?
|
* このプラグインをインストールしますか?
|
||||||
*/
|
*/
|
||||||
"title": string;
|
"title": string;
|
||||||
/**
|
|
||||||
* プラグイン情報
|
|
||||||
*/
|
|
||||||
"metaTitle": string;
|
|
||||||
};
|
};
|
||||||
"_theme": {
|
"_theme": {
|
||||||
/**
|
/**
|
||||||
* このテーマをインストールしますか?
|
* このテーマをインストールしますか?
|
||||||
*/
|
*/
|
||||||
"title": string;
|
"title": string;
|
||||||
/**
|
|
||||||
* テーマ情報
|
|
||||||
*/
|
|
||||||
"metaTitle": string;
|
|
||||||
};
|
};
|
||||||
"_meta": {
|
"_meta": {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1334,6 +1334,7 @@ paste: "Incolla"
|
||||||
emojiPalette: "Tavolozza emoji"
|
emojiPalette: "Tavolozza emoji"
|
||||||
postForm: "Finestra di pubblicazione"
|
postForm: "Finestra di pubblicazione"
|
||||||
textCount: "Il numero di caratteri"
|
textCount: "Il numero di caratteri"
|
||||||
|
information: "Informazioni"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "Tavolozza"
|
palettes: "Tavolozza"
|
||||||
enableSyncBetweenDevicesForPalettes: "Attiva la sincronizzazione tra dispositivi"
|
enableSyncBetweenDevicesForPalettes: "Attiva la sincronizzazione tra dispositivi"
|
||||||
|
@ -2673,10 +2674,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Prima di installare, assicurati che la fonte sia affidabile."
|
checkVendorBeforeInstall: "Prima di installare, assicurati che la fonte sia affidabile."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Vuoi davvero installare questo componente aggiuntivo?"
|
title: "Vuoi davvero installare questo componente aggiuntivo?"
|
||||||
metaTitle: "Informazioni sul componente aggiuntivo"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Vuoi davvero installare questa variazione grafica?"
|
title: "Vuoi davvero installare questa variazione grafica?"
|
||||||
metaTitle: "Informazioni sulla variazione grafica"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Combinazione base di colori"
|
base: "Combinazione base di colori"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1333,6 +1333,7 @@ paste: "ペースト"
|
||||||
emojiPalette: "絵文字パレット"
|
emojiPalette: "絵文字パレット"
|
||||||
postForm: "投稿フォーム"
|
postForm: "投稿フォーム"
|
||||||
textCount: "文字数"
|
textCount: "文字数"
|
||||||
|
information: "情報"
|
||||||
chat: "チャット"
|
chat: "チャット"
|
||||||
individualChat: "個人チャット"
|
individualChat: "個人チャット"
|
||||||
individualChat_description: "特定ユーザーとの一対一のチャットができます。"
|
individualChat_description: "特定ユーザーとの一対一のチャットができます。"
|
||||||
|
@ -2757,10 +2758,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "配布元が信頼できるかを確認した上でインストールしてください。"
|
checkVendorBeforeInstall: "配布元が信頼できるかを確認した上でインストールしてください。"
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "このプラグインをインストールしますか?"
|
title: "このプラグインをインストールしますか?"
|
||||||
metaTitle: "プラグイン情報"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "このテーマをインストールしますか?"
|
title: "このテーマをインストールしますか?"
|
||||||
metaTitle: "テーマ情報"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "基本のカラースキーム"
|
base: "基本のカラースキーム"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1312,6 +1312,7 @@ federationDisabled: "このサーバーは連合が無効化されてるで。
|
||||||
confirmOnReact: "ツッコむときに確認とる"
|
confirmOnReact: "ツッコむときに確認とる"
|
||||||
reactAreYouSure: "\" {emoji} \" でツッコむ?"
|
reactAreYouSure: "\" {emoji} \" でツッコむ?"
|
||||||
postForm: "投稿フォーム"
|
postForm: "投稿フォーム"
|
||||||
|
information: "情報"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_accountSettings:
|
_accountSettings:
|
||||||
|
@ -2610,10 +2611,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "配ってるとこが信頼できるか確認した上でインストールしてな。"
|
checkVendorBeforeInstall: "配ってるとこが信頼できるか確認した上でインストールしてな。"
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "このプラグイン、インストールする?"
|
title: "このプラグイン、インストールする?"
|
||||||
metaTitle: "プラグイン情報"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "このテーマインストールする?"
|
title: "このテーマインストールする?"
|
||||||
metaTitle: "テーマ情報"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: ""
|
base: ""
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -655,6 +655,7 @@ replies: "답하기"
|
||||||
renotes: "리노트"
|
renotes: "리노트"
|
||||||
attach: "옇기"
|
attach: "옇기"
|
||||||
surrender: "아이예"
|
surrender: "아이예"
|
||||||
|
information: "정보"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "고만 보내예"
|
stop: "고만 보내예"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1330,6 +1330,7 @@ preferenceSyncConflictChoiceDevice: "장치 설정값"
|
||||||
paste: "붙여넣기"
|
paste: "붙여넣기"
|
||||||
emojiPalette: "이모지 팔레트"
|
emojiPalette: "이모지 팔레트"
|
||||||
postForm: "글 입력란"
|
postForm: "글 입력란"
|
||||||
|
information: "정보"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "팔레트"
|
palettes: "팔레트"
|
||||||
paletteForMain: "메인으로 사용할 팔레트"
|
paletteForMain: "메인으로 사용할 팔레트"
|
||||||
|
@ -2650,10 +2651,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "제공자를 신뢰할 수 있는 경우에만 설치하십시오."
|
checkVendorBeforeInstall: "제공자를 신뢰할 수 있는 경우에만 설치하십시오."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "이 플러그인을 설치하시겠습니까?"
|
title: "이 플러그인을 설치하시겠습니까?"
|
||||||
metaTitle: "플러그인 정보"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "이 테마를 설치하시겠습니까?"
|
title: "이 테마를 설치하시겠습니까?"
|
||||||
metaTitle: "테마 정보"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "기본 컬러 스키마"
|
base: "기본 컬러 스키마"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -394,6 +394,7 @@ searchByGoogle: "ຄົ້ນຫາ"
|
||||||
file: "ໄຟລ໌"
|
file: "ໄຟລ໌"
|
||||||
replies: "ຕອບກັບ"
|
replies: "ຕອບກັບ"
|
||||||
renotes: "Renote"
|
renotes: "Renote"
|
||||||
|
information: "ກ່ຽວກັບ"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "ໂຈະ"
|
stop: "ໂຈະ"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -462,6 +462,7 @@ loggedInAsBot: "Momenteel als bot ingelogd"
|
||||||
icon: "Avatar"
|
icon: "Avatar"
|
||||||
replies: "Antwoord"
|
replies: "Antwoord"
|
||||||
renotes: "Herdelen"
|
renotes: "Herdelen"
|
||||||
|
information: "Over"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Opgeschort"
|
stop: "Opgeschort"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -463,6 +463,7 @@ icon: "Avatar"
|
||||||
replies: "Svar"
|
replies: "Svar"
|
||||||
renotes: "Renote"
|
renotes: "Renote"
|
||||||
surrender: "Avbryt"
|
surrender: "Avbryt"
|
||||||
|
information: "Informasjon"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Suspendert"
|
stop: "Suspendert"
|
||||||
_initialAccountSetting:
|
_initialAccountSetting:
|
||||||
|
|
|
@ -1045,6 +1045,7 @@ lastNDays: "W ciągu ostatnich {n} dni"
|
||||||
surrender: "Odrzuć"
|
surrender: "Odrzuć"
|
||||||
gameRetry: "Spróbuj ponownie"
|
gameRetry: "Spróbuj ponownie"
|
||||||
postForm: "Formularz tworzenia wpisu"
|
postForm: "Formularz tworzenia wpisu"
|
||||||
|
information: "Informacje"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Zawieszono"
|
stop: "Zawieszono"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1302,6 +1302,7 @@ pleaseSelectAccount: "Selecione uma conta"
|
||||||
availableRoles: "Cargos disponíveis"
|
availableRoles: "Cargos disponíveis"
|
||||||
acknowledgeNotesAndEnable: "Ative após compreender as precauções."
|
acknowledgeNotesAndEnable: "Ative após compreender as precauções."
|
||||||
postForm: "Campo de postagem"
|
postForm: "Campo de postagem"
|
||||||
|
information: "Informações"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_accountSettings:
|
_accountSettings:
|
||||||
|
@ -2598,10 +2599,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "Tenha certeza de que o distribuidor desse recurso é confiável antes da instalação."
|
checkVendorBeforeInstall: "Tenha certeza de que o distribuidor desse recurso é confiável antes da instalação."
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "Deseja instalar esse plugin?"
|
title: "Deseja instalar esse plugin?"
|
||||||
metaTitle: "Informações do plugin"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "Deseja instalar esse tema?"
|
title: "Deseja instalar esse tema?"
|
||||||
metaTitle: "Informações do tema"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "Paleta de cores base"
|
base: "Paleta de cores base"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -646,6 +646,7 @@ show: "Arată"
|
||||||
icon: "Avatar"
|
icon: "Avatar"
|
||||||
replies: "Răspunde"
|
replies: "Răspunde"
|
||||||
renotes: "Re-notează"
|
renotes: "Re-notează"
|
||||||
|
information: "Despre"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Suspendat"
|
stop: "Suspendat"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1182,6 +1182,7 @@ alwaysConfirmFollow: "Всегда подтверждать подписку"
|
||||||
inquiry: "Связаться"
|
inquiry: "Связаться"
|
||||||
messageToFollower: "Сообщение подписчикам"
|
messageToFollower: "Сообщение подписчикам"
|
||||||
postForm: "Форма отправки"
|
postForm: "Форма отправки"
|
||||||
|
information: "Описание"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Вебхук"
|
webhook: "Вебхук"
|
||||||
_delivery:
|
_delivery:
|
||||||
|
|
|
@ -918,6 +918,7 @@ sourceCode: "Zdrojový kód"
|
||||||
flip: "Preklopiť"
|
flip: "Preklopiť"
|
||||||
lastNDays: "Posledných {n} dní"
|
lastNDays: "Posledných {n} dní"
|
||||||
postForm: "Napísať poznámku"
|
postForm: "Napísať poznámku"
|
||||||
|
information: "Informácie"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Zmrazené"
|
stop: "Zmrazené"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -562,6 +562,7 @@ inquiry: "Kontakt"
|
||||||
tryAgain: "Försök igen senare"
|
tryAgain: "Försök igen senare"
|
||||||
signinWithPasskey: "Logga in med nyckel"
|
signinWithPasskey: "Logga in med nyckel"
|
||||||
unknownWebAuthnKey: "Okänd nyckel"
|
unknownWebAuthnKey: "Okänd nyckel"
|
||||||
|
information: "Om"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Suspenderad"
|
stop: "Suspenderad"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1293,6 +1293,7 @@ prohibitedWordsForNameOfUserDescription: "หากมีสตริงใด
|
||||||
yourNameContainsProhibitedWords: "ชื่อของคุณนั้นมีคำที่ต้องห้าม"
|
yourNameContainsProhibitedWords: "ชื่อของคุณนั้นมีคำที่ต้องห้าม"
|
||||||
yourNameContainsProhibitedWordsDescription: "ถ้าหากคุณต้องการใช้ชื่อนี้ กรุณาติดต่อผู้ดูแลระบบของเซิร์ฟเวอร์นะค่ะ"
|
yourNameContainsProhibitedWordsDescription: "ถ้าหากคุณต้องการใช้ชื่อนี้ กรุณาติดต่อผู้ดูแลระบบของเซิร์ฟเวอร์นะค่ะ"
|
||||||
postForm: "แบบฟอร์มการโพสต์"
|
postForm: "แบบฟอร์มการโพสต์"
|
||||||
|
information: "เกี่ยวกับ"
|
||||||
_settings:
|
_settings:
|
||||||
webhook: "Webhook"
|
webhook: "Webhook"
|
||||||
_abuseUserReport:
|
_abuseUserReport:
|
||||||
|
@ -2572,10 +2573,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
|
checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "ต้องการติดตั้งปลั๊กอินนี้ใช่ไหม?"
|
title: "ต้องการติดตั้งปลั๊กอินนี้ใช่ไหม?"
|
||||||
metaTitle: "ข้อมูลส่วนเสริม"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "ต้องการติดตั้งธีมนี้ใช่ไหม?"
|
title: "ต้องการติดตั้งธีมนี้ใช่ไหม?"
|
||||||
metaTitle: "ข้อมูลธีม"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "โทนสีพื้นฐาน"
|
base: "โทนสีพื้นฐาน"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -910,6 +910,7 @@ sourceCode: "Вихідний код"
|
||||||
flip: "Перевернути"
|
flip: "Перевернути"
|
||||||
lastNDays: "Останні {n} днів"
|
lastNDays: "Останні {n} днів"
|
||||||
postForm: "Створення нотатки"
|
postForm: "Створення нотатки"
|
||||||
|
information: "Інформація"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Призупинено"
|
stop: "Призупинено"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -841,6 +841,7 @@ icon: "Avatar"
|
||||||
replies: "Javob berish"
|
replies: "Javob berish"
|
||||||
renotes: "Qayta qayd etish"
|
renotes: "Qayta qayd etish"
|
||||||
flip: "Teskari"
|
flip: "Teskari"
|
||||||
|
information: "Haqida"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "To'xtatilgan"
|
stop: "To'xtatilgan"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1120,6 +1120,7 @@ cwNotationRequired: "Nếu \"Ẩn nội dung\" được bật thì cần phải
|
||||||
lastNDays: "{n} ngày trước"
|
lastNDays: "{n} ngày trước"
|
||||||
surrender: "Từ chối"
|
surrender: "Từ chối"
|
||||||
postForm: "Mẫu đăng"
|
postForm: "Mẫu đăng"
|
||||||
|
information: "Giới thiệu"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "Đã vô hiệu hóa"
|
stop: "Đã vô hiệu hóa"
|
||||||
_type:
|
_type:
|
||||||
|
|
|
@ -1334,6 +1334,7 @@ paste: "粘贴"
|
||||||
emojiPalette: "表情符号调色板"
|
emojiPalette: "表情符号调色板"
|
||||||
postForm: "投稿窗口"
|
postForm: "投稿窗口"
|
||||||
textCount: "字数"
|
textCount: "字数"
|
||||||
|
information: "关于"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "调色板"
|
palettes: "调色板"
|
||||||
enableSyncBetweenDevicesForPalettes: "启用调色板的设备间同步"
|
enableSyncBetweenDevicesForPalettes: "启用调色板的设备间同步"
|
||||||
|
@ -2673,10 +2674,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "请在安装前确保来源可靠"
|
checkVendorBeforeInstall: "请在安装前确保来源可靠"
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "要安装此插件吗?"
|
title: "要安装此插件吗?"
|
||||||
metaTitle: "插件信息"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "要安装此主题吗?"
|
title: "要安装此主题吗?"
|
||||||
metaTitle: "主题信息"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "基本配色方案"
|
base: "基本配色方案"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1334,6 +1334,7 @@ paste: "貼上"
|
||||||
emojiPalette: "表情符號調色盤"
|
emojiPalette: "表情符號調色盤"
|
||||||
postForm: "發文視窗"
|
postForm: "發文視窗"
|
||||||
textCount: "字數"
|
textCount: "字數"
|
||||||
|
information: "關於"
|
||||||
_emojiPalette:
|
_emojiPalette:
|
||||||
palettes: "調色盤"
|
palettes: "調色盤"
|
||||||
enableSyncBetweenDevicesForPalettes: "啟用裝置與裝置之間的調色盤同步化"
|
enableSyncBetweenDevicesForPalettes: "啟用裝置與裝置之間的調色盤同步化"
|
||||||
|
@ -2673,10 +2674,8 @@ _externalResourceInstaller:
|
||||||
checkVendorBeforeInstall: "安裝前請確認提供者是可信賴的。"
|
checkVendorBeforeInstall: "安裝前請確認提供者是可信賴的。"
|
||||||
_plugin:
|
_plugin:
|
||||||
title: "要安裝此外掛嘛?"
|
title: "要安裝此外掛嘛?"
|
||||||
metaTitle: "外掛資訊"
|
|
||||||
_theme:
|
_theme:
|
||||||
title: "要安裝此佈景主題嗎?"
|
title: "要安裝此佈景主題嗎?"
|
||||||
metaTitle: "佈景主題資訊"
|
|
||||||
_meta:
|
_meta:
|
||||||
base: "基本配色方案"
|
base: "基本配色方案"
|
||||||
_vendorInfo:
|
_vendorInfo:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2025.3.2-beta.4",
|
"version": "2025.3.2-beta.6",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -7,42 +7,16 @@ import { Injectable } from '@nestjs/common';
|
||||||
import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js';
|
import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js';
|
import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js';
|
||||||
import { AbuseReportPayload, SystemWebhookPayload, SystemWebhookService } from '@/core/SystemWebhookService.js';
|
import { type AbuseReportPayload, SystemWebhookPayload, SystemWebhookService } from '@/core/SystemWebhookService.js';
|
||||||
import { Packed } from '@/misc/json-schema.js';
|
import { type Packed } from '@/misc/json-schema.js';
|
||||||
import { type WebhookEventTypes } from '@/models/Webhook.js';
|
import { type WebhookEventTypes } from '@/models/Webhook.js';
|
||||||
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
import { type UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
|
import { type UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
|
import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
|
||||||
|
|
||||||
const oneDayMillis = 24 * 60 * 60 * 1000;
|
const oneDayMillis = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
function generateAbuseReport(override?: Partial<MiAbuseUserReport>): AbuseReportPayload {
|
|
||||||
const result: MiAbuseUserReport = {
|
|
||||||
id: 'dummy-abuse-report1',
|
|
||||||
targetUserId: 'dummy-target-user',
|
|
||||||
targetUser: null,
|
|
||||||
reporterId: 'dummy-reporter-user',
|
|
||||||
reporter: null,
|
|
||||||
assigneeId: null,
|
|
||||||
assignee: null,
|
|
||||||
resolved: false,
|
|
||||||
forwarded: false,
|
|
||||||
comment: 'This is a dummy report for testing purposes.',
|
|
||||||
targetUserHost: null,
|
|
||||||
reporterHost: null,
|
|
||||||
resolvedAs: null,
|
|
||||||
moderationNote: 'foo',
|
|
||||||
...override,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
targetUser: result.targetUser ? toPackedUserLite(result.targetUser) : null,
|
|
||||||
reporter: result.reporter ? toPackedUserLite(result.reporter) : null,
|
|
||||||
assignee: result.assignee ? toPackedUserLite(result.assignee) : null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateDummyUser(override?: Partial<MiUser>): MiUser {
|
function generateDummyUser(override?: Partial<MiUser>): MiUser {
|
||||||
return {
|
return {
|
||||||
id: 'dummy-user-1',
|
id: 'dummy-user-1',
|
||||||
|
@ -134,124 +108,6 @@ function generateDummyNote(override?: Partial<MiNote>): MiNote {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function toPackedNote(note: MiNote, detail = true, override?: Packed<'Note'>): Packed<'Note'> {
|
|
||||||
return {
|
|
||||||
id: note.id,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
deletedAt: null,
|
|
||||||
text: note.text,
|
|
||||||
cw: note.cw,
|
|
||||||
userId: note.userId,
|
|
||||||
user: toPackedUserLite(note.user ?? generateDummyUser()),
|
|
||||||
replyId: note.replyId,
|
|
||||||
renoteId: note.renoteId,
|
|
||||||
isHidden: false,
|
|
||||||
visibility: note.visibility,
|
|
||||||
mentions: note.mentions,
|
|
||||||
visibleUserIds: note.visibleUserIds,
|
|
||||||
fileIds: note.fileIds,
|
|
||||||
files: [],
|
|
||||||
tags: note.tags,
|
|
||||||
poll: null,
|
|
||||||
emojis: note.emojis,
|
|
||||||
channelId: note.channelId,
|
|
||||||
channel: note.channel,
|
|
||||||
localOnly: note.localOnly,
|
|
||||||
reactionAcceptance: note.reactionAcceptance,
|
|
||||||
reactionEmojis: {},
|
|
||||||
reactions: {},
|
|
||||||
reactionCount: 0,
|
|
||||||
renoteCount: note.renoteCount,
|
|
||||||
repliesCount: note.repliesCount,
|
|
||||||
uri: note.uri ?? undefined,
|
|
||||||
url: note.url ?? undefined,
|
|
||||||
reactionAndUserPairCache: note.reactionAndUserPairCache,
|
|
||||||
...(detail ? {
|
|
||||||
clippedCount: note.clippedCount,
|
|
||||||
reply: note.reply ? toPackedNote(note.reply, false) : null,
|
|
||||||
renote: note.renote ? toPackedNote(note.renote, true) : null,
|
|
||||||
myReaction: null,
|
|
||||||
} : {}),
|
|
||||||
...override,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function toPackedUserLite(user: MiUser, override?: Packed<'UserLite'>): Packed<'UserLite'> {
|
|
||||||
return {
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
username: user.username,
|
|
||||||
host: user.host,
|
|
||||||
avatarUrl: user.avatarUrl,
|
|
||||||
avatarBlurhash: user.avatarBlurhash,
|
|
||||||
avatarDecorations: user.avatarDecorations.map(it => ({
|
|
||||||
id: it.id,
|
|
||||||
angle: it.angle,
|
|
||||||
flipH: it.flipH,
|
|
||||||
url: 'https://example.com/dummy-image001.png',
|
|
||||||
offsetX: it.offsetX,
|
|
||||||
offsetY: it.offsetY,
|
|
||||||
})),
|
|
||||||
isBot: user.isBot,
|
|
||||||
isCat: user.isCat,
|
|
||||||
emojis: user.emojis,
|
|
||||||
onlineStatus: 'active',
|
|
||||||
badgeRoles: [],
|
|
||||||
...override,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function toPackedUserDetailedNotMe(user: MiUser, override?: Packed<'UserDetailedNotMe'>): Packed<'UserDetailedNotMe'> {
|
|
||||||
return {
|
|
||||||
...toPackedUserLite(user),
|
|
||||||
url: null,
|
|
||||||
uri: null,
|
|
||||||
movedTo: null,
|
|
||||||
alsoKnownAs: [],
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: user.updatedAt?.toISOString() ?? null,
|
|
||||||
lastFetchedAt: user.lastFetchedAt?.toISOString() ?? null,
|
|
||||||
bannerUrl: user.bannerUrl,
|
|
||||||
bannerBlurhash: user.bannerBlurhash,
|
|
||||||
isLocked: user.isLocked,
|
|
||||||
isSilenced: false,
|
|
||||||
isSuspended: user.isSuspended,
|
|
||||||
description: null,
|
|
||||||
location: null,
|
|
||||||
birthday: null,
|
|
||||||
lang: null,
|
|
||||||
fields: [],
|
|
||||||
verifiedLinks: [],
|
|
||||||
followersCount: user.followersCount,
|
|
||||||
followingCount: user.followingCount,
|
|
||||||
notesCount: user.notesCount,
|
|
||||||
pinnedNoteIds: [],
|
|
||||||
pinnedNotes: [],
|
|
||||||
pinnedPageId: null,
|
|
||||||
pinnedPage: null,
|
|
||||||
publicReactions: true,
|
|
||||||
followersVisibility: 'public',
|
|
||||||
followingVisibility: 'public',
|
|
||||||
twoFactorEnabled: false,
|
|
||||||
usePasswordLessLogin: false,
|
|
||||||
securityKeys: false,
|
|
||||||
roles: [],
|
|
||||||
memo: null,
|
|
||||||
moderationNote: undefined,
|
|
||||||
isFollowing: false,
|
|
||||||
isFollowed: false,
|
|
||||||
hasPendingFollowRequestFromYou: false,
|
|
||||||
hasPendingFollowRequestToYou: false,
|
|
||||||
isBlocking: false,
|
|
||||||
isBlocked: false,
|
|
||||||
isMuted: false,
|
|
||||||
isRenoteMuted: false,
|
|
||||||
notify: 'none',
|
|
||||||
withReplies: true,
|
|
||||||
...override,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const dummyUser1 = generateDummyUser();
|
const dummyUser1 = generateDummyUser();
|
||||||
const dummyUser2 = generateDummyUser({
|
const dummyUser2 = generateDummyUser({
|
||||||
id: 'dummy-user-2',
|
id: 'dummy-user-2',
|
||||||
|
@ -284,6 +140,7 @@ export class WebhookTestService {
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private customEmojiService: CustomEmojiService,
|
||||||
private userWebhookService: UserWebhookService,
|
private userWebhookService: UserWebhookService,
|
||||||
private systemWebhookService: SystemWebhookService,
|
private systemWebhookService: SystemWebhookService,
|
||||||
private queueService: QueueService,
|
private queueService: QueueService,
|
||||||
|
@ -354,31 +211,31 @@ export class WebhookTestService {
|
||||||
|
|
||||||
switch (params.type) {
|
switch (params.type) {
|
||||||
case 'note': {
|
case 'note': {
|
||||||
send('note', { note: toPackedNote(dummyNote1) });
|
send('note', { note: await this.toPackedNote(dummyNote1) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'reply': {
|
case 'reply': {
|
||||||
send('reply', { note: toPackedNote(dummyReply1) });
|
send('reply', { note: await this.toPackedNote(dummyReply1) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'renote': {
|
case 'renote': {
|
||||||
send('renote', { note: toPackedNote(dummyRenote1) });
|
send('renote', { note: await this.toPackedNote(dummyRenote1) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'mention': {
|
case 'mention': {
|
||||||
send('mention', { note: toPackedNote(dummyMention1) });
|
send('mention', { note: await this.toPackedNote(dummyMention1) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'follow': {
|
case 'follow': {
|
||||||
send('follow', { user: toPackedUserDetailedNotMe(dummyUser1) });
|
send('follow', { user: await this.toPackedUserDetailedNotMe(dummyUser1) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'followed': {
|
case 'followed': {
|
||||||
send('followed', { user: toPackedUserLite(dummyUser2) });
|
send('followed', { user: await this.toPackedUserLite(dummyUser2) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'unfollow': {
|
case 'unfollow': {
|
||||||
send('unfollow', { user: toPackedUserDetailedNotMe(dummyUser3) });
|
send('unfollow', { user: await this.toPackedUserDetailedNotMe(dummyUser3) });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// まだ実装されていない (#9485)
|
// まだ実装されていない (#9485)
|
||||||
|
@ -427,7 +284,7 @@ export class WebhookTestService {
|
||||||
|
|
||||||
switch (params.type) {
|
switch (params.type) {
|
||||||
case 'abuseReport': {
|
case 'abuseReport': {
|
||||||
send('abuseReport', generateAbuseReport({
|
send('abuseReport', await this.generateAbuseReport({
|
||||||
targetUserId: dummyUser1.id,
|
targetUserId: dummyUser1.id,
|
||||||
targetUser: dummyUser1,
|
targetUser: dummyUser1,
|
||||||
reporterId: dummyUser2.id,
|
reporterId: dummyUser2.id,
|
||||||
|
@ -436,7 +293,7 @@ export class WebhookTestService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'abuseReportResolved': {
|
case 'abuseReportResolved': {
|
||||||
send('abuseReportResolved', generateAbuseReport({
|
send('abuseReportResolved', await this.generateAbuseReport({
|
||||||
targetUserId: dummyUser1.id,
|
targetUserId: dummyUser1.id,
|
||||||
targetUser: dummyUser1,
|
targetUser: dummyUser1,
|
||||||
reporterId: dummyUser2.id,
|
reporterId: dummyUser2.id,
|
||||||
|
@ -448,7 +305,7 @@ export class WebhookTestService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'userCreated': {
|
case 'userCreated': {
|
||||||
send('userCreated', toPackedUserLite(dummyUser1));
|
send('userCreated', await this.toPackedUserLite(dummyUser1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'inactiveModeratorsWarning': {
|
case 'inactiveModeratorsWarning': {
|
||||||
|
@ -474,4 +331,153 @@ export class WebhookTestService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
private async generateAbuseReport(override?: Partial<MiAbuseUserReport>): Promise<AbuseReportPayload> {
|
||||||
|
const result: MiAbuseUserReport = {
|
||||||
|
id: 'dummy-abuse-report1',
|
||||||
|
targetUserId: 'dummy-target-user',
|
||||||
|
targetUser: null,
|
||||||
|
reporterId: 'dummy-reporter-user',
|
||||||
|
reporter: null,
|
||||||
|
assigneeId: null,
|
||||||
|
assignee: null,
|
||||||
|
resolved: false,
|
||||||
|
forwarded: false,
|
||||||
|
comment: 'This is a dummy report for testing purposes.',
|
||||||
|
targetUserHost: null,
|
||||||
|
reporterHost: null,
|
||||||
|
resolvedAs: null,
|
||||||
|
moderationNote: 'foo',
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
targetUser: result.targetUser ? await this.toPackedUserLite(result.targetUser) : null,
|
||||||
|
reporter: result.reporter ? await this.toPackedUserLite(result.reporter) : null,
|
||||||
|
assignee: result.assignee ? await this.toPackedUserLite(result.assignee) : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
private async toPackedNote(note: MiNote, detail = true, override?: Packed<'Note'>): Promise<Packed<'Note'>> {
|
||||||
|
return {
|
||||||
|
id: note.id,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
deletedAt: null,
|
||||||
|
text: note.text,
|
||||||
|
cw: note.cw,
|
||||||
|
userId: note.userId,
|
||||||
|
user: await this.toPackedUserLite(note.user ?? generateDummyUser()),
|
||||||
|
replyId: note.replyId,
|
||||||
|
renoteId: note.renoteId,
|
||||||
|
isHidden: false,
|
||||||
|
visibility: note.visibility,
|
||||||
|
mentions: note.mentions,
|
||||||
|
visibleUserIds: note.visibleUserIds,
|
||||||
|
fileIds: note.fileIds,
|
||||||
|
files: [],
|
||||||
|
tags: note.tags,
|
||||||
|
poll: null,
|
||||||
|
emojis: await this.customEmojiService.populateEmojis(note.emojis, note.userHost),
|
||||||
|
channelId: note.channelId,
|
||||||
|
channel: note.channel,
|
||||||
|
localOnly: note.localOnly,
|
||||||
|
reactionAcceptance: note.reactionAcceptance,
|
||||||
|
reactionEmojis: {},
|
||||||
|
reactions: {},
|
||||||
|
reactionCount: 0,
|
||||||
|
renoteCount: note.renoteCount,
|
||||||
|
repliesCount: note.repliesCount,
|
||||||
|
uri: note.uri ?? undefined,
|
||||||
|
url: note.url ?? undefined,
|
||||||
|
reactionAndUserPairCache: note.reactionAndUserPairCache,
|
||||||
|
...(detail ? {
|
||||||
|
clippedCount: note.clippedCount,
|
||||||
|
reply: note.reply ? await this.toPackedNote(note.reply, false) : null,
|
||||||
|
renote: note.renote ? await this.toPackedNote(note.renote, true) : null,
|
||||||
|
myReaction: null,
|
||||||
|
} : {}),
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
private async toPackedUserLite(user: MiUser, override?: Packed<'UserLite'>): Promise<Packed<'UserLite'>> {
|
||||||
|
return {
|
||||||
|
id: user.id,
|
||||||
|
name: user.name,
|
||||||
|
username: user.username,
|
||||||
|
host: user.host,
|
||||||
|
avatarUrl: user.avatarUrl,
|
||||||
|
avatarBlurhash: user.avatarBlurhash,
|
||||||
|
avatarDecorations: user.avatarDecorations.map(it => ({
|
||||||
|
id: it.id,
|
||||||
|
angle: it.angle,
|
||||||
|
flipH: it.flipH,
|
||||||
|
url: 'https://example.com/dummy-image001.png',
|
||||||
|
offsetX: it.offsetX,
|
||||||
|
offsetY: it.offsetY,
|
||||||
|
})),
|
||||||
|
isBot: user.isBot,
|
||||||
|
isCat: user.isCat,
|
||||||
|
emojis: await this.customEmojiService.populateEmojis(user.emojis, user.host),
|
||||||
|
onlineStatus: 'active',
|
||||||
|
badgeRoles: [],
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
private async toPackedUserDetailedNotMe(user: MiUser, override?: Packed<'UserDetailedNotMe'>): Promise<Packed<'UserDetailedNotMe'>> {
|
||||||
|
return {
|
||||||
|
...await this.toPackedUserLite(user),
|
||||||
|
url: null,
|
||||||
|
uri: null,
|
||||||
|
movedTo: null,
|
||||||
|
alsoKnownAs: [],
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: user.updatedAt?.toISOString() ?? null,
|
||||||
|
lastFetchedAt: user.lastFetchedAt?.toISOString() ?? null,
|
||||||
|
bannerUrl: user.bannerUrl,
|
||||||
|
bannerBlurhash: user.bannerBlurhash,
|
||||||
|
isLocked: user.isLocked,
|
||||||
|
isSilenced: false,
|
||||||
|
isSuspended: user.isSuspended,
|
||||||
|
description: null,
|
||||||
|
location: null,
|
||||||
|
birthday: null,
|
||||||
|
lang: null,
|
||||||
|
fields: [],
|
||||||
|
verifiedLinks: [],
|
||||||
|
followersCount: user.followersCount,
|
||||||
|
followingCount: user.followingCount,
|
||||||
|
notesCount: user.notesCount,
|
||||||
|
pinnedNoteIds: [],
|
||||||
|
pinnedNotes: [],
|
||||||
|
pinnedPageId: null,
|
||||||
|
pinnedPage: null,
|
||||||
|
publicReactions: true,
|
||||||
|
followersVisibility: 'public',
|
||||||
|
followingVisibility: 'public',
|
||||||
|
twoFactorEnabled: false,
|
||||||
|
usePasswordLessLogin: false,
|
||||||
|
securityKeys: false,
|
||||||
|
roles: [],
|
||||||
|
memo: null,
|
||||||
|
moderationNote: undefined,
|
||||||
|
isFollowing: false,
|
||||||
|
isFollowed: false,
|
||||||
|
hasPendingFollowRequestFromYou: false,
|
||||||
|
hasPendingFollowRequestToYou: false,
|
||||||
|
isBlocking: false,
|
||||||
|
isBlocked: false,
|
||||||
|
isMuted: false,
|
||||||
|
isRenoteMuted: false,
|
||||||
|
notify: 'none',
|
||||||
|
withReplies: true,
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,7 @@ export interface Schema extends OfSchema {
|
||||||
readonly maximum?: number;
|
readonly maximum?: number;
|
||||||
readonly minimum?: number;
|
readonly minimum?: number;
|
||||||
readonly pattern?: string;
|
readonly pattern?: string;
|
||||||
|
readonly additionalProperties?: Schema | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type RequiredPropertyNames<s extends Obj> = {
|
type RequiredPropertyNames<s extends Obj> = {
|
||||||
|
@ -222,6 +223,13 @@ type ObjectSchemaTypeDef<p extends Schema> =
|
||||||
:
|
:
|
||||||
p['anyOf'] extends ReadonlyArray<Schema> ? never : // see CONTRIBUTING.md
|
p['anyOf'] extends ReadonlyArray<Schema> ? never : // see CONTRIBUTING.md
|
||||||
p['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> :
|
p['allOf'] extends ReadonlyArray<Schema> ? UnionToIntersection<UnionSchemaType<p['allOf']>> :
|
||||||
|
p['additionalProperties'] extends true ? Record<string, any> :
|
||||||
|
p['additionalProperties'] extends Schema ?
|
||||||
|
p['additionalProperties'] extends infer AdditionalProperties ?
|
||||||
|
AdditionalProperties extends Schema ?
|
||||||
|
Record<string, SchemaType<AdditionalProperties>> :
|
||||||
|
never :
|
||||||
|
never :
|
||||||
any;
|
any;
|
||||||
|
|
||||||
type ObjectSchemaType<p extends Schema> = NullOrUndefined<p, ObjectSchemaTypeDef<p>>;
|
type ObjectSchemaType<p extends Schema> = NullOrUndefined<p, ObjectSchemaTypeDef<p>>;
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { MiSystemWebhook, MiUser, MiWebhook, UserProfilesRepository, UsersReposi
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import { QueueService } from '@/core/QueueService.js';
|
import { QueueService } from '@/core/QueueService.js';
|
||||||
|
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
|
||||||
|
|
||||||
describe('WebhookTestService', () => {
|
describe('WebhookTestService', () => {
|
||||||
let app: TestingModule;
|
let app: TestingModule;
|
||||||
|
@ -56,6 +57,11 @@ describe('WebhookTestService', () => {
|
||||||
providers: [
|
providers: [
|
||||||
WebhookTestService,
|
WebhookTestService,
|
||||||
IdService,
|
IdService,
|
||||||
|
{
|
||||||
|
provide: CustomEmojiService, useFactory: () => ({
|
||||||
|
populateEmojis: jest.fn(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: QueueService, useFactory: () => ({
|
provide: QueueService, useFactory: () => ({
|
||||||
systemWebhookDeliver: jest.fn(),
|
systemWebhookDeliver: jest.fn(),
|
||||||
|
|
|
@ -33,13 +33,11 @@ const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resol
|
||||||
Math.min(navigator.hardwareConcurrency - 1, 4),
|
Math.min(navigator.hardwareConcurrency - 1, 4),
|
||||||
);
|
);
|
||||||
resolve(workers);
|
resolve(workers);
|
||||||
if (_DEV_) console.log('WebGL2 in worker is supported!');
|
|
||||||
} else {
|
} else {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 64;
|
canvas.width = 64;
|
||||||
canvas.height = 64;
|
canvas.height = 64;
|
||||||
resolve(canvas);
|
resolve(canvas);
|
||||||
if (_DEV_) console.log('WebGL2 in worker is not supported...');
|
|
||||||
}
|
}
|
||||||
testWorker.terminate();
|
testWorker.terminate();
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,9 +50,40 @@ export default [
|
||||||
// defineExposeが誤検知されてしまう
|
// defineExposeが誤検知されてしまう
|
||||||
'@typescript-eslint/no-unused-expressions': 'off',
|
'@typescript-eslint/no-unused-expressions': 'off',
|
||||||
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
||||||
// window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため
|
// window ... グローバルスコープと衝突し、予期せぬ結果を招くため
|
||||||
// e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため
|
// e ... error や event など、複数のキーワードの頭文字であり分かりにくいため
|
||||||
'id-denylist': ['error', 'window', 'e'],
|
// close ... window.closeと衝突 or 紛らわしい
|
||||||
|
// open ... window.openと衝突 or 紛らわしい
|
||||||
|
// fetch ... window.fetchと衝突 or 紛らわしい
|
||||||
|
// location ... window.locationと衝突 or 紛らわしい
|
||||||
|
'id-denylist': ['warn', 'window', 'e', 'close', 'open', 'fetch', 'location'],
|
||||||
|
'no-restricted-globals': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'name': 'open',
|
||||||
|
'message': 'Use `window.open`.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'close',
|
||||||
|
'message': 'Use `window.close`.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'fetch',
|
||||||
|
'message': 'Use `window.fetch`.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'location',
|
||||||
|
'message': 'Use `window.location`.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'history',
|
||||||
|
'message': 'Use `window.history`.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'name',
|
||||||
|
'message': 'Use `window.name`. もしくは name という変数名を定義し忘れている',
|
||||||
|
},
|
||||||
|
],
|
||||||
'no-shadow': ['warn'],
|
'no-shadow': ['warn'],
|
||||||
'vue/attributes-order': ['error', {
|
'vue/attributes-order': ['error', {
|
||||||
alphabetical: false,
|
alphabetical: false,
|
||||||
|
|
|
@ -12,9 +12,9 @@ import '@/style.scss';
|
||||||
import { mainBoot } from '@/boot/main-boot.js';
|
import { mainBoot } from '@/boot/main-boot.js';
|
||||||
import { subBoot } from '@/boot/sub-boot.js';
|
import { subBoot } from '@/boot/sub-boot.js';
|
||||||
|
|
||||||
const subBootPaths = ['/share', '/auth', '/miauth', '/oauth', '/signup-complete'];
|
const subBootPaths = ['/share', '/auth', '/miauth', '/oauth', '/signup-complete', '/install-extensions'];
|
||||||
|
|
||||||
if (subBootPaths.some(i => location.pathname === i || location.pathname.startsWith(i + '/'))) {
|
if (subBootPaths.some(i => window.location.pathname === i || window.location.pathname.startsWith(i + '/'))) {
|
||||||
subBoot();
|
subBoot();
|
||||||
} else {
|
} else {
|
||||||
mainBoot();
|
mainBoot();
|
||||||
|
|
|
@ -191,7 +191,7 @@ export async function login(token: AccountWithToken['token'], redirect?: string)
|
||||||
// 他のタブは再読み込みするだけ
|
// 他のタブは再読み込みするだけ
|
||||||
reloadChannel.postMessage(null);
|
reloadChannel.postMessage(null);
|
||||||
// このページはredirectで指定された先に移動
|
// このページはredirectで指定された先に移動
|
||||||
location.href = redirect;
|
window.location.href = redirect;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,14 +98,14 @@ export async function common(createVue: () => App<Element>) {
|
||||||
document.addEventListener('touchend', () => {}, { passive: true });
|
document.addEventListener('touchend', () => {}, { passive: true });
|
||||||
|
|
||||||
// URLに#pswpを含む場合は取り除く
|
// URLに#pswpを含む場合は取り除く
|
||||||
if (location.hash === '#pswp') {
|
if (window.location.hash === '#pswp') {
|
||||||
history.replaceState(null, '', location.href.replace('#pswp', ''));
|
window.history.replaceState(null, '', window.location.href.replace('#pswp', ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一斉リロード
|
// 一斉リロード
|
||||||
reloadChannel.addEventListener('message', path => {
|
reloadChannel.addEventListener('message', path => {
|
||||||
if (path !== null) location.href = path;
|
if (path !== null) window.location.href = path;
|
||||||
else location.reload();
|
else window.location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
// If mobile, insert the viewport meta tag
|
// If mobile, insert the viewport meta tag
|
||||||
|
@ -130,11 +130,11 @@ export async function common(createVue: () => App<Element>) {
|
||||||
});
|
});
|
||||||
|
|
||||||
//#region loginId
|
//#region loginId
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const loginId = params.get('loginId');
|
const loginId = params.get('loginId');
|
||||||
|
|
||||||
if (loginId) {
|
if (loginId) {
|
||||||
const target = getUrlWithoutLoginId(location.href);
|
const target = getUrlWithoutLoginId(window.location.href);
|
||||||
|
|
||||||
if (!$i || $i.id !== loginId) {
|
if (!$i || $i.id !== loginId) {
|
||||||
const account = await getAccountFromId(loginId);
|
const account = await getAccountFromId(loginId);
|
||||||
|
@ -143,7 +143,7 @@ export async function common(createVue: () => App<Element>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
history.replaceState({ misskey: 'loginId' }, '', target);
|
window.history.replaceState({ misskey: 'loginId' }, '', target);
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
@ -300,6 +300,7 @@ export async function common(createVue: () => App<Element>) {
|
||||||
removeSplash();
|
removeSplash();
|
||||||
|
|
||||||
//#region Self-XSS 対策メッセージ
|
//#region Self-XSS 対策メッセージ
|
||||||
|
if (!_DEV_) {
|
||||||
console.log(
|
console.log(
|
||||||
`%c${i18n.ts._selfXssPrevention.warning}`,
|
`%c${i18n.ts._selfXssPrevention.warning}`,
|
||||||
'color: #f00; background-color: #ff0; font-size: 36px; padding: 4px;',
|
'color: #f00; background-color: #ff0; font-size: 36px; padding: 4px;',
|
||||||
|
@ -318,6 +319,7 @@ export async function common(createVue: () => App<Element>) {
|
||||||
'font-size: 20px; font-weight: 700; color: #f00;',
|
'font-size: 20px; font-weight: 700; color: #f00;',
|
||||||
);
|
);
|
||||||
console.log(i18n.tsx._selfXssPrevention.description3({ link: 'https://misskey-hub.net/docs/for-users/resources/self-xss/' }));
|
console.log(i18n.tsx._selfXssPrevention.description3({ link: 'https://misskey-hub.net/docs/for-users/resources/self-xss/' }));
|
||||||
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export async function mainBoot() {
|
||||||
if (!$i) uiStyle = 'visitor';
|
if (!$i) uiStyle = 'visitor';
|
||||||
|
|
||||||
if (searchParams.has('zen')) uiStyle = 'zen';
|
if (searchParams.has('zen')) uiStyle = 'zen';
|
||||||
if (uiStyle === 'deck' && prefer.s['deck.useSimpleUiForNonRootPages'] && location.pathname !== '/') uiStyle = 'zen';
|
if (uiStyle === 'deck' && prefer.s['deck.useSimpleUiForNonRootPages'] && window.location.pathname !== '/') uiStyle = 'zen';
|
||||||
|
|
||||||
if (searchParams.has('ui')) uiStyle = searchParams.get('ui');
|
if (searchParams.has('ui')) uiStyle = searchParams.get('ui');
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ export async function mainBoot() {
|
||||||
let reloadDialogShowing = false;
|
let reloadDialogShowing = false;
|
||||||
stream.on('_disconnected_', async () => {
|
stream.on('_disconnected_', async () => {
|
||||||
if (prefer.s.serverDisconnectedBehavior === 'reload') {
|
if (prefer.s.serverDisconnectedBehavior === 'reload') {
|
||||||
location.reload();
|
window.location.reload();
|
||||||
} else if (prefer.s.serverDisconnectedBehavior === 'dialog') {
|
} else if (prefer.s.serverDisconnectedBehavior === 'dialog') {
|
||||||
if (reloadDialogShowing) return;
|
if (reloadDialogShowing) return;
|
||||||
reloadDialogShowing = true;
|
reloadDialogShowing = true;
|
||||||
|
@ -227,7 +227,7 @@ export async function mainBoot() {
|
||||||
});
|
});
|
||||||
reloadDialogShowing = false;
|
reloadDialogShowing = false;
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -458,7 +458,7 @@ export async function mainBoot() {
|
||||||
|
|
||||||
const latestDonationInfoShownAt = miLocalStorage.getItem('latestDonationInfoShownAt');
|
const latestDonationInfoShownAt = miLocalStorage.getItem('latestDonationInfoShownAt');
|
||||||
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
||||||
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
|
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !window.location.pathname.startsWith('/miauth')) {
|
||||||
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
||||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<canvas ref="canvasEl" style="width: 100%; height: 100%; pointer-events: none;"></canvas>
|
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
|
@ -3,14 +3,12 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable import/no-default-export */
|
|
||||||
import type { StoryObj } from '@storybook/vue3';
|
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { file } from '../../.storybook/fakes.js';
|
import { file } from '../../.storybook/fakes.js';
|
||||||
import { commonHandlers } from '../../.storybook/mocks.js';
|
import { commonHandlers } from '../../.storybook/mocks.js';
|
||||||
import MkCropperDialog from './MkCropperDialog.vue';
|
import MkCropperDialog from './MkCropperDialog.vue';
|
||||||
|
import type { StoryObj } from '@storybook/vue3';
|
||||||
export const Default = {
|
export const Default = {
|
||||||
render(args) {
|
render(args) {
|
||||||
return {
|
return {
|
||||||
|
@ -55,7 +53,7 @@ export const Default = {
|
||||||
http.get('/proxy/image.webp', async ({ request }) => {
|
http.get('/proxy/image.webp', async ({ request }) => {
|
||||||
const url = new URL(request.url).searchParams.get('url');
|
const url = new URL(request.url).searchParams.get('url');
|
||||||
if (url === 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true') {
|
if (url === 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true') {
|
||||||
const image = await (await fetch('client-assets/fedi.jpg')).blob();
|
const image = await (await window.fetch('client-assets/fedi.jpg')).blob();
|
||||||
return new HttpResponse(image, {
|
return new HttpResponse(image, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'image/jpeg',
|
'Content-Type': 'image/jpeg',
|
||||||
|
|
|
@ -180,7 +180,7 @@ function applyToPreview() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (currentPreviewUrl === embedPreviewUrl.value) {
|
if (currentPreviewUrl === embedPreviewUrl.value) {
|
||||||
// URLが変わらなくてもリロード
|
// URLが変わらなくてもリロード
|
||||||
iframeEl.value?.contentWindow?.location.reload();
|
iframeEl.value?.contentWindow?.window.location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,17 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<!-- 拡張用? -->
|
<!-- 拡張用? -->
|
||||||
<i v-else class="ti ti-download"></i>
|
<i v-else class="ti ti-download"></i>
|
||||||
</div>
|
</div>
|
||||||
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].title }}</h2>
|
|
||||||
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
|
<h2 v-if="isPlugin" :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller._plugin.title }}</h2>
|
||||||
<MkInfo v-if="isPlugin" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
|
<h2 v-else-if="isTheme" :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller._theme.title }}</h2>
|
||||||
<FormSection>
|
|
||||||
<template #label>{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].metaTitle }}</template>
|
<MkInfo :warn="true">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</MkInfo>
|
||||||
|
|
||||||
|
<div v-if="isPlugin" class="_gaps_s">
|
||||||
|
<MkFolder :defaultOpen="true">
|
||||||
|
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.metadata }}</template>
|
||||||
|
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<FormSplit>
|
<FormSplit>
|
||||||
<MkKeyValue>
|
<MkKeyValue>
|
||||||
|
@ -27,15 +33,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #value>{{ extension.meta.author }}</template>
|
<template #value>{{ extension.meta.author }}</template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
</FormSplit>
|
</FormSplit>
|
||||||
<MkKeyValue v-if="isPlugin">
|
<MkKeyValue>
|
||||||
<template #key>{{ i18n.ts.description }}</template>
|
<template #key>{{ i18n.ts.description }}</template>
|
||||||
<template #value>{{ extension.meta.description ?? i18n.ts.none }}</template>
|
<template #value>{{ extension.meta.description ?? i18n.ts.none }}</template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
<MkKeyValue v-if="isPlugin">
|
<MkKeyValue>
|
||||||
<template #key>{{ i18n.ts.version }}</template>
|
<template #key>{{ i18n.ts.version }}</template>
|
||||||
<template #value>{{ extension.meta.version }}</template>
|
<template #value>{{ extension.meta.version }}</template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
<MkKeyValue v-if="isPlugin">
|
<MkKeyValue>
|
||||||
<template #key>{{ i18n.ts.permission }}</template>
|
<template #key>{{ i18n.ts.permission }}</template>
|
||||||
<template #value>
|
<template #value>
|
||||||
<ul v-if="extension.meta.permissions && extension.meta.permissions.length > 0" :class="$style.extInstallerKVList">
|
<ul v-if="extension.meta.permissions && extension.meta.permissions.length > 0" :class="$style.extInstallerKVList">
|
||||||
|
@ -44,21 +50,52 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template v-else>{{ i18n.ts.none }}</template>
|
<template v-else>{{ i18n.ts.none }}</template>
|
||||||
</template>
|
</template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
<MkKeyValue v-if="isTheme">
|
</div>
|
||||||
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
|
</MkFolder>
|
||||||
<template #value>{{ i18n.ts[extension.meta.base ?? 'none'] }}</template>
|
|
||||||
</MkKeyValue>
|
<MkFolder :withSpacer="false">
|
||||||
<MkFolder>
|
|
||||||
<template #icon><i class="ti ti-code"></i></template>
|
<template #icon><i class="ti ti-code"></i></template>
|
||||||
<template #label>{{ i18n.ts._plugin.viewSource }}</template>
|
<template #label>{{ i18n.ts._plugin.viewSource }}</template>
|
||||||
|
|
||||||
<MkCode :code="extension.raw"/>
|
<MkCode :code="extension.raw"/>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
<div v-else-if="isTheme" class="_gaps_s">
|
||||||
|
<MkFolder :defaultOpen="true">
|
||||||
|
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.metadata }}</template>
|
||||||
|
|
||||||
|
<div class="_gaps_s">
|
||||||
|
<FormSplit>
|
||||||
|
<MkKeyValue>
|
||||||
|
<template #key>{{ i18n.ts.name }}</template>
|
||||||
|
<template #value>{{ extension.meta.name }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
<MkKeyValue>
|
||||||
|
<template #key>{{ i18n.ts.author }}</template>
|
||||||
|
<template #value>{{ extension.meta.author }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
</FormSplit>
|
||||||
|
<MkKeyValue>
|
||||||
|
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
|
||||||
|
<template #value>{{ i18n.ts[extension.meta.base ?? 'none'] }}</template>
|
||||||
|
</MkKeyValue>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder :withSpacer="false">
|
||||||
|
<template #icon><i class="ti ti-code"></i></template>
|
||||||
|
<template #label>{{ i18n.ts._theme.code }}</template>
|
||||||
|
|
||||||
|
<MkCode :code="extension.raw"/>
|
||||||
|
</MkFolder>
|
||||||
|
</div>
|
||||||
|
|
||||||
<slot name="additionalInfo"/>
|
<slot name="additionalInfo"/>
|
||||||
|
|
||||||
<div class="_buttonsCenter">
|
<div class="_buttonsCenter">
|
||||||
<MkButton gradate rounded @click="emits('confirm')"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
|
<MkButton danger rounded large @click="emits('cancel')"><i class="ti ti-x"></i> {{ i18n.ts.cancel }}</MkButton>
|
||||||
|
<MkButton gradate rounded large @click="emits('confirm')"><i class="ti ti-download"></i> {{ i18n.ts.install }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -105,6 +142,7 @@ const props = defineProps<{
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(ev: 'confirm'): void;
|
(ev: 'confirm'): void;
|
||||||
|
(ev: 'cancel'): void;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -112,13 +150,13 @@ const emits = defineEmits<{
|
||||||
.extInstallerRoot {
|
.extInstallerRoot {
|
||||||
border-radius: var(--MI-radius);
|
border-radius: var(--MI-radius);
|
||||||
background: var(--MI_THEME-panel);
|
background: var(--MI_THEME-panel);
|
||||||
padding: 1.5rem;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extInstallerIconWrapper {
|
.extInstallerIconWrapper {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
line-height: 48px;
|
line-height: 48px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
@ -135,10 +173,6 @@ const emits = defineEmits<{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extInstallerNormDesc {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.extInstallerKVList {
|
.extInstallerKVList {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
|
@ -69,13 +69,11 @@ const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resol
|
||||||
Math.min(navigator.hardwareConcurrency - 1, 4),
|
Math.min(navigator.hardwareConcurrency - 1, 4),
|
||||||
);
|
);
|
||||||
resolve(workers);
|
resolve(workers);
|
||||||
if (_DEV_) console.log('WebGL2 in worker is supported!');
|
|
||||||
} else {
|
} else {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 64;
|
canvas.width = 64;
|
||||||
canvas.height = 64;
|
canvas.height = 64;
|
||||||
resolve(canvas);
|
resolve(canvas);
|
||||||
if (_DEV_) console.log('WebGL2 in worker is not supported...');
|
|
||||||
}
|
}
|
||||||
testWorker.terminate();
|
testWorker.terminate();
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { StoryObj } from '@storybook/vue3';
|
|
||||||
import { HttpResponse, http } from 'msw';
|
import { HttpResponse, http } from 'msw';
|
||||||
import { federationInstance } from '../../.storybook/fakes.js';
|
import { federationInstance } from '../../.storybook/fakes.js';
|
||||||
import { commonHandlers } from '../../.storybook/mocks.js';
|
import { commonHandlers } from '../../.storybook/mocks.js';
|
||||||
import { getChartResolver } from '../../.storybook/charts.js';
|
import { getChartResolver } from '../../.storybook/charts.js';
|
||||||
import MkInstanceCardMini from './MkInstanceCardMini.vue';
|
import MkInstanceCardMini from './MkInstanceCardMini.vue';
|
||||||
|
import type { StoryObj } from '@storybook/vue3';
|
||||||
|
|
||||||
export const Default = {
|
export const Default = {
|
||||||
render(args) {
|
render(args) {
|
||||||
|
@ -48,7 +47,7 @@ export const Default = {
|
||||||
const url = new URL(urlStr);
|
const url = new URL(urlStr);
|
||||||
|
|
||||||
if (url.href.startsWith('https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/')) {
|
if (url.href.startsWith('https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/')) {
|
||||||
const image = await (await fetch(`client-assets/${url.pathname.split('/').pop()}`)).blob();
|
const image = await (await window.fetch(`client-assets/${url.pathname.split('/').pop()}`)).blob();
|
||||||
return new HttpResponse(image, {
|
return new HttpResponse(image, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'image/jpeg',
|
'Content-Type': 'image/jpeg',
|
||||||
|
|
|
@ -183,14 +183,14 @@ onMounted(() => {
|
||||||
lightbox?.pswp?.element?.focus({
|
lightbox?.pswp?.element?.focus({
|
||||||
preventScroll: true,
|
preventScroll: true,
|
||||||
});
|
});
|
||||||
history.pushState(null, '', '#pswp');
|
window.history.pushState(null, '', '#pswp');
|
||||||
});
|
});
|
||||||
|
|
||||||
lightbox.on('destroy', () => {
|
lightbox.on('destroy', () => {
|
||||||
focusParent(activeEl, true, false);
|
focusParent(activeEl, true, false);
|
||||||
activeEl = null;
|
activeEl = null;
|
||||||
if (window.location.hash === '#pswp') {
|
if (window.location.hash === '#pswp') {
|
||||||
history.back();
|
window.history.back();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineAsyncComponent, inject, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, unref, watch } from 'vue';
|
import { computed, defineAsyncComponent, inject, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, unref, watch, shallowRef } from 'vue';
|
||||||
import type { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio, MenuRadioOption, MenuParent } from '@/types/menu.js';
|
import type { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio, MenuRadioOption, MenuParent } from '@/types/menu.js';
|
||||||
import type { Keymap } from '@/utility/hotkey.js';
|
import type { Keymap } from '@/utility/hotkey.js';
|
||||||
import MkSwitchButton from '@/components/MkSwitch.button.vue';
|
import MkSwitchButton from '@/components/MkSwitch.button.vue';
|
||||||
|
@ -292,7 +292,7 @@ watch(() => props.items, () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const childMenu = ref<MenuItem[] | null>();
|
const childMenu = ref<MenuItem[] | null>();
|
||||||
const childTarget = useTemplateRef('childTarget');
|
const childTarget = shallowRef<HTMLElement>();
|
||||||
|
|
||||||
function closeChild() {
|
function closeChild() {
|
||||||
childMenu.value = null;
|
childMenu.value = null;
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<MkAnimBg style="position: absolute;"/>
|
||||||
|
<div class="_pageScrollable" style="position: absolute; top: 0; width: 100%; height: 100%;">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MkAnimBg from '@/components/MkAnimBg.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
|
||||||
|
</style>
|
|
@ -267,7 +267,7 @@ async function onSubmit(): Promise<void> {
|
||||||
'testcaptcha-response': testcaptchaResponse.value,
|
'testcaptcha-response': testcaptchaResponse.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await fetch(`${config.apiUrl}/signup`, {
|
const res = await window.fetch(`${config.apiUrl}/signup`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
|
|
@ -87,7 +87,7 @@ function openWindow() {
|
||||||
|
|
||||||
function nav(ev: MouseEvent) {
|
function nav(ev: MouseEvent) {
|
||||||
if (behavior === 'browser') {
|
if (behavior === 'browser') {
|
||||||
location.href = props.to;
|
window.location.href = props.to;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -320,7 +320,7 @@ export class Nirax<DEF extends RouteDef[]> extends EventEmitter<RouterEvents> {
|
||||||
}
|
}
|
||||||
const res = this.navigate(fullPath);
|
const res = this.navigate(fullPath);
|
||||||
if (res.route.path === '/:(*)') {
|
if (res.route.path === '/:(*)') {
|
||||||
location.href = fullPath;
|
window.location.href = fullPath;
|
||||||
} else {
|
} else {
|
||||||
this.emit('push', {
|
this.emit('push', {
|
||||||
beforeFullPath,
|
beforeFullPath,
|
||||||
|
|
|
@ -172,7 +172,7 @@ export const navbarItemDef = reactive({
|
||||||
title: i18n.ts.reload,
|
title: i18n.ts.reload,
|
||||||
icon: 'ti ti-refresh',
|
icon: 'ti ti-refresh',
|
||||||
action: (ev) => {
|
action: (ev) => {
|
||||||
location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
profile: {
|
profile: {
|
||||||
|
|
|
@ -64,7 +64,7 @@ function accepted() {
|
||||||
if (session.value && session.value.app.callbackUrl) {
|
if (session.value && session.value.app.callbackUrl) {
|
||||||
const url = new URL(session.value.app.callbackUrl);
|
const url = new URL(session.value.app.callbackUrl);
|
||||||
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(url.protocol)) throw new Error('invalid url');
|
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(url.protocol)) throw new Error('invalid url');
|
||||||
location.href = `${session.value.app.callbackUrl}?token=${session.value.token}`;
|
window.location.href = `${session.value.app.callbackUrl}?token=${session.value.token}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -632,7 +632,7 @@ function loadMonoTextures() {
|
||||||
src = URL.createObjectURL(monoTextures[mono.img]);
|
src = URL.createObjectURL(monoTextures[mono.img]);
|
||||||
monoTextureUrls[mono.img] = src;
|
monoTextureUrls[mono.img] = src;
|
||||||
} else {
|
} else {
|
||||||
const res = await fetch(mono.img);
|
const res = await window.fetch(mono.img);
|
||||||
const blob = await res.blob();
|
const blob = await res.blob();
|
||||||
monoTextures[mono.img] = blob;
|
monoTextures[mono.img] = blob;
|
||||||
src = URL.createObjectURL(blob);
|
src = URL.createObjectURL(blob);
|
||||||
|
|
|
@ -4,14 +4,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MkStickyContainer>
|
<MkPageWithAnimBg>
|
||||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
<MkSpacer :contentMax="550" :marginMax="50">
|
||||||
<MkSpacer :contentMax="500">
|
|
||||||
<MkLoading v-if="uiPhase === 'fetching'"/>
|
<MkLoading v-if="uiPhase === 'fetching'"/>
|
||||||
<MkExtensionInstaller v-else-if="uiPhase === 'confirm' && data" :extension="data" @confirm="install()">
|
<MkExtensionInstaller v-else-if="uiPhase === 'confirm' && data" :extension="data" @confirm="install()" @cancel="close_()">
|
||||||
<template #additionalInfo>
|
<template #additionalInfo>
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
|
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<MkKeyValue>
|
<MkKeyValue>
|
||||||
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
|
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
|
||||||
|
@ -35,12 +33,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<h2 :class="$style.extInstallerTitle">{{ errorKV?.title }}</h2>
|
<h2 :class="$style.extInstallerTitle">{{ errorKV?.title }}</h2>
|
||||||
<div :class="$style.extInstallerNormDesc">{{ errorKV?.description }}</div>
|
<div :class="$style.extInstallerNormDesc">{{ errorKV?.description }}</div>
|
||||||
<div class="_buttonsCenter">
|
<div class="_buttonsCenter">
|
||||||
<MkButton @click="goBack()">{{ i18n.ts.goBack }}</MkButton>
|
<MkButton @click="close_()">{{ i18n.ts.close }}</MkButton>
|
||||||
<MkButton @click="goToMisskey()">{{ i18n.ts.goToMisskey }}</MkButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
</MkStickyContainer>
|
</MkPageWithAnimBg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -60,6 +57,7 @@ import { parseThemeCode, installTheme } from '@/theme.js';
|
||||||
import { unisonReload } from '@/utility/unison-reload.js';
|
import { unisonReload } from '@/utility/unison-reload.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePage } from '@/page.js';
|
import { definePage } from '@/page.js';
|
||||||
|
import MkPageWithAnimBg from '@/components/MkPageWithAnimBg.vue';
|
||||||
|
|
||||||
const uiPhase = ref<'fetching' | 'confirm' | 'error'>('fetching');
|
const uiPhase = ref<'fetching' | 'confirm' | 'error'>('fetching');
|
||||||
const errorKV = ref<{
|
const errorKV = ref<{
|
||||||
|
@ -75,12 +73,12 @@ const hash = ref<string | null>(null);
|
||||||
|
|
||||||
const data = ref<Extension | null>(null);
|
const data = ref<Extension | null>(null);
|
||||||
|
|
||||||
function goBack(): void {
|
function close_(): void {
|
||||||
history.back();
|
if (window.history.length === 1) {
|
||||||
}
|
window.close();
|
||||||
|
} else {
|
||||||
function goToMisskey(): void {
|
window.history.back();
|
||||||
location.href = '/';
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
|
@ -207,9 +205,9 @@ async function install() {
|
||||||
try {
|
try {
|
||||||
await installPlugin(data.value.raw, data.value.meta as AiScriptPluginMeta);
|
await installPlugin(data.value.raw, data.value.meta as AiScriptPluginMeta);
|
||||||
os.success();
|
os.success();
|
||||||
nextTick(() => {
|
window.setTimeout(() => {
|
||||||
unisonReload('/');
|
close_();
|
||||||
});
|
}, 3000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorKV.value = {
|
errorKV.value = {
|
||||||
title: i18n.ts._externalResourceInstaller._errors._pluginInstallFailed.title,
|
title: i18n.ts._externalResourceInstaller._errors._pluginInstallFailed.title,
|
||||||
|
@ -223,9 +221,9 @@ async function install() {
|
||||||
if (!data.value.meta) return;
|
if (!data.value.meta) return;
|
||||||
await installTheme(data.value.raw);
|
await installTheme(data.value.raw);
|
||||||
os.success();
|
os.success();
|
||||||
nextTick(() => {
|
window.setTimeout(() => {
|
||||||
location.href = '/settings/theme';
|
close_();
|
||||||
});
|
}, 3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,10 +232,6 @@ url.value = urlParams.get('url');
|
||||||
hash.value = urlParams.get('hash');
|
hash.value = urlParams.get('hash');
|
||||||
fetch();
|
fetch();
|
||||||
|
|
||||||
const headerActions = computed(() => []);
|
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
|
||||||
|
|
||||||
definePage(() => ({
|
definePage(() => ({
|
||||||
title: i18n.ts._externalResourceInstaller.title,
|
title: i18n.ts._externalResourceInstaller.title,
|
||||||
icon: 'ti ti-download',
|
icon: 'ti ti-download',
|
||||||
|
|
|
@ -31,7 +31,7 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
const state = ref<'fetching' | 'done'>('fetching');
|
const state = ref<'fetching' | 'done'>('fetching');
|
||||||
|
|
||||||
function fetch() {
|
function fetch() {
|
||||||
const params = new URL(location.href).searchParams;
|
const params = new URL(window.location.href).searchParams;
|
||||||
|
|
||||||
// acctのほうはdeprecated
|
// acctのほうはdeprecated
|
||||||
let uri = params.get('uri') ?? params.get('acct');
|
let uri = params.get('uri') ?? params.get('acct');
|
||||||
|
@ -76,12 +76,12 @@ function close(): void {
|
||||||
|
|
||||||
// 閉じなければ100ms後タイムラインに
|
// 閉じなければ100ms後タイムラインに
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
location.href = '/';
|
window.location.href = '/';
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToMisskey(): void {
|
function goToMisskey(): void {
|
||||||
location.href = '/';
|
window.location.href = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch();
|
fetch();
|
||||||
|
|
|
@ -4,8 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MkPageWithAnimBg>
|
||||||
<MkAnimBg style="position: fixed; top: 0;"/>
|
|
||||||
<div :class="$style.formContainer">
|
<div :class="$style.formContainer">
|
||||||
<div :class="$style.form">
|
<div :class="$style.form">
|
||||||
<MkAuthConfirm
|
<MkAuthConfirm
|
||||||
|
@ -25,16 +24,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkAuthConfirm>
|
</MkAuthConfirm>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</MkPageWithAnimBg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, useTemplateRef } from 'vue';
|
import { computed, useTemplateRef } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import MkPageWithAnimBg from '@/components/MkPageWithAnimBg.vue';
|
||||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
|
||||||
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
||||||
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
import { definePage } from '@/page.js';
|
import { definePage } from '@/page.js';
|
||||||
|
@ -64,7 +61,7 @@ async function onAccept(token: string) {
|
||||||
const cbUrl = new URL(props.callback);
|
const cbUrl = new URL(props.callback);
|
||||||
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(cbUrl.protocol)) throw new Error('invalid url');
|
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(cbUrl.protocol)) throw new Error('invalid url');
|
||||||
cbUrl.searchParams.set('session', props.session);
|
cbUrl.searchParams.set('session', props.session);
|
||||||
location.href = cbUrl.toString();
|
window.location.href = cbUrl.toString();
|
||||||
} else {
|
} else {
|
||||||
authRoot.value?.showUI('success');
|
authRoot.value?.showUI('success');
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MkPageWithAnimBg>
|
||||||
<MkAnimBg style="position: fixed; top: 0;"/>
|
|
||||||
<div :class="$style.formContainer">
|
<div :class="$style.formContainer">
|
||||||
<div :class="$style.form">
|
<div :class="$style.form">
|
||||||
<MkAuthConfirm
|
<MkAuthConfirm
|
||||||
|
@ -19,12 +18,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</MkPageWithAnimBg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
import MkPageWithAnimBg from '@/components/MkPageWithAnimBg.vue';
|
||||||
import { definePage } from '@/page.js';
|
import { definePage } from '@/page.js';
|
||||||
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
|
||||||
|
|
||||||
|
|
|
@ -182,12 +182,12 @@ function close(): void {
|
||||||
|
|
||||||
// 閉じなければ100ms後タイムラインに
|
// 閉じなければ100ms後タイムラインに
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
location.href = '/';
|
window.location.href = '/';
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goToMisskey(): void {
|
function goToMisskey(): void {
|
||||||
location.href = '/';
|
window.location.href = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPosted(): void {
|
function onPosted(): void {
|
||||||
|
|
|
@ -4,8 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MkPageWithAnimBg>
|
||||||
<MkAnimBg style="position: fixed; top: 0;"/>
|
|
||||||
<div :class="$style.formContainer">
|
<div :class="$style.formContainer">
|
||||||
<form :class="$style.form" class="_panel" @submit.prevent="submit()">
|
<form :class="$style.form" class="_panel" @submit.prevent="submit()">
|
||||||
<div :class="$style.banner">
|
<div :class="$style.banner">
|
||||||
|
@ -21,13 +20,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</MkPageWithAnimBg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
import MkPageWithAnimBg from '@/components/MkPageWithAnimBg.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
|
@ -64,8 +63,8 @@ function submit() {
|
||||||
min-height: 100svh;
|
min-height: 100svh;
|
||||||
padding: 32px 32px 64px 32px;
|
padding: 32px 32px 64px 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-content: center;
|
place-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
|
|
|
@ -4,8 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MkPageWithAnimBg>
|
||||||
<MkAnimBg style="position: fixed; top: 0;"/>
|
|
||||||
<div :class="$style.formContainer">
|
<div :class="$style.formContainer">
|
||||||
<form :class="$style.form" class="_panel" @submit.prevent="submit()">
|
<form :class="$style.form" class="_panel" @submit.prevent="submit()">
|
||||||
<div :class="$style.title">
|
<div :class="$style.title">
|
||||||
|
@ -35,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</MkPageWithAnimBg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -46,7 +45,7 @@ import MkInput from '@/components/MkInput.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkAnimBg from '@/components/MkAnimBg.vue';
|
import MkPageWithAnimBg from '@/components/MkPageWithAnimBg.vue';
|
||||||
import { login } from '@/accounts.js';
|
import { login } from '@/accounts.js';
|
||||||
|
|
||||||
const username = ref('');
|
const username = ref('');
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import type { PreferencesProfile, StorageProvider } from '@/preferences/manager.js';
|
import type { PreferencesProfile, StorageProvider } from '@/preferences/manager.js';
|
||||||
import { cloudBackup } from '@/preferences/utility.js';
|
import { cloudBackup } from '@/preferences/utility.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
@ -11,8 +10,7 @@ import { isSameScope, PreferencesManager } from '@/preferences/manager.js';
|
||||||
import { store } from '@/store.js';
|
import { store } from '@/store.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||||
|
import { TAB_ID } from '@/tab-id.js';
|
||||||
const TAB_ID = uuid();
|
|
||||||
|
|
||||||
function createPrefManager(storageProvider: StorageProvider) {
|
function createPrefManager(storageProvider: StorageProvider) {
|
||||||
let profile: PreferencesProfile;
|
let profile: PreferencesProfile;
|
||||||
|
|
|
@ -32,6 +32,8 @@ export type SoundStore = {
|
||||||
// NOTE: デフォルト値は他の設定の状態に依存してはならない(依存していた場合、ユーザーがその設定項目単体で「初期値にリセット」した場合不具合の原因になる)
|
// NOTE: デフォルト値は他の設定の状態に依存してはならない(依存していた場合、ユーザーがその設定項目単体で「初期値にリセット」した場合不具合の原因になる)
|
||||||
|
|
||||||
export const PREF_DEF = {
|
export const PREF_DEF = {
|
||||||
|
// TODO: 持つのはホストやユーザーID、ユーザー名など最低限にしといて、その他のプロフィール情報はpreferences外で管理した方が綺麗そう
|
||||||
|
// 現状だと、updateCurrentAccount/updateCurrentAccountPartialが呼ばれるたびに「設定」へのcommitが行われて不自然(明らかに設定の更新とは捉えにくい)だし
|
||||||
accounts: {
|
accounts: {
|
||||||
default: [] as [host: string, user: Misskey.entities.User][],
|
default: [] as [host: string, user: Misskey.entities.User][],
|
||||||
},
|
},
|
||||||
|
|
|
@ -139,9 +139,16 @@ export class PreferencesManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public commit<K extends keyof PREF>(key: K, value: ValueOf<K>) {
|
public commit<K extends keyof PREF>(key: K, value: ValueOf<K>) {
|
||||||
console.log('prefer:commit', key, value);
|
const v = JSON.parse(JSON.stringify(value)); // deep copy 兼 vueのプロキシ解除
|
||||||
|
|
||||||
this.rewriteRawState(key, value);
|
if (deepEqual(this.s[key], v)) {
|
||||||
|
console.log('(skip) prefer:commit', key, v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('prefer:commit', key, v);
|
||||||
|
|
||||||
|
this.rewriteRawState(key, v);
|
||||||
|
|
||||||
const record = this.getMatchedRecordOf(key);
|
const record = this.getMatchedRecordOf(key);
|
||||||
|
|
||||||
|
@ -149,7 +156,7 @@ export class PreferencesManager {
|
||||||
this.profile.preferences[key].push([makeScope({
|
this.profile.preferences[key].push([makeScope({
|
||||||
server: host,
|
server: host,
|
||||||
account: $i!.id,
|
account: $i!.id,
|
||||||
}), value, {}]);
|
}), v, {}]);
|
||||||
this.save();
|
this.save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -157,12 +164,12 @@ export class PreferencesManager {
|
||||||
if (parseScope(record[0]).server == null && this.isServerDependentKey(key)) {
|
if (parseScope(record[0]).server == null && this.isServerDependentKey(key)) {
|
||||||
this.profile.preferences[key].push([makeScope({
|
this.profile.preferences[key].push([makeScope({
|
||||||
server: host,
|
server: host,
|
||||||
}), value, {}]);
|
}), v, {}]);
|
||||||
this.save();
|
this.save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
record[1] = value;
|
record[1] = v;
|
||||||
this.save();
|
this.save();
|
||||||
|
|
||||||
if (record[2].sync) {
|
if (record[2].sync) {
|
||||||
|
|
|
@ -17,10 +17,10 @@ export function createRouter(fullPath: string): Router {
|
||||||
return new Nirax(ROUTE_DEF, fullPath, !!$i, page(() => import('@/pages/not-found.vue')));
|
return new Nirax(ROUTE_DEF, fullPath, !!$i, page(() => import('@/pages/not-found.vue')));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mainRouter = createRouter(location.pathname + location.search + location.hash);
|
export const mainRouter = createRouter(window.location.pathname + window.location.search + window.location.hash);
|
||||||
|
|
||||||
window.addEventListener('popstate', (event) => {
|
window.addEventListener('popstate', (event) => {
|
||||||
mainRouter.replace(location.pathname + location.search + location.hash);
|
mainRouter.replace(window.location.pathname + window.location.search + window.location.hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
mainRouter.addListener('push', ctx => {
|
mainRouter.addListener('push', ctx => {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
// HMR有効時にバグか知らんけど複数回実行されるのでその対策
|
||||||
|
export const TAB_ID = window.sessionStorage.getItem('TAB_ID') ?? uuid();
|
||||||
|
window.sessionStorage.setItem('TAB_ID', TAB_ID);
|
||||||
|
console.log('TAB_ID', TAB_ID);
|
|
@ -34,7 +34,7 @@ function resetDisconnected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
useStream().on('_disconnected_', onDisconnected);
|
useStream().on('_disconnected_', onDisconnected);
|
||||||
|
|
|
@ -139,7 +139,7 @@ if (window.innerWidth < 1024) {
|
||||||
const currentUI = miLocalStorage.getItem('ui');
|
const currentUI = miLocalStorage.getItem('ui');
|
||||||
miLocalStorage.setItem('ui_temp', currentUI ?? 'default');
|
miLocalStorage.setItem('ui_temp', currentUI ?? 'default');
|
||||||
miLocalStorage.setItem('ui', 'default');
|
miLocalStorage.setItem('ui', 'default');
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.documentElement.style.overflowY = 'scroll';
|
document.documentElement.style.overflowY = 'scroll';
|
||||||
|
|
|
@ -5,9 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.root">
|
<div :class="$style.root">
|
||||||
<div style="height: 100%;">
|
|
||||||
<RouterView/>
|
<RouterView/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<XCommon/>
|
<XCommon/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,12 +37,11 @@ provideMetadataReceiver((metadataGetter) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
provideReactiveMetadata(pageMetadata);
|
provideReactiveMetadata(pageMetadata);
|
||||||
|
|
||||||
document.documentElement.style.overflowY = 'scroll';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.root {
|
.root {
|
||||||
min-height: 100dvh;
|
position: relative;
|
||||||
|
height: 100dvh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -170,7 +170,7 @@ if (window.innerWidth > 1024) {
|
||||||
if (tempUI) {
|
if (tempUI) {
|
||||||
miLocalStorage.setItem('ui', tempUI);
|
miLocalStorage.setItem('ui', tempUI);
|
||||||
miLocalStorage.removeItem('ui_temp');
|
miLocalStorage.removeItem('ui_temp');
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ const isRoot = computed(() => mainRouter.currentRoute.value.name === 'index');
|
||||||
|
|
||||||
const pageMetadata = ref<null | PageMetadata>(null);
|
const pageMetadata = ref<null | PageMetadata>(null);
|
||||||
|
|
||||||
const showBottom = !(new URLSearchParams(location.search)).has('zen') && ui === 'deck';
|
const showBottom = !(new URLSearchParams(window.location.search)).has('zen') && ui === 'deck';
|
||||||
|
|
||||||
provide(DI.router, mainRouter);
|
provide(DI.router, mainRouter);
|
||||||
provideMetadataReceiver((metadataGetter) => {
|
provideMetadataReceiver((metadataGetter) => {
|
||||||
|
|
|
@ -35,6 +35,6 @@ export async function reloadAsk(opts: {
|
||||||
if (opts.unison) {
|
if (opts.unison) {
|
||||||
unisonReload();
|
unisonReload();
|
||||||
} else {
|
} else {
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ export async function loadAudio(url: string, options?: { useCache?: boolean; })
|
||||||
let response: Response;
|
let response: Response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await fetch(url);
|
response = await window.fetch(url);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ export const reloadChannel = new BroadcastChannel<string | null>('reload');
|
||||||
export function unisonReload(path?: string) {
|
export function unisonReload(path?: string) {
|
||||||
if (path !== undefined) {
|
if (path !== undefined) {
|
||||||
reloadChannel.postMessage(path);
|
reloadChannel.postMessage(path);
|
||||||
location.href = path;
|
window.location.href = path;
|
||||||
} else {
|
} else {
|
||||||
reloadChannel.postMessage(null);
|
reloadChannel.postMessage(null);
|
||||||
location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"name": "misskey-js",
|
"name": "misskey-js",
|
||||||
"version": "2025.3.2-beta.4",
|
"version": "2025.3.2-beta.6",
|
||||||
"description": "Misskey SDK for JavaScript",
|
"description": "Misskey SDK for JavaScript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
|
|
Loading…
Reference in New Issue