Compare commits
	
		
			18 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 000f876084 | ||
|   | 2d11c558fa | ||
|   | ac6b02af40 | ||
|   | 7d91912cfd | ||
|   | 3c504b4b08 | ||
|   | adad4bcfe3 | ||
|   | b3e8671dd9 | ||
|   | 0f8c890761 | ||
|   | 512e451f24 | ||
|   | ca0d53ec5d | ||
|   | 686a709e87 | ||
|   | 83fb629f0b | ||
|   | 35eeeb25e3 | ||
|   | 19035c676c | ||
|   | 61ffe7417c | ||
|   | 7651353f39 | ||
|   | 3f5b81060f | ||
|   | 63dc66769f | 
							
								
								
									
										11
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -8,6 +8,17 @@ | ||||
|  | ||||
| You should also include the user name that made the change. | ||||
| --> | ||||
| ## 13.5.6 (2023/02/10) | ||||
|  | ||||
| ### Improvements | ||||
| - 非ログイン時にMiAuthを踏んだ際にMiAuthであることを表示する | ||||
| - /auth/のUIをアップデート | ||||
| - 利用規約同意UIの調整 | ||||
| - クロップ時の質問を分かりやすく | ||||
|  | ||||
| ### Bugfixes | ||||
| - fix: prevent clipping audio plyr's tooltip | ||||
|  | ||||
| ## 13.5.4 (2023/02/09) | ||||
|  | ||||
| ### Improvements | ||||
|   | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "Möchtest du diese Blockierung wirklich aufheben?" | ||||
| suspendConfirm: "Möchtest du diesen Benutzer wirklich sperren?" | ||||
| unsuspendConfirm: "Möchtest du diesen Benutzer wirklich entsperren?" | ||||
| selectList: "Liste auswählen" | ||||
| selectChannel: "Kanal auswählen" | ||||
| selectAntenna: "Antenne auswählen" | ||||
| selectWidget: "Widget auswählen" | ||||
| editWidgets: "Widgets bearbeiten" | ||||
| @@ -256,6 +257,8 @@ noMoreHistory: "Kein weiterer Verlauf vorhanden" | ||||
| startMessaging: "Neuen Chat erstellen" | ||||
| nUsersRead: "Von {n} Benutzern gelesen" | ||||
| agreeTo: "Ich stimme {0} zu" | ||||
| agreeBelow: "Ich stimme Untenstehendem zu" | ||||
| basicNotesBeforeCreateAccount: "Wichtige Infos" | ||||
| tos: "Nutzungsbedingungen" | ||||
| start: "Anfangen" | ||||
| home: "Startseite" | ||||
| @@ -861,6 +864,8 @@ failedToFetchAccountInformation: "Benutzerkontoinformationen konnten nicht abgef | ||||
| rateLimitExceeded: "Versuchsanzahl überschritten" | ||||
| cropImage: "Bild zuschneiden" | ||||
| cropImageAsk: "Möchtest du das Bild zuschneiden?" | ||||
| cropYes: "Zuschneiden" | ||||
| cropNo: "Unbearbeitet verwenden" | ||||
| file: "Datei" | ||||
| recentNHours: "Letzten {n} Stunden" | ||||
| recentNDays: "Letzten {n} Tage" | ||||
| @@ -939,6 +944,8 @@ cannotPerformTemporaryDescription: "Diese Aktion ist wegen des Überschreitenes | ||||
| preset: "Vorlage" | ||||
| selectFromPresets: "Aus Vorlagen wählen" | ||||
| achievements: "Errungenschaften" | ||||
| gotInvalidResponseError: "Ungültige Antwort des Servers" | ||||
| gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal." | ||||
| _achievements: | ||||
|   earnedAt: "Freigeschaltet am" | ||||
|   _types: | ||||
| @@ -1593,12 +1600,15 @@ _permissions: | ||||
|   "read:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge lesen" | ||||
|   "write:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge bearbeiten" | ||||
| _auth: | ||||
|   shareAccessTitle: "Verteilung von App-Berechtigungen" | ||||
|   shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?" | ||||
|   shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?" | ||||
|   permission: "{name} fordert folgende Berechtigungen" | ||||
|   permissionAsk: "Diese Anwendung fordert folgende Berechtigungen" | ||||
|   pleaseGoBack: "Bitte kehre zur Anwendung zurück" | ||||
|   callback: "Es wird zur Anwendung zurückgekehrt" | ||||
|   denied: "Zugriff verweigert" | ||||
|   pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren." | ||||
| _antennaSources: | ||||
|   all: "Alle Notizen" | ||||
|   homeTimeline: "Notizen von Benutzern, denen gefolgt wird" | ||||
| @@ -1869,6 +1879,6 @@ _deck: | ||||
|     tl: "Chronik" | ||||
|     antenna: "Antennen" | ||||
|     list: "Listen" | ||||
|     channel: "Kanäle" | ||||
|     channel: "Kanal" | ||||
|     mentions: "Erwähnungen" | ||||
|     direct: "Direktnachrichten" | ||||
|   | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "Are you sure that you want to unblock this account?" | ||||
| suspendConfirm: "Are you sure that you want to suspend this account?" | ||||
| unsuspendConfirm: "Are you sure that you want to unsuspend this account?" | ||||
| selectList: "Select a list" | ||||
| selectChannel: "Select a channel" | ||||
| selectAntenna: "Select an antenna" | ||||
| selectWidget: "Select a widget" | ||||
| editWidgets: "Edit widgets" | ||||
| @@ -256,6 +257,8 @@ noMoreHistory: "There is no further history" | ||||
| startMessaging: "Start a new chat" | ||||
| nUsersRead: "read by {n}" | ||||
| agreeTo: "I agree to {0}" | ||||
| agreeBelow: "I agree to the below" | ||||
| basicNotesBeforeCreateAccount: "Important notes" | ||||
| tos: "Terms of Service" | ||||
| start: "Begin" | ||||
| home: "Home" | ||||
| @@ -861,6 +864,8 @@ failedToFetchAccountInformation: "Could not fetch account information" | ||||
| rateLimitExceeded: "Rate limit exceeded" | ||||
| cropImage: "Crop image" | ||||
| cropImageAsk: "Do you want to crop this image?" | ||||
| cropYes: "Crop" | ||||
| cropNo: "Use as-is" | ||||
| file: "File" | ||||
| recentNHours: "Last {n} hours" | ||||
| recentNDays: "Last {n} days" | ||||
| @@ -939,6 +944,8 @@ cannotPerformTemporaryDescription: "This action cannot be performed temporarily | ||||
| preset: "Preset" | ||||
| selectFromPresets: "Choose from presets" | ||||
| achievements: "Achievements" | ||||
| gotInvalidResponseError: "Invalid server response" | ||||
| gotInvalidResponseErrorDescription: "The server may be unreachable or undergoing maintenance. Please try again later." | ||||
| _achievements: | ||||
|   earnedAt: "Unlocked at" | ||||
|   _types: | ||||
| @@ -1593,12 +1600,15 @@ _permissions: | ||||
|   "read:gallery-likes": "View your list of liked gallery posts" | ||||
|   "write:gallery-likes": "Edit your list of liked gallery posts" | ||||
| _auth: | ||||
|   shareAccessTitle: "Granting application permissions" | ||||
|   shareAccess: "Would you like to authorize \"{name}\" to access this account?" | ||||
|   shareAccessAsk: "Are you sure you want to authorize this application to access your account?" | ||||
|   permission: "{name} requests the following permissions" | ||||
|   permissionAsk: "This application requests the following permissions" | ||||
|   pleaseGoBack: "Please go back to the application" | ||||
|   callback: "Returning to the application" | ||||
|   denied: "Access denied" | ||||
|   pleaseLogin: "Please log in to authorize applications." | ||||
| _antennaSources: | ||||
|   all: "All notes" | ||||
|   homeTimeline: "Notes from followed users" | ||||
| @@ -1869,6 +1879,6 @@ _deck: | ||||
|     tl: "Timeline" | ||||
|     antenna: "Antennas" | ||||
|     list: "List" | ||||
|     channel: "Channels" | ||||
|     channel: "Channel" | ||||
|     mentions: "Mentions" | ||||
|     direct: "Direct notes" | ||||
|   | ||||
| @@ -56,7 +56,7 @@ reply: "Responder" | ||||
| loadMore: "Ver más" | ||||
| showMore: "Ver más" | ||||
| showLess: "Cerrar" | ||||
| youGotNewFollower: "te ha seguido" | ||||
| youGotNewFollower: "ahora te sigue" | ||||
| receiveFollowRequest: "Recibiste una solicitud de seguimiento" | ||||
| followRequestAccepted: "La solicitud de seguimiento fue aceptada" | ||||
| mention: "Menciones" | ||||
| @@ -257,6 +257,8 @@ noMoreHistory: "El historial se ha acabado" | ||||
| startMessaging: "Iniciar chat" | ||||
| nUsersRead: "Leído por {n} personas" | ||||
| agreeTo: "De acuerdo con {0}" | ||||
| agreeBelow: "Estoy de acuerdo con lo siguiente" | ||||
| basicNotesBeforeCreateAccount: "Notas básicas" | ||||
| tos: "Términos de uso" | ||||
| start: "Comenzar" | ||||
| home: "Inicio" | ||||
| @@ -940,6 +942,8 @@ cannotPerformTemporaryDescription: "Esta acción no se puede realizar porque se | ||||
| preset: "Predefinido" | ||||
| selectFromPresets: "Escoger desde predefinidos" | ||||
| achievements: "Logros" | ||||
| gotInvalidResponseError: "Respuesta del servidor inválida" | ||||
| gotInvalidResponseErrorDescription: "Puede que el servidor esté caído o en mantenimiento. Favor de intentar más tarde" | ||||
| _achievements: | ||||
|   earnedAt: "Desbloqueado el" | ||||
|   _types: | ||||
| @@ -1594,12 +1598,15 @@ _permissions: | ||||
|   "read:gallery-likes": "Ver favoritos de la galería" | ||||
|   "write:gallery-likes": "Editar favoritos de la galería" | ||||
| _auth: | ||||
|   shareAccessTitle: "Permisos de la aplicación" | ||||
|   shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?" | ||||
|   shareAccessAsk: "¿Está seguro de que desea autorizar esta aplicación para acceder a su cuenta?" | ||||
|   permission: "{name} solicita los siguientes permisos" | ||||
|   permissionAsk: "Esta aplicación requiere los siguientes permisos" | ||||
|   pleaseGoBack: "Por favor, vuelve a la aplicación" | ||||
|   callback: "Volviendo a la aplicación" | ||||
|   denied: "Acceso denegado" | ||||
|   pleaseLogin: "Se requiere un inicio de sesión para darle permisos a la aplicación" | ||||
| _antennaSources: | ||||
|   all: "Todas las notas" | ||||
|   homeTimeline: "Notas de los usuarios que sigues" | ||||
|   | ||||
| @@ -257,6 +257,8 @@ noMoreHistory: "これより過去の履歴はありません" | ||||
| startMessaging: "チャットを開始" | ||||
| nUsersRead: "{n}人が読みました" | ||||
| agreeTo: "{0}に同意" | ||||
| agreeBelow: "下記に同意する" | ||||
| basicNotesBeforeCreateAccount: "基本的な注意事項" | ||||
| tos: "利用規約" | ||||
| start: "始める" | ||||
| home: "ホーム" | ||||
| @@ -862,6 +864,8 @@ failedToFetchAccountInformation: "アカウント情報の取得に失敗しま | ||||
| rateLimitExceeded: "レート制限を超えました" | ||||
| cropImage: "画像のクロップ" | ||||
| cropImageAsk: "画像をクロップしますか?" | ||||
| cropYes: "クロップする" | ||||
| cropNo: "そのまま使う" | ||||
| file: "ファイル" | ||||
| recentNHours: "直近{n}時間" | ||||
| recentNDays: "直近{n}日" | ||||
| @@ -1628,12 +1632,15 @@ _permissions: | ||||
|   "write:gallery-likes": "ギャラリーのいいねを操作する" | ||||
|  | ||||
| _auth: | ||||
|   shareAccessTitle: "アプリへのアクセス許可" | ||||
|   shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" | ||||
|   shareAccessAsk: "アカウントへのアクセスを許可しますか?" | ||||
|   permission: "{name}は次の権限を要求しています" | ||||
|   permissionAsk: "このアプリは次の権限を要求しています" | ||||
|   pleaseGoBack: "アプリケーションに戻ってやっていってください" | ||||
|   callback: "アプリケーションに戻っています" | ||||
|   denied: "アクセスを拒否しました" | ||||
|   pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。" | ||||
|  | ||||
| _antennaSources: | ||||
|   all: "全てのノート" | ||||
|   | ||||
| @@ -46,7 +46,7 @@ copyContent: "内容をコピー" | ||||
| copyLink: "リンクをコピー" | ||||
| delete: "ほかす" | ||||
| deleteAndEdit: "ほかして直す" | ||||
| deleteAndEditConfirm: "このノートをほかして書き直すんか?このノートへのリアクション、Renote、返信も全部消えてまうで。" | ||||
| deleteAndEditConfirm: "このノートをほかしてもっかい直す?このノートへのリアクション、Renote、返信も全部消えるんやけどそれでもええん?" | ||||
| addToList: "リストに入れたる" | ||||
| sendMessage: "メッセージを送る" | ||||
| copyRSS: "RSSをコピー" | ||||
| @@ -89,7 +89,7 @@ serverIsDead: "サーバーからの応答がないで。もうちょい待っ | ||||
| youShouldUpgradeClient: "このページを表示するには、リロードして新しいバージョンのクライアントを使ってなー。" | ||||
| enterListName: "リスト名を入れてや" | ||||
| privacy: "プライバシー" | ||||
| makeFollowManuallyApprove: "自分が認めた人だけがこのアカウントをフォローできるようにする" | ||||
| makeFollowManuallyApprove: "他人のフォローは許可してからや!" | ||||
| defaultNoteVisibility: "もとからの公開範囲" | ||||
| follow: "フォロー" | ||||
| followRequest: "フォローを頼む" | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "ブロックやめたるってほんまか?" | ||||
| suspendConfirm: "凍結してしもうてええか?" | ||||
| unsuspendConfirm: "解凍するけどええか?" | ||||
| selectList: "リストを選ぶ" | ||||
| selectChannel: "チャンネルを選ぶ" | ||||
| selectAntenna: "アンテナを選ぶ" | ||||
| selectWidget: "ウィジェットを選ぶ" | ||||
| editWidgets: "ウィジェットをいじる" | ||||
| @@ -256,6 +257,8 @@ noMoreHistory: "これより過去の履歴はあらへんで" | ||||
| startMessaging: "チャットやるで" | ||||
| nUsersRead: "{n}人が読んでもうた" | ||||
| agreeTo: "{0}に同意したで" | ||||
| agreeBelow: "下記に同意したる" | ||||
| basicNotesBeforeCreateAccount: "よう読んでやってや" | ||||
| tos: "利用規約" | ||||
| start: "始める" | ||||
| home: "ホーム" | ||||
| @@ -300,7 +303,7 @@ avatar: "アイコン" | ||||
| banner: "バナー" | ||||
| nsfw: "閲覧注意" | ||||
| whenServerDisconnected: "サーバーとの接続が切れたとき" | ||||
| disconnectedFromServer: "サーバーとの通信が切れたで" | ||||
| disconnectedFromServer: "サーバーが機嫌悪いねん" | ||||
| reload: "リロード" | ||||
| doNothing: "何もせんとく" | ||||
| reloadConfirm: "リロードしてええか?" | ||||
| @@ -673,8 +676,8 @@ sentReactionsCount: "リアクションした数やで" | ||||
| receivedReactionsCount: "リアクションされた数" | ||||
| pollVotesCount: "アンケートに投票した数" | ||||
| pollVotedCount: "アンケートに投票された数" | ||||
| yes: "はい" | ||||
| no: "いいえ" | ||||
| yes: "ええで" | ||||
| no: "あかんで" | ||||
| driveFilesCount: "ドライブのファイル数" | ||||
| driveUsage: "ドライブ使用量やで" | ||||
| noCrawle: "クローラーによるインデックスを拒否するで" | ||||
| @@ -861,6 +864,8 @@ failedToFetchAccountInformation: "アカウントの取得に失敗したみた | ||||
| rateLimitExceeded: "レート制限が超えたみたいやで" | ||||
| cropImage: "画像のクロップ" | ||||
| cropImageAsk: "画像をクロップしたってええか?" | ||||
| cropYes: "切り抜いたる" | ||||
| cropNo: "切り抜かへん" | ||||
| file: "ファイル" | ||||
| recentNHours: "直近{n}時間" | ||||
| recentNDays: "直近{n}日" | ||||
| @@ -938,6 +943,37 @@ cannotPerformTemporary: "一時的に利用できへんで" | ||||
| cannotPerformTemporaryDescription: "操作回数が制限を超えたから一時的に利用できへんくなったで。ちょっと時間置いてからもう一回やってやー。" | ||||
| preset: "プリセット" | ||||
| selectFromPresets: "プリセットから選ぶ" | ||||
| achievements: "実績" | ||||
| gotInvalidResponseError: "サーバー黙っとるわ、知らんけど" | ||||
| gotInvalidResponseErrorDescription: "サーバーいま日曜日。またきて月曜日。" | ||||
| _achievements: | ||||
|   earnedAt: "貰った日ぃ" | ||||
|   _types: | ||||
|     _notes1: | ||||
|       title: "まいど!" | ||||
|       description: "初めてノート投稿したった" | ||||
|     _notes10: | ||||
|       title: "ノートの天保山" | ||||
|     _notes100: | ||||
|       title: "ノートの真田山" | ||||
|     _notes500: | ||||
|       title: "ノートの生駒山" | ||||
|     _notes5000: | ||||
|       title: "箕面の滝からノート" | ||||
|     _login3: | ||||
|       flavor: "今日からワシはミスキストやで" | ||||
|     _iLoveMisskey: | ||||
|       title: "Misskey好きやねん" | ||||
|     _foundTreasure: | ||||
|       title: "なんでも鑑定団" | ||||
|     _client30min: | ||||
|       title: "ねんね" | ||||
|     _noteDeletedWithin1min: | ||||
|       title: "*おおっと*" | ||||
|     _open3windows: | ||||
|       title: "マド開けすぎ" | ||||
|     _driveFolderCircularReference: | ||||
|       title: "環状線" | ||||
| _role: | ||||
|   new: "ロールの作成" | ||||
|   edit: "ロールの編集" | ||||
| @@ -1355,10 +1391,12 @@ _permissions: | ||||
| _auth: | ||||
|   shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?" | ||||
|   shareAccessAsk: "アカウントのアクセスを許可してもええか?" | ||||
|   permission: "{name}に次の権限つけたってやって" | ||||
|   permissionAsk: "このアプリは次の権限を要求しとるで" | ||||
|   pleaseGoBack: "アプリケーションに戻ってええよ" | ||||
|   callback: "アプリケーションに戻っとるで" | ||||
|   denied: "アクセスを拒否ったで" | ||||
|   pleaseLogin: "アプリにアクセスさせるんやったら、ログインしてや。" | ||||
| _antennaSources: | ||||
|   all: "みんなのノート" | ||||
|   homeTimeline: "フォローしとるユーザーのノート" | ||||
| @@ -1587,6 +1625,7 @@ _notification: | ||||
|   pollEnded: "アンケートの結果が出たみたいや" | ||||
|   unreadAntennaNote: "アンテナ {name}" | ||||
|   emptyPushNotificationMessage: "プッシュ通知の更新をしといたで" | ||||
|   achievementEarned: "実績を獲得しとるで" | ||||
|   _types: | ||||
|     all: "すべて" | ||||
|     follow: "フォロー" | ||||
|   | ||||
| @@ -49,24 +49,196 @@ deleteAndEdit: "ລົບແລະແກ້ໄຂ" | ||||
| deleteAndEditConfirm: "ເຈົ້າແນ່ໃຈບໍ່? ທີ່ທ່ານຕ້ອງການທີ່ຈະລຶບບັນທຶກນີ້ແລະແກ້ໄຂມັນ ທ່ານອາດຈະສູນເສຍການໂຕ້ຕອບ, ບັນທຶກ, ແລະການຕອບກັບທັງໝົດ" | ||||
| addToList: "ເພີ່ມໃສ່ລາຍຊື່" | ||||
| sendMessage: "ສົ່ງຂໍ້ຄວາມ" | ||||
| copyRSS: "ສຳເນົາ RSS" | ||||
| copyUsername: "ສຳເນົາຊື່ຜູ້ໃຊ້" | ||||
| searchUser: "ຄົ້ນຫາຜູ້ໃຊ້" | ||||
| reply: "ຕອບໄປທີ" | ||||
| loadMore: "ໂຫຼດເພີ່ມເຕີມ" | ||||
| showMore: "ໂຫຼດເພີ່ມເຕີມ" | ||||
| showLess: "ປິດ" | ||||
| youGotNewFollower: "ໄດ້ຕິດຕາມທ່ານ" | ||||
| receiveFollowRequest: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ໄດ້ຮັບ" | ||||
| followRequestAccepted: "ຜູ້ຕິດຕາມໄດ້ຍອມຮັບຄໍາຮ້ອງຂໍຂອງທ່ານ" | ||||
| mention: "ໄດ້ກ່າວມາ" | ||||
| mentions: "ກ່າວເຖິງ" | ||||
| directNotes: "ໂດຍກົງຫມາຍເຫດ" | ||||
| importAndExport: "ນໍາເຂົ້າ / ສົ່ງອອກ" | ||||
| import: "ນຳເຂົ້າ" | ||||
| export: "ນຳອອກ" | ||||
| files: "ໄຟລ໌" | ||||
| download: "ດາວໂຫລດ" | ||||
| driveFileDeleteConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບໄຟລ໌ \"{name}\"? ບັນທຶກທີ່ມີໄຟລ໌ແນບນີ້ຈະຖືກລຶບຖິ້ມ" | ||||
| unfollowConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການເຊົາຕິດຕາມ {name}?" | ||||
| exportRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການສົ່ງອອກ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ ແລະມັນຈະຖືກເພີ່ມໃສ່ drive ຂອງທ່ານເມື່ອມັນສຳເລັດແລ້ວ" | ||||
| importRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການນໍາເຂົ້າ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ" | ||||
| lists: "ລາຍການ" | ||||
| noLists: "ທ່ານບໍ່ມີລາຍການໃດໆ" | ||||
| note: "ບັນທຶກ" | ||||
| notes: "ບັນທຶກ" | ||||
| following: "ກຳລັງຕິດຕາມ" | ||||
| followers: "ຜູ້ຕິດຕາມ" | ||||
| followsYou: "ຕິດຕາມເຈົ້າ" | ||||
| createList: "ສ້າງລາຍຊື່" | ||||
| manageLists: "ການບໍລິຫານບັນຊີລາຍການ" | ||||
| error: "ຂໍ້ຜິດພາດ" | ||||
| somethingHappened: "ອຸຍ, ມີບາງຢ່າງຜິດພາດ" | ||||
| retry: "ລອງໃຫມ່" | ||||
| pageLoadError: "ເກີດຄວາມຜິດພາດໃນການໂຫລດໜ້ານີ້" | ||||
| pageLoadErrorDescription: "ປົກກະຕິແລ້ວມັນເກີດຈາກຄວາມຜິດພາດເຄືອຂ່າຍ ຫຼື cache ຂອງຕົວທ່ອງເວັບ ລອງລຶບລ້າງແຄດແລ້ວລອງໃໝ່ພາຍຫຼັງສອງສາມນາທີ" | ||||
| serverIsDead: "ເຊີບເວີນີ້ບໍ່ຕອບສະໜອງ ກະລຸນາລໍຖ້າຈັກໜ່ອຍແລ້ວລອງໃໝ່ອີກຄັ້ງ" | ||||
| youShouldUpgradeClient: "ເພື່ອເບິ່ງໜ້ານີ້, ກະລຸນາໂຫຼດຂໍ້ມູນຄືນໃໝ່ເພື່ອອັບເດດລູກຄ້າຂອງທ່ານ" | ||||
| enterListName: "ໃສ່ຊື່ສຳລັບລາຍຊື່" | ||||
| privacy: "ຄວາມເປັນສ່ວນຕົວ" | ||||
| makeFollowManuallyApprove: "ປະຕິບັດຕາມການຮ້ອງຂໍຮຽກຮ້ອງໃຫ້ມີການອະນຸມັດ" | ||||
| defaultNoteVisibility: "ເປັນຄ່າເລີ່ມຕົ້ນ" | ||||
| follow: "ກຳລັງຕິດຕາມ" | ||||
| followRequest: "ສົ່ງການຮ້ອງຂໍປະຕິບຕາມ" | ||||
| followRequests: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍ" | ||||
| unfollow: "ເຊົາຕິດຕາມ" | ||||
| followRequestPending: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ລໍຖ້າຢູ່" | ||||
| enterEmoji: "ປ້ອນອີໂມຈິ" | ||||
| renote: "Renote" | ||||
| unrenote: "ເລີກ Renote" | ||||
| renoted: "ເກັບບັນທຶກໄວ້" | ||||
| quote: "ລວມຂໍ້ຄວາມອ້າງອີງ" | ||||
| pinnedNote: "ບັນທຶກທີ່ປັກໝຸດໄວ້" | ||||
| pinned: "ປັກໝຸດໄປຫາໂປຣໄຟລ໌" | ||||
| you: "ເຈົ້າ" | ||||
| clickToShow: "ກົດເພື່ອສະແດງໃຫ້ເຫັນ" | ||||
| sensitive: "NSFW" | ||||
| add: "ເພີ່ມ" | ||||
| reaction: "ປະຕິກິລິຍາ" | ||||
| reactions: "ປະຕິກິລິຍາ" | ||||
| mute: "ປີດສຽງ" | ||||
| unmute: "ເປີດສຽງ" | ||||
| block: "ບ໋ອກ" | ||||
| unblock: "ຍົກເລີກກາຮົບລັອກ" | ||||
| suspend: "ລະງັບ" | ||||
| unsuspend: "ເຊົາລະງັບ" | ||||
| selectList: "ເລືອກບັນຊີລາຍການ" | ||||
| selectWidget: "ເລືອກວິກເຈັດ" | ||||
| editWidgets: "ແກ້ໄຂ Widget" | ||||
| editWidgetsExit: "ສຳເລັດແລ້ວ" | ||||
| customEmojis: "ອີໂມຈິແບບກຳນົດເອງ" | ||||
| emoji: "ອີໂມຈິ" | ||||
| emojis: "ອີໂມຈິ" | ||||
| emojiName: "ຊື່ Emoji" | ||||
| emojiUrl: "URL ອີໂມຈິ" | ||||
| addEmoji: "ຕື່ມອີໂມຈິ" | ||||
| flagAsBot: "ໝາຍບັນຊີນີ້ເປັນບັອດ" | ||||
| flagAsCat: "ໝາຍບັນຊີນີ້ເປັນແມວ" | ||||
| flagAsCatDescription: "ເປີດໃຊ້ຕົວເລືອກນີ້ເພື່ອໝາຍບັນຊີນີ້ເປັນແມວ" | ||||
| flagShowTimelineReplies: "ສະແດງການຕອບກັບໃນທາມລາຍ" | ||||
| flagShowTimelineRepliesDescription: "ສະແດງການຕອບກັບຂອງຜູ້ໃຊ້ຕໍ່ກັບບັນທຶກຂອງຜູ້ໃຊ້ອື່ນໃນທາມລາຍຖ້າເປີດໃຊ້ງານ" | ||||
| autoAcceptFollowed: "ອະນຸມັດອັດຕະໂນມັດຕາມຄຳຮ້ອງຂໍຈາກຜູ້ໃຊ້ທີ່ທ່ານກຳລັງຕິດຕາມຢູ່" | ||||
| addAccount: "ເພີ່ມບັນຊີ" | ||||
| loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ" | ||||
| general: "ທົ່ວໄປ" | ||||
| wallpaper: "ພາບພື້ນຫລັງ" | ||||
| setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ" | ||||
| instances: "ອີນສະແຕນ" | ||||
| instanceInfo: "ອີນສະແຕນ" | ||||
| statistics: "ສະຖິຕິ" | ||||
| clearQueue: "ລ້າງຄິວ" | ||||
| clearCachedFiles: "ລຶບລ້າງແຄສ" | ||||
| editProfile: "ແກ້ໄຂໂປຣໄຟລ໌" | ||||
| done: "ສຳເລັດ" | ||||
| processing: "ກຳລັງປະມວນຜົນ" | ||||
| preview: "ສະແດງເປັນຕົວຢ່າງ" | ||||
| default: "ຄ່າເລີ່ມຕົ້ນ" | ||||
| blocked: "ບລັອກແລ້ວ " | ||||
| all: "ທັງໝົດ" | ||||
| subscribing: "ສະໝັກສະມາຊິກແລັວ" | ||||
| publishing: "ການພິມເຜີຍແຜ່" | ||||
| notResponding: "ບໍ່ຕອບສະໜອງ" | ||||
| instanceFollowing: "ກຳລັງຕິດຕາມສຸດຕົວຢ່າງ" | ||||
| instanceFollowers: "ຜູ້ຕິດຕາມຕົວຢ່າງ" | ||||
| instanceUsers: "ຜູ້ຊົມໃຊ້ຂອງຕົວຢ່າງນີ້" | ||||
| changePassword: "ປ່ຽນລະຫັດຜ່ານ" | ||||
| featured: "ໄຮໄລທ໌" | ||||
| announcements: "ປະກາດ" | ||||
| remove: "ລຶບ" | ||||
| messaging: "ແຊ໋ດ" | ||||
| tos: "ເງື່ອນໄຂການໃຫ້ບໍລິການ" | ||||
| start: "ເລີ່ມຕົ້ນນຳໃຊ້ເລີຍ" | ||||
| home: "ໜ້າຫຼັກ" | ||||
| images: "ຮູບພາບ" | ||||
| birthday: "ວັນເກີດ" | ||||
| registeredDate: "ວັນທີ່ເປັນສະມາຊິກ" | ||||
| location: "ທີ່ຕັ້ງ" | ||||
| theme: "ແທ໋ມ" | ||||
| light: "ສະຫວ່າງ" | ||||
| dark: "ມືດ" | ||||
| lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ" | ||||
| darkThemes: "ຮູບແບບສີສັນມືດ" | ||||
| fileName: "ຊື່ໄຟລ໌" | ||||
| selectFile: "ເລືອກໄຟລ໌" | ||||
| selectFiles: "ເລືອກໄຟລ໌" | ||||
| nsfw: "NSFW" | ||||
| accept: "ອະນຸຍາດ" | ||||
| pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້" | ||||
| userList: "ລາຍການ" | ||||
| smtpUser: "ຊື່ຜູ້ໃຊ້" | ||||
| smtpPass: "ລະຫັດຜ່ານ" | ||||
| clearCache: "ລຶບລ້າງແຄສ" | ||||
| user: "ຜູ້ໃຊ້ຕ່າງໆ" | ||||
| searchByGoogle: "ຄົ້ນຫາ" | ||||
| file: "ໄຟລ໌" | ||||
| _email: | ||||
|   _follow: | ||||
|     title: "ໄດ້ຕິດຕາມທ່ານ" | ||||
| _mfm: | ||||
|   mention: "ໄດ້ກ່າວມາ" | ||||
|   quote: "ລວມຂໍ້ຄວາມອ້າງອີງ" | ||||
|   emoji: "ອີໂມຈິແບບກຳນົດເອງ" | ||||
|   search: "ຄົ້ນຫາ" | ||||
| _theme: | ||||
|   keys: | ||||
|     mention: "ໄດ້ກ່າວມາ" | ||||
|     renote: "Renote" | ||||
| _sfx: | ||||
|   note: "ບັນທຶກ" | ||||
|   notification: "ການແຈ້ງເຕືອນ" | ||||
|   chat: "ແຊ໋ດ" | ||||
| _widgets: | ||||
|   profile: "ໂພຼຟາຍ" | ||||
|   instanceInfo: "ອີນສະແຕນ" | ||||
|   notifications: "ການແຈ້ງເຕືອນ" | ||||
|   timeline: "ເສັ້ນກຳນົດເວລາ" | ||||
|   _userList: | ||||
|     chooseList: "ເລືອກບັນຊີລາຍການ" | ||||
| _cw: | ||||
|   show: "ໂຫຼດເພີ່ມເຕີມ" | ||||
| _visibility: | ||||
|   home: "ໜ້າຫຼັກ" | ||||
|   followers: "ຜູ້ຕິດຕາມ" | ||||
| _profile: | ||||
|   username: "ຊື່ຜູ້ໃຊ້" | ||||
| _exportOrImport: | ||||
|   followingList: "ກຳລັງຕິດຕາມ" | ||||
|   muteList: "ປີດສຽງ" | ||||
|   blockingList: "ບ໋ອກ" | ||||
|   userLists: "ລາຍການ" | ||||
| _timelines: | ||||
|   home: "ໜ້າຫຼັກ" | ||||
| _pages: | ||||
|   blocks: | ||||
|     image: "ຮູບພາບ" | ||||
| _notification: | ||||
|   youWereFollowed: "ໄດ້ຕິດຕາມທ່ານ" | ||||
|   _types: | ||||
|     follow: "ກຳລັງຕິດຕາມ" | ||||
|     mention: "ໄດ້ກ່າວມາ" | ||||
|     renote: "Renote" | ||||
|     quote: "ລວມຂໍ້ຄວາມອ້າງອີງ" | ||||
|     reaction: "ປະຕິກິລິຍາ" | ||||
|   _actions: | ||||
|     reply: "ຕອບໄປທີ" | ||||
|     renote: "Renote" | ||||
| _deck: | ||||
|   _columns: | ||||
|     notifications: "ການແຈ້ງເຕືອນ" | ||||
|     tl: "ເສັ້ນກຳນົດເວລາ" | ||||
|     list: "ລາຍການ" | ||||
|     channel: "ຊ່ອງ" | ||||
|     mentions: "ກ່າວເຖິງ" | ||||
|   | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "คุณแน่ใจแล้วเหรอ? ว่าต | ||||
| suspendConfirm: "นายแน่ใจแล้วเหรอว่าต้องการระงับบัญชีนี้อ่ะ?" | ||||
| unsuspendConfirm: "นายแน่ใจแล้วหรอ? ว่าต้องการยกเลิกการระงับบัญชีนี้" | ||||
| selectList: "เลือกรายการ" | ||||
| selectChannel: "เลือกแชนแนล" | ||||
| selectAntenna: "เลือกเสาอากาศ" | ||||
| selectWidget: "เลือกวิดเจ็ต" | ||||
| editWidgets: "แก้ไขวิดเจ็ต" | ||||
| @@ -939,6 +940,8 @@ cannotPerformTemporaryDescription: "การดําเนินการน | ||||
| preset: "พรีเซ็ต" | ||||
| selectFromPresets: "เลือกจากการพรีเซ็ต" | ||||
| achievements: "ความสำเร็จ" | ||||
| gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง" | ||||
| gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ" | ||||
| _achievements: | ||||
|   earnedAt: "ได้รับเมื่อ" | ||||
|   _types: | ||||
| @@ -1593,12 +1596,15 @@ _permissions: | ||||
|   "read:gallery-likes": "ดูรายการโพสต์ในแกลเลอรีที่ชอบของคุณ" | ||||
|   "write:gallery-likes": "แก้ไขรายการโพสต์ในแกลเลอรีที่ชอบของคุณ" | ||||
| _auth: | ||||
|   shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน" | ||||
|   shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?" | ||||
|   shareAccessAsk: "คุณแน่ใจแล้วจริงๆหรอว่าต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณแน่ใจแล้วหรอ?" | ||||
|   permission: "{name} ได้ขอสิทธิ์การเข้าถึงดังต่อไปนี้" | ||||
|   permissionAsk: "แอปพลิเคชันนี้ขอสิทธิ์ดังต่อไปนี้" | ||||
|   pleaseGoBack: "กรุณากลับไปที่แอปพลิเคชัน" | ||||
|   callback: "กำลังกลับไปที่แอปพลิเคชัน" | ||||
|   denied: "ปฏิเสธการเข้าใช้" | ||||
|   pleaseLogin: "กรุณาเข้าสู่ระบบเพื่ออนุมัติแอปพลิเคชัน" | ||||
| _antennaSources: | ||||
|   all: "โน้ตทั้งหมด" | ||||
|   homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม" | ||||
|   | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "确定要解除拉黑吗?" | ||||
| suspendConfirm: "要冻结吗?" | ||||
| unsuspendConfirm: "要解除冻结吗?" | ||||
| selectList: "选择列表" | ||||
| selectChannel: "选择频道" | ||||
| selectAntenna: "选择天线" | ||||
| selectWidget: "选择小工具" | ||||
| editWidgets: "编辑部件" | ||||
| @@ -256,6 +257,8 @@ noMoreHistory: "没有更多的历史记录" | ||||
| startMessaging: "添加聊天" | ||||
| nUsersRead: "{n}人已读" | ||||
| agreeTo: "勾选则表示已阅读并同意{0}" | ||||
| agreeBelow: "同意以下观点" | ||||
| basicNotesBeforeCreateAccount: "基本注意事项" | ||||
| tos: "服务条款" | ||||
| start: "开始" | ||||
| home: "首页" | ||||
| @@ -861,6 +864,8 @@ failedToFetchAccountInformation: "获取账户信息失败" | ||||
| rateLimitExceeded: "已超過速率限制" | ||||
| cropImage: "剪裁图像" | ||||
| cropImageAsk: "是否要裁剪图像?" | ||||
| cropYes: "已裁剪" | ||||
| cropNo: "就这样吧!" | ||||
| file: "文件" | ||||
| recentNHours: "最近{n}小时" | ||||
| recentNDays: "最近{n}天" | ||||
| @@ -939,6 +944,8 @@ cannotPerformTemporaryDescription: "因操作过于频繁,暂时不可用, | ||||
| preset: "預設值" | ||||
| selectFromPresets: "從預設值中選擇" | ||||
| achievements: "成就" | ||||
| gotInvalidResponseError: "服务器无应答" | ||||
| gotInvalidResponseErrorDescription: "您的网络连接可能出现了问题, 或是远程服务器暂时不可用. 请稍后重试。" | ||||
| _achievements: | ||||
|   earnedAt: "达成时间" | ||||
|   _types: | ||||
| @@ -1122,7 +1129,7 @@ _achievements: | ||||
|       description: "在0点发布一篇帖子" | ||||
|       flavor: "嘣 嘣 嘣 Biu——!" | ||||
|     _selfQuote: | ||||
|       title: "自我提及" | ||||
|       title: "自我引用" | ||||
|       description: "引用了自己的帖子" | ||||
|     _htl20npm: | ||||
|       title: "流动的时间线" | ||||
| @@ -1593,12 +1600,15 @@ _permissions: | ||||
|   "read:gallery-likes": "读取喜欢的图片" | ||||
|   "write:gallery-likes": "操作喜欢的图片" | ||||
| _auth: | ||||
|   shareAccessTitle: "应用程序授权许可" | ||||
|   shareAccess: "您要授权允许“{name}”访问您的帐户吗?" | ||||
|   shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?" | ||||
|   permission: "{name}需要以下权限" | ||||
|   permissionAsk: "这个应用程序需要以下权限" | ||||
|   pleaseGoBack: "请返回到应用程序" | ||||
|   callback: "回到应用程序" | ||||
|   denied: "拒绝访问" | ||||
|   pleaseLogin: "在对应用进行授权许可之前,请先登录" | ||||
| _antennaSources: | ||||
|   all: "所有帖子" | ||||
|   homeTimeline: "已关注用户的帖子" | ||||
|   | ||||
| @@ -129,6 +129,7 @@ unblockConfirm: "確定解除封鎖此用戶?" | ||||
| suspendConfirm: "確定凍結此帳號?" | ||||
| unsuspendConfirm: "確定解凍此帳號?" | ||||
| selectList: "選擇清單" | ||||
| selectChannel: "選擇頻道" | ||||
| selectAntenna: "選擇天線" | ||||
| selectWidget: "選擇小工具" | ||||
| editWidgets: "編輯小工具" | ||||
| @@ -256,6 +257,8 @@ noMoreHistory: "沒有更多歷史紀錄" | ||||
| startMessaging: "開始聊天" | ||||
| nUsersRead: "{n}人已讀" | ||||
| agreeTo: "我同意{0}" | ||||
| agreeBelow: "同意以下內容" | ||||
| basicNotesBeforeCreateAccount: "基本注意事項" | ||||
| tos: "使用條款" | ||||
| start: "開始" | ||||
| home: "首頁" | ||||
| @@ -861,6 +864,8 @@ failedToFetchAccountInformation: "取得帳戶資訊失敗" | ||||
| rateLimitExceeded: "已超過速率限制" | ||||
| cropImage: "圖片裁剪" | ||||
| cropImageAsk: "要剪裁圖片嗎?" | ||||
| cropYes: "裁剪" | ||||
| cropNo: "使用原圖" | ||||
| file: "檔案" | ||||
| recentNHours: "過去{n}小時" | ||||
| recentNDays: "過去{n}天" | ||||
| @@ -939,6 +944,8 @@ cannotPerformTemporaryDescription: "由於超過操作次數限制,暫時無 | ||||
| preset: "預設值" | ||||
| selectFromPresets: "從預設值中選擇" | ||||
| achievements: "成就" | ||||
| gotInvalidResponseError: "伺服器的回應無效" | ||||
| gotInvalidResponseErrorDescription: "伺服器可能已關閉或者在維護中,請稍後再試。" | ||||
| _achievements: | ||||
|   earnedAt: "獲得日期" | ||||
|   _types: | ||||
| @@ -1593,12 +1600,15 @@ _permissions: | ||||
|   "read:gallery-likes": "讀取喜歡的圖片" | ||||
|   "write:gallery-likes": "操作喜歡的圖片" | ||||
| _auth: | ||||
|   shareAccessTitle: "應用程式的存取權限" | ||||
|   shareAccess: "要授權「“{name}”」存取您的帳戶嗎?" | ||||
|   shareAccessAsk: "您確定要授權這個應用程式使用您的帳戶嗎?" | ||||
|   permission: "{name}要求以下的權限" | ||||
|   permissionAsk: "此應用程式需要以下權限" | ||||
|   pleaseGoBack: "請返回至應用程式" | ||||
|   callback: "回到應用程式" | ||||
|   denied: "拒絕訪問" | ||||
|   pleaseLogin: "必須登入以提供應用程式的存取權限。" | ||||
| _antennaSources: | ||||
|   all: "全部貼文" | ||||
|   homeTimeline: "來自已追隨使用者的貼文" | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| { | ||||
| 	"name": "misskey", | ||||
| 	"version": "13.5.4", | ||||
| 	"version": "13.5.6", | ||||
| 	"codename": "nasubi", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
| 		"url": "https://github.com/misskey-dev/misskey.git" | ||||
| 	}, | ||||
| 	"packageManager": "pnpm@7.24.3", | ||||
| 	"packageManager": "pnpm@7.27.0", | ||||
| 	"workspaces": [ | ||||
| 		"packages/frontend", | ||||
| 		"packages/backend", | ||||
|   | ||||
| @@ -255,8 +255,21 @@ export class FileServerService { | ||||
| 			const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image'); | ||||
| 			const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image'); | ||||
|  | ||||
| 			if ( | ||||
| 				'emoji' in request.query || | ||||
| 				'avatar' in request.query || | ||||
| 				'static' in request.query || | ||||
| 				'preview' in request.query || | ||||
| 				'badge' in request.query | ||||
| 			) { | ||||
| 				if (!isConvertibleImage) { | ||||
| 					// 画像でないなら404でお茶を濁す | ||||
| 					throw new StatusError('Unexpected mime', 404); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			let image: IImageStreamable | null = null; | ||||
| 			if (('emoji' in request.query || 'avatar' in request.query) && isConvertibleImage) { | ||||
| 			if ('emoji' in request.query || 'avatar' in request.query) { | ||||
| 				if (!isAnimationConvertibleImage && !('static' in request.query)) { | ||||
| 					image = { | ||||
| 						data: fs.createReadStream(file.path), | ||||
| @@ -277,16 +290,11 @@ export class FileServerService { | ||||
| 						type: 'image/webp', | ||||
| 					}; | ||||
| 				} | ||||
| 			} else if ('static' in request.query && isConvertibleImage) { | ||||
| 			} else if ('static' in request.query) { | ||||
| 				image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280); | ||||
| 			} else if ('preview' in request.query && isConvertibleImage) { | ||||
| 			} else if ('preview' in request.query) { | ||||
| 				image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200); | ||||
| 			} else if ('badge' in request.query) { | ||||
| 				if (!isConvertibleImage) { | ||||
| 					// 画像でないなら404でお茶を濁す | ||||
| 					throw new StatusError('Unexpected mime', 404); | ||||
| 				} | ||||
|  | ||||
| 				const mask = sharp(file.path) | ||||
| 					.resize(96, 96, { | ||||
| 						fit: 'inside', | ||||
|   | ||||
| @@ -107,6 +107,7 @@ onMounted(() => { | ||||
| } | ||||
|  | ||||
| .iconFrame { | ||||
| 	position: relative; | ||||
| 	width: 58px; | ||||
| 	height: 58px; | ||||
| 	padding: 6px; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
| <button class="_button" :class="$style.root" @click="toggle"> | ||||
| <button class="_button" :class="$style.root" @mousedown="toggle"> | ||||
| 	<b>{{ modelValue ? i18n.ts._cw.hide : i18n.ts._cw.show }}</b> | ||||
| 	<span v-if="!modelValue" :class="$style.label">{{ label }}</span> | ||||
| </button> | ||||
|   | ||||
| @@ -28,8 +28,8 @@ | ||||
| 			</template> | ||||
| 		</MkSelect> | ||||
| 		<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons"> | ||||
| 			<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" @click="ok">{{ (showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt }}</MkButton> | ||||
| 			<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ i18n.ts.cancel }}</MkButton> | ||||
| 			<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton> | ||||
| 			<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ cancelText ?? i18n.ts.cancel }}</MkButton> | ||||
| 		</div> | ||||
| 		<div v-if="actions" :class="$style.buttons"> | ||||
| 			<MkButton v-for="action in actions" :key="action.text" inline :primary="action.primary" @click="() => { action.callback(); close(); }">{{ action.text }}</MkButton> | ||||
| @@ -82,6 +82,8 @@ const props = withDefaults(defineProps<{ | ||||
| 	showOkButton?: boolean; | ||||
| 	showCancelButton?: boolean; | ||||
| 	cancelableByBgClick?: boolean; | ||||
| 	okText?: string; | ||||
| 	cancelText?: string; | ||||
| }>(), { | ||||
| 	type: 'info', | ||||
| 	showOkButton: true, | ||||
|   | ||||
| @@ -56,7 +56,7 @@ onMounted(() => { | ||||
| 	width: 100%; | ||||
| 	border-radius: 4px; | ||||
| 	margin-top: 4px; | ||||
| 	overflow: clip; | ||||
| 	// overflow: clip; | ||||
|  | ||||
| 	--plyr-color-main: var(--accent); | ||||
| 	--plyr-audio-controls-background: var(--bg); | ||||
| @@ -99,7 +99,7 @@ onMounted(() => { | ||||
|  | ||||
| 	> .audio { | ||||
| 		border-radius: 8px; | ||||
| 		overflow: clip; | ||||
| 		// overflow: clip; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -134,6 +134,9 @@ const previewable = (file: misskey.entities.DriveFile): boolean => { | ||||
| 	display: grid; | ||||
| 	grid-gap: 8px; | ||||
|  | ||||
| 	// for webkit | ||||
| 	height: 100%; | ||||
|  | ||||
| 	&.n1 { | ||||
| 		aspect-ratio: 16/9; | ||||
| 		grid-template-rows: 1fr; | ||||
|   | ||||
| @@ -50,13 +50,13 @@ | ||||
| 			<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span> | ||||
| 		</template> | ||||
| 	</MkInput> | ||||
| 	<MkSwitch v-if="instance.tosUrl" v-model="ToSAgreement" class="tou"> | ||||
| 		<I18n :src="i18n.ts.agreeTo"> | ||||
| 			<template #0> | ||||
| 				<a :href="instance.tosUrl" class="_link" target="_blank">{{ i18n.ts.tos }}</a> | ||||
| 			</template> | ||||
| 		</I18n> | ||||
| 	<MkSwitch v-model="ToSAgreement" class="tou"> | ||||
| 		<template #label>{{ i18n.ts.agreeBelow }}</template> | ||||
| 	</MkSwitch> | ||||
| 	<ul style="margin: 0; padding-left: 2em;"> | ||||
| 		<li v-if="instance.tosUrl"><a :href="instance.tosUrl" class="_link" target="_blank">{{ i18n.ts.tos }}</a></li> | ||||
| 		<li><a href="https://misskey-hub.net/docs/notes.html" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }}</a></li> | ||||
| 	</ul> | ||||
| 	<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" class="captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/> | ||||
| 	<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" class="captcha" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/> | ||||
| 	<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" class="captcha" provider="turnstile" :sitekey="instance.turnstileSiteKey"/> | ||||
|   | ||||
| @@ -1,11 +1,19 @@ | ||||
| <template> | ||||
| <span v-if="!link" v-user-preview="preview ? user.id : undefined" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" class="_noSelect" :style="{ color }" :title="acct(user)" @click="onClick"> | ||||
| <span v-if="!link" v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick"> | ||||
| 	<img :class="$style.inner" :src="url" decoding="async"/> | ||||
| 	<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/> | ||||
| 	<template v-if="user.isCat"> | ||||
| 		<div :class="$style.earLeft"/> | ||||
| 		<div :class="$style.earRight"/> | ||||
| 	</template> | ||||
| </span> | ||||
| <MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :to="userPage(user)" :title="acct(user)" :target="target"> | ||||
| <MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" :to="userPage(user)" :target="target"> | ||||
| 	<img :class="$style.inner" :src="url" decoding="async"/> | ||||
| 	<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/> | ||||
| 	<template v-if="user.isCat"> | ||||
| 		<div :class="$style.earLeft"/> | ||||
| 		<div :class="$style.earRight"/> | ||||
| 	</template> | ||||
| </MkA> | ||||
| </template> | ||||
|  | ||||
| @@ -110,32 +118,41 @@ watch(() => props.user.avatarBlurhash, () => { | ||||
| } | ||||
|  | ||||
| .cat { | ||||
| 	&:before, &:after { | ||||
| 		background: #df548f; | ||||
| 		border: solid 4px currentColor; | ||||
| 		box-sizing: border-box; | ||||
| 		content: ''; | ||||
| 	> .earLeft, | ||||
| 	> .earRight { | ||||
| 		contain: strict; | ||||
| 		display: inline-block; | ||||
| 		height: 50%; | ||||
| 		width: 50%; | ||||
| 		background: currentColor; | ||||
|  | ||||
| 		&::before { | ||||
| 			contain: strict; | ||||
| 			content: ''; | ||||
| 			display: block; | ||||
| 			width: 60%; | ||||
| 			height: 60%; | ||||
| 			margin: 20%; | ||||
| 			background: #df548f; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	&:before { | ||||
| 	> .earLeft { | ||||
| 		border-radius: 0 75% 75%; | ||||
| 		transform: rotate(37.5deg) skew(30deg); | ||||
| 	} | ||||
|  | ||||
| 	&:after { | ||||
| 	> .earRight { | ||||
| 		border-radius: 75% 0 75% 75%; | ||||
| 		transform: rotate(-37.5deg) skew(-30deg); | ||||
| 	} | ||||
|  | ||||
| 	&:hover { | ||||
| 		&:before { | ||||
| 		> .earLeft { | ||||
| 			animation: earwiggleleft 1s infinite; | ||||
| 		} | ||||
|  | ||||
| 		&:after { | ||||
| 		> .earRight { | ||||
| 			animation: earwiggleright 1s infinite; | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -171,6 +171,8 @@ export function confirm(props: { | ||||
| 	type: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question'; | ||||
| 	title?: string | null; | ||||
| 	text?: string | null; | ||||
| 	okText?: string; | ||||
| 	cancelText?: string; | ||||
| }): Promise<{ canceled: boolean }> { | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		popup(MkDialog, { | ||||
|   | ||||
| @@ -1,60 +1,66 @@ | ||||
| <template> | ||||
| <section class=""> | ||||
| 	<div class="">{{ $t('_auth.shareAccess', { name: app.name }) }}</div> | ||||
| 	<div class=""> | ||||
| 		<h2>{{ app.name }}</h2> | ||||
| 		<p class="id">{{ app.id }}</p> | ||||
| 		<p class="description">{{ app.description }}</p> | ||||
| 	</div> | ||||
| 	<div class=""> | ||||
| 		<h2>{{ $ts._auth.permissionAsk }}</h2> | ||||
| 		<ul> | ||||
| 			<li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> | ||||
| 		</ul> | ||||
| 	</div> | ||||
| 	<div class=""> | ||||
| 		<MkButton inline @click="cancel">{{ $ts.cancel }}</MkButton> | ||||
| 		<MkButton inline primary @click="accept">{{ $ts.accept }}</MkButton> | ||||
| 	</div> | ||||
| </section> | ||||
| 	<section> | ||||
| 		<div v-if="app.permission.length > 0"> | ||||
| 			<p>{{ $t('_auth.permission', { name }) }}</p> | ||||
| 			<ul> | ||||
| 				<li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> | ||||
| 			</ul> | ||||
| 		</div> | ||||
| 		<div>{{ i18n.t('_auth.shareAccess', { name: `${name} (${app.id})` }) }}</div> | ||||
| 		<div :class="$style.buttons"> | ||||
| 			<MkButton inline @click="cancel">{{ i18n.ts.cancel }}</MkButton> | ||||
| 			<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> | ||||
| 		</div> | ||||
| 	</section> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { } from 'vue'; | ||||
| import MkButton from '@/components/MkButton.vue'; | ||||
| import * as os from '@/os'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import { AuthSession } from 'misskey-js/built/entities'; | ||||
|  | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 	}, | ||||
| 	props: ['session'], | ||||
| 	computed: { | ||||
| 		name(): string { | ||||
| 			const el = document.createElement('div'); | ||||
| 			el.textContent = this.app.name; | ||||
| 			return el.innerHTML; | ||||
| 		}, | ||||
| 		app(): any { | ||||
| 			return this.session.app; | ||||
| 		}, | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		cancel() { | ||||
| 			os.api('auth/deny', { | ||||
| 				token: this.session.token, | ||||
| 			}).then(() => { | ||||
| 				this.$emit('denied'); | ||||
| 			}); | ||||
| 		}, | ||||
| const props = defineProps<{ | ||||
| 	session: AuthSession; | ||||
| }>(); | ||||
|  | ||||
| 		accept() { | ||||
| 			os.api('auth/accept', { | ||||
| 				token: this.session.token, | ||||
| 			}).then(() => { | ||||
| 				this.$emit('accepted'); | ||||
| 			}); | ||||
| 		}, | ||||
| 	}, | ||||
| const emit = defineEmits<{ | ||||
| 	(event: 'accepted'): void; | ||||
| 	(event: 'denied'): void; | ||||
| }>(); | ||||
|  | ||||
| const app = $computed(() => props.session.app); | ||||
|  | ||||
| const name = $computed(() => { | ||||
| 	const el = document.createElement('div'); | ||||
| 	el.textContent = app.name; | ||||
| 	return el.innerHTML; | ||||
| }); | ||||
|  | ||||
| function cancel() { | ||||
| 	os.api('auth/deny', { | ||||
| 		token: props.session.token, | ||||
| 	}).then(() => { | ||||
| 		emit('denied'); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| function accept() { | ||||
| 	os.api('auth/accept', { | ||||
| 		token: props.session.token, | ||||
| 	}).then(() => { | ||||
| 		emit('accepted'); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" module> | ||||
| .buttons { | ||||
| 	margin-top: 16px; | ||||
| 	display: flex; | ||||
| 	gap: 8px; | ||||
| 	flex-wrap: wrap; | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -1,93 +1,105 @@ | ||||
| <template> | ||||
| <div v-if="$i && fetching" class=""> | ||||
| 	<MkLoading/> | ||||
| </div> | ||||
| <div v-else-if="$i"> | ||||
| 	<XForm | ||||
| 		v-if="state == 'waiting'" | ||||
| 		ref="form" | ||||
| 		class="form" | ||||
| 		:session="session" | ||||
| 		@denied="state = 'denied'" | ||||
| 		@accepted="accepted" | ||||
| 	/> | ||||
| 	<div v-if="state == 'denied'" class="denied"> | ||||
| 		<h1>{{ $ts._auth.denied }}</h1> | ||||
| 	</div> | ||||
| 	<div v-if="state == 'accepted'" class="accepted"> | ||||
| 		<h1>{{ session.app.isAuthorized ? $t('already-authorized') : $ts.allowed }}</h1> | ||||
| 		<p v-if="session.app.callbackUrl">{{ $ts._auth.callback }}<MkEllipsis/></p> | ||||
| 		<p v-if="!session.app.callbackUrl">{{ $ts._auth.pleaseGoBack }}</p> | ||||
| 	</div> | ||||
| 	<div v-if="state == 'fetch-session-error'" class="error"> | ||||
| 		<p>{{ $ts.somethingHappened }}</p> | ||||
| 	</div> | ||||
| </div> | ||||
| <div v-else class="signin"> | ||||
| 	<MkSignin @login="onLogin"/> | ||||
| </div> | ||||
| <MkStickyContainer> | ||||
| 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template> | ||||
| 	<MkSpacer :content-max="500"> | ||||
| 		<div v-if="state == 'fetch-session-error'"> | ||||
| 			<p>{{ i18n.ts.somethingHappened }}</p> | ||||
| 		</div> | ||||
| 		<div v-else-if="$i && !session"> | ||||
| 			<MkLoading /> | ||||
| 		</div> | ||||
| 		<div v-else-if="$i && session"> | ||||
| 			<XForm | ||||
| 				v-if="state == 'waiting'" | ||||
| 				class="form" | ||||
| 				:session="session" | ||||
| 				@denied="state = 'denied'" | ||||
| 				@accepted="accepted" | ||||
| 			/> | ||||
| 			<div v-if="state == 'denied'"> | ||||
| 				<h1>{{ i18n.ts._auth.denied }}</h1> | ||||
| 			</div> | ||||
| 			<div v-if="state == 'accepted' && session"> | ||||
| 				<h1>{{ session.app.isAuthorized ? $t('already-authorized') : i18n.ts.allowed }}</h1> | ||||
| 				<p v-if="session.app.callbackUrl">{{ i18n.ts._auth.callback }} | ||||
| 					<MkEllipsis /> | ||||
| 				</p> | ||||
| 				<p v-if="!session.app.callbackUrl">{{ i18n.ts._auth.pleaseGoBack }}</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div v-else> | ||||
| 			<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p> | ||||
| 			<MkSignin @login="onLogin" /> | ||||
| 		</div> | ||||
| 	</MkSpacer> | ||||
| </MkStickyContainer> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { onMounted } from 'vue'; | ||||
| import XForm from './auth.form.vue'; | ||||
| import MkSignin from '@/components/MkSignin.vue'; | ||||
| import * as os from '@/os'; | ||||
| import { login } from '@/account'; | ||||
| import { $i, login } from '@/account'; | ||||
| import { definePageMetadata } from '@/scripts/page-metadata'; | ||||
| import { AuthSession } from 'misskey-js/built/entities'; | ||||
| import { i18n } from '@/i18n'; | ||||
|  | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XForm, | ||||
| 		MkSignin, | ||||
| 	}, | ||||
| 	props: ['token'], | ||||
| 	data() { | ||||
| 		return { | ||||
| 			state: null, | ||||
| 			session: null, | ||||
| 			fetching: true, | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		if (!this.$i) return; | ||||
| const props = defineProps<{ | ||||
| 	token: string; | ||||
| }>(); | ||||
|  | ||||
| 		// Fetch session | ||||
| 		os.api('auth/session/show', { | ||||
| 			token: this.token, | ||||
| 		}).then(session => { | ||||
| 			this.session = session; | ||||
| 			this.fetching = false; | ||||
| let state = $ref<'waiting' | 'accepted' | 'fetch-session-error' | 'denied' | null>(null); | ||||
| let session = $ref<AuthSession | null>(null); | ||||
|  | ||||
| 			// 既に連携していた場合 | ||||
| 			if (this.session.app.isAuthorized) { | ||||
| 				os.api('auth/accept', { | ||||
| 					token: this.session.token, | ||||
| 				}).then(() => { | ||||
| 					this.accepted(); | ||||
| 				}); | ||||
| 			} else { | ||||
| 				this.state = 'waiting'; | ||||
| 			} | ||||
| 		}).catch(error => { | ||||
| 			this.state = 'fetch-session-error'; | ||||
| 			this.fetching = false; | ||||
| function accepted() { | ||||
| 	state = 'accepted'; | ||||
| 	if (session && session.app.callbackUrl) { | ||||
| 		const url = new URL(session.app.callbackUrl); | ||||
| 		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url'); | ||||
| 		location.href = `${session.app.callbackUrl}?token=${session.token}`; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function onLogin(res) { | ||||
| 	login(res.i); | ||||
| } | ||||
|  | ||||
| onMounted(async () => { | ||||
| 	if (!$i) return; | ||||
|  | ||||
| 	try { | ||||
| 		session = await os.api('auth/session/show', { | ||||
| 			token: props.token, | ||||
| 		}); | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		accepted() { | ||||
| 			this.state = 'accepted'; | ||||
| 			if (this.session.app.callbackUrl) { | ||||
| 				const url = new URL(this.session.app.callbackUrl); | ||||
| 				if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url'); | ||||
| 				location.href = `${this.session.app.callbackUrl}?token=${this.session.token}`; | ||||
| 			} | ||||
| 		}, onLogin(res) { | ||||
| 			login(res.i); | ||||
| 		}, | ||||
| 	}, | ||||
|  | ||||
| 		// 既に連携していた場合 | ||||
| 		if (session.app.isAuthorized) { | ||||
| 			await os.api('auth/accept', { | ||||
| 				token: session.token, | ||||
| 			}); | ||||
| 			accepted(); | ||||
| 		} else { | ||||
| 			state = 'waiting'; | ||||
| 		} | ||||
| 	} catch (e) { | ||||
| 		state = 'fetch-session-error'; | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| const headerActions = $computed(() => []); | ||||
|  | ||||
| const headerTabs = $computed(() => []); | ||||
|  | ||||
| definePageMetadata({ | ||||
| 	title: i18n.ts._auth.shareAccessTitle, | ||||
| 	icon: 'ti ti-apps', | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|  | ||||
| <style lang="scss" module> | ||||
| .loginMessage { | ||||
| 	text-align: center; | ||||
| 	margin: 8px 0 24px; | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -1,41 +1,40 @@ | ||||
| <template> | ||||
| <MkSpacer :content-max="800"> | ||||
| 	<div v-if="$i"> | ||||
| 		<div v-if="state == 'waiting'" class="waiting"> | ||||
| 			<div class=""> | ||||
| <MkStickyContainer> | ||||
| 	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template> | ||||
| 	<MkSpacer :content-max="800"> | ||||
| 		<div v-if="$i"> | ||||
| 			<div v-if="state == 'waiting'"> | ||||
| 				<MkLoading/> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div v-if="state == 'denied'" class="denied"> | ||||
| 			<div class=""> | ||||
| 			<div v-if="state == 'denied'"> | ||||
| 				<p>{{ i18n.ts._auth.denied }}</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div v-else-if="state == 'accepted'" class="accepted"> | ||||
| 			<div class=""> | ||||
| 			<div v-else-if="state == 'accepted'" class="accepted"> | ||||
| 				<p v-if="callback">{{ i18n.ts._auth.callback }}<MkEllipsis/></p> | ||||
| 				<p v-else>{{ i18n.ts._auth.pleaseGoBack }}</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div v-else class=""> | ||||
| 			<div v-if="name" class="">{{ $t('_auth.shareAccess', { name: name }) }}</div> | ||||
| 			<div v-else class="">{{ i18n.ts._auth.shareAccessAsk }}</div> | ||||
| 			<div class=""> | ||||
| 				<p>{{ i18n.ts._auth.permissionAsk }}</p> | ||||
| 				<ul> | ||||
| 					<li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li> | ||||
| 				</ul> | ||||
| 			</div> | ||||
| 			<div class=""> | ||||
| 				<MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton> | ||||
| 				<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> | ||||
| 			<div v-else> | ||||
| 				<div v-if="_permissions.length > 0"> | ||||
| 					<p v-if="name">{{ $t('_auth.permission', { name }) }}</p> | ||||
| 					<p v-else>{{ i18n.ts._auth.permissionAsk }}</p> | ||||
| 					<ul> | ||||
| 						<li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li> | ||||
| 					</ul> | ||||
| 				</div> | ||||
| 				<div v-if="name">{{ $t('_auth.shareAccess', { name }) }}</div> | ||||
| 				<div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div> | ||||
| 				<div :class="$style.buttons"> | ||||
| 					<MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton> | ||||
| 					<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div v-else class="signin"> | ||||
| 		<MkSignin @login="onLogin"/> | ||||
| 	</div> | ||||
| </MkSpacer> | ||||
| 		<div v-else> | ||||
| 			<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p> | ||||
| 			<MkSignin @login="onLogin"/> | ||||
| 		</div> | ||||
| 	</MkSpacer> | ||||
| </MkStickyContainer> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| @@ -45,6 +44,7 @@ import MkButton from '@/components/MkButton.vue'; | ||||
| import * as os from '@/os'; | ||||
| import { $i, login } from '@/account'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import { definePageMetadata } from '@/scripts/page-metadata'; | ||||
|  | ||||
| const props = defineProps<{ | ||||
| 	session: string; | ||||
| @@ -54,7 +54,7 @@ const props = defineProps<{ | ||||
| 	permission: string; // コンマ区切り | ||||
| }>(); | ||||
|  | ||||
| const _permissions = props.permission.split(','); | ||||
| const _permissions = props.permission ? props.permission.split(',') : []; | ||||
|  | ||||
| let state = $ref<string | null>(null); | ||||
|  | ||||
| @@ -83,8 +83,27 @@ function deny(): void { | ||||
| function onLogin(res): void { | ||||
| 	login(res.i); | ||||
| } | ||||
|  | ||||
| const headerActions = $computed(() => []); | ||||
|  | ||||
| const headerTabs = $computed(() => []); | ||||
|  | ||||
| definePageMetadata({ | ||||
| 	title: 'MiAuth', | ||||
| 	icon: 'ti ti-apps', | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| <style lang="scss" module> | ||||
| .buttons { | ||||
| 	margin-top: 16px; | ||||
| 	display: flex; | ||||
| 	gap: 8px; | ||||
| 	flex-wrap: wrap; | ||||
| } | ||||
|  | ||||
| .loginMessage { | ||||
| 	text-align: center; | ||||
| 	margin: 8px 0 24px; | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -150,6 +150,8 @@ function changeAvatar(ev) { | ||||
| 		const { canceled } = await os.confirm({ | ||||
| 			type: 'question', | ||||
| 			text: i18n.t('cropImageAsk'), | ||||
| 			okText: i18n.ts.cropYes, | ||||
| 			cancelText: i18n.ts.cropNo, | ||||
| 		}); | ||||
|  | ||||
| 		if (!canceled) { | ||||
| @@ -174,6 +176,8 @@ function changeBanner(ev) { | ||||
| 		const { canceled } = await os.confirm({ | ||||
| 			type: 'question', | ||||
| 			text: i18n.t('cropImageAsk'), | ||||
| 			okText: i18n.ts.cropYes, | ||||
| 			cancelText: i18n.ts.cropNo, | ||||
| 		}); | ||||
|  | ||||
| 		if (!canceled) { | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
| 				<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span> | ||||
| 			</button> | ||||
| 			<button v-click-anime class="item _button account" @click="openAccountMenu"> | ||||
| 				<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> | ||||
| 				<MkAvatar :user="$i" class="avatar"/><MkAcct class="text _nowrap" :user="$i"/> | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| @@ -168,20 +168,25 @@ function more() { | ||||
| 				display: flex; | ||||
| 				align-items: center; | ||||
| 				padding-left: 30px; | ||||
| 				text-overflow: ellipsis; | ||||
| 				overflow: hidden; | ||||
| 				white-space: nowrap; | ||||
| 				width: 100%; | ||||
| 				text-align: left; | ||||
| 				box-sizing: border-box; | ||||
| 				margin-top: 16px; | ||||
|  | ||||
| 				> .avatar { | ||||
| 					display: block; | ||||
| 					flex-shrink: 0; | ||||
| 					position: relative; | ||||
| 					width: 32px; | ||||
| 					aspect-ratio: 1; | ||||
| 					margin-right: 8px; | ||||
| 				} | ||||
|  | ||||
| 				> .text { | ||||
| 					display: block; | ||||
| 					flex-shrink: 1; | ||||
| 					padding-right: 8px; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -45,7 +45,7 @@ | ||||
| 				<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span> | ||||
| 			</button> | ||||
| 			<button v-click-anime v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="item _button account" @click="openAccountMenu"> | ||||
| 				<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> | ||||
| 				<MkAvatar :user="$i" class="avatar"/><MkAcct class="text _nowrap" :user="$i"/> | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| @@ -217,20 +217,25 @@ function more(ev: MouseEvent) { | ||||
| 					display: flex; | ||||
| 					align-items: center; | ||||
| 					padding-left: 30px; | ||||
| 					text-overflow: ellipsis; | ||||
| 					overflow: hidden; | ||||
| 					white-space: nowrap; | ||||
| 					width: 100%; | ||||
| 					text-align: left; | ||||
| 					box-sizing: border-box; | ||||
| 					margin-top: 16px; | ||||
|  | ||||
| 					> .avatar { | ||||
| 						display: block; | ||||
| 						flex-shrink: 0; | ||||
| 						position: relative; | ||||
| 						width: 32px; | ||||
| 						aspect-ratio: 1; | ||||
| 						margin-right: 8px; | ||||
| 					} | ||||
|  | ||||
| 					> .text { | ||||
| 						display: block; | ||||
| 						flex-shrink: 1; | ||||
| 						padding-right: 8px; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user