Merge branch 'develop' into fix-13766

This commit is contained in:
かっこかり 2024-08-12 15:12:53 +09:00 committed by GitHub
commit 953eac40ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
60 changed files with 1830 additions and 406 deletions

View file

@ -6,7 +6,7 @@ on:
- develop
paths:
- 'CHANGELOG.md'
# - .github/workflows/release-edit-with-push.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -17,6 +17,10 @@ on:
type: boolean
description: 'MERGE RELEASE BRANCH TO MAIN'
default: false
start-rc:
type: boolean
description: 'Start Release Candidate'
default: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -56,13 +60,13 @@ jobs:
### General
-
### Client
-
### Server
-
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
indent: ${{ vars.INDENT }}
secrets:
@ -79,6 +83,9 @@ jobs:
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
indent: ${{ vars.INDENT }}
draft_prerelease_channel: alpha
ready_start_prerelease_channel: beta
prerelease_channel: ${{ inputs.start-rc && 'rc' || '' }}
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
@ -122,6 +129,7 @@ jobs:
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
indent: ${{ vars.INDENT }}
stable_branch: ${{ vars.STABLE_BRANCH }}
draft_prerelease_channel: alpha
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

View file

@ -39,6 +39,8 @@ jobs:
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
indent: ${{ vars.INDENT }}
draft_prerelease_channel: alpha
ready_start_prerelease_channel: beta
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

View file

@ -7,6 +7,11 @@ on:
- develop
- dev/storybook8 # for testing
pull_request_target:
branches-ignore:
# Since pull requests targets master mostly is the "develop" branch.
# Storybook CI is checked on the "push" event of "develop" branch so it would cause a duplicate build.
# This is a waste of chromatic build quota, so we don't run storybook CI on pull requests targets master.
- master
jobs:
build:

2
.gitignore vendored
View file

@ -35,6 +35,8 @@ coverage
!/.config/example.yml
!/.config/docker_example.yml
!/.config/docker_example.env
docker-compose.yml
compose.yml
.devcontainer/compose.yml
!/.devcontainer/compose.yml

View file

@ -1,3 +1,28 @@
## 2024.8.0
### General
- Fix: リモートユーザのフォロー・フォロワーの一覧が非公開設定の場合も表示できてしまう問題を修正
- Enhance: モデレーターはすべてのユーザーのフォロー・フォロワーの一覧を見られるように
### Client
- Enhance: 「自分のPlay」ページにおいてPlayが非公開かどうかが一目でわかるように
- Fix: Play編集時に公開範囲が「パブリック」にリセットされる問題を修正
- Fix: ページ遷移に失敗することがある問題を修正
- Fix: iOSでユーザー名などがリンクとして誤検知される現象を抑制
- Fix: mCaptchaを使用していてもbotプロテクションに関する警告が消えないのを修正
### Server
- Fix: WSの`readAllNotifications` メッセージが `body` を持たない場合に動作しない問題 #14374
- 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。
- これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。
- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582)
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679)
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
- キュー処理のつまりが改善される可能性があります
## 2024.7.0
### Note

View file

@ -2010,7 +2010,6 @@ _webhookSettings:
createWebhook: "Vytvořit Webhook"
name: "Jméno"
secret: "Tajné"
events: "Události Webhook"
active: "Zapnuto"
_events:
follow: "Při sledování uživatele"

View file

@ -2191,7 +2191,6 @@ _webhookSettings:
createWebhook: "Webhook erstellen"
name: "Name"
secret: "Secret"
events: "Webhook-Ereignisse"
active: "Aktiviert"
_events:
follow: "Wenn du jemandem folgst"

View file

@ -398,7 +398,7 @@ mcaptcha: "mCaptcha"
enableMcaptcha: "Enable mCaptcha"
mcaptchaSiteKey: "Site key"
mcaptchaSecretKey: "Secret key"
mcaptchaInstanceUrl: "mCaptcha instance URL"
mcaptchaInstanceUrl: "mCaptcha server URL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Enable reCAPTCHA"
recaptchaSiteKey: "Site key"
@ -1255,7 +1255,7 @@ launchApp: "Launch the app"
useNativeUIForVideoAudioPlayer: "Use UI of browser when play video and audio"
keepOriginalFilename: "Keep original file name"
keepOriginalFilenameDescription: "If you turn off this setting, files names will be replaced with random string automatically when you upload files."
noDescription: "There is not the explanation"
noDescription: "There is no explanation"
alwaysConfirmFollow: "Always confirm when following"
inquiry: "Contact"
tryAgain: "Please try again later"
@ -1365,7 +1365,7 @@ _initialTutorial:
_exampleNote:
cw: "This will surely make you hungry!"
note: "Just had a chocolate-glazed donut 🍩😋"
useCases: "This is used when following the server guidelines for necessary notes or for self-restriction of spoiler or sensitive text."
useCases: "This is used when following the server guidelines, for necessary notes, or for self-restriction of spoiler or sensitive text."
_howToMakeAttachmentsSensitive:
title: "How to Mark Attachments as Sensitive?"
description: "For attachments that are required by server guidelines or that should not be left intact, add a \"sensitive\" flag."
@ -2426,7 +2426,7 @@ _webhookSettings:
modifyWebhook: "Modify Webhook"
name: "Name"
secret: "Secret"
events: "Webhook Events"
trigger: "Trigger"
active: "Enabled"
_events:
follow: "When following a user"
@ -2494,7 +2494,7 @@ _moderationLogTypes:
unsetUserAvatar: "Unset this user's avatar"
unsetUserBanner: "Unset this user's banner"
createSystemWebhook: "Create SystemWebhook"
updateSystemWebhook: "Update SystemWebHook"
updateSystemWebhook: "Update SystemWebhook"
deleteSystemWebhook: "Delete SystemWebhook"
createAbuseReportNotificationRecipient: "Create a recipient for abuse reports"
updateAbuseReportNotificationRecipient: "Update recipients for abuse reports"

View file

@ -2382,7 +2382,6 @@ _webhookSettings:
createWebhook: "Crear Webhook"
name: "Nombre"
secret: "Secreto"
events: "Eventos de webhook"
active: "Activado"
_events:
follow: "Cuando se sigue a alguien"

View file

@ -1094,6 +1094,8 @@ preservedUsernames: "Noms d'utilisateur·rice réservés"
preservedUsernamesDescription: "Énumérez les noms d'utilisateur à réserver, séparés par des nouvelles lignes. Les noms d'utilisateur spécifiés ici ne seront plus utilisables lors de la création d'un compte, sauf la création manuelle par un administrateur. De plus, les comptes existants ne seront pas affectés."
createNoteFromTheFile: "Rédiger une note de ce fichier"
archive: "Archive"
archived: "Archivé"
unarchive: "Annuler l'archivage"
channelArchiveConfirmTitle: "Voulez-vous vraiment archiver {name} ?"
channelArchiveConfirmDescription: "Une fois archivé, le canal n'apparaîtra plus dans la liste des canaux ni dans les résultats de recherche, et la publication des nouvelles notes sera impossible."
thisChannelArchived: "Ce canal a été archivé."
@ -1224,7 +1226,10 @@ enableHorizontalSwipe: "Glisser pour changer d'onglet"
loading: "Chargement en cours"
surrender: "Annuler"
gameRetry: "Réessayer"
launchApp: "Lancer l'app"
inquiry: "Contact"
_delivery:
status: "Statut de la diffusion"
stop: "Suspendu·e"
_type:
none: "Publié"

View file

@ -2403,7 +2403,6 @@ _webhookSettings:
modifyWebhook: "Sunting Webhook"
name: "Nama"
secret: "Secret"
events: "Webhook Events"
active: "Aktif"
_events:
follow: "Ketika mengikuti pengguna"

View file

@ -2412,7 +2412,6 @@ _webhookSettings:
modifyWebhook: "Modifica Webhook"
name: "Nome"
secret: "Segreto"
events: "Quando eseguire il Webhook"
active: "Attivo"
_events:
follow: "Quando segui un profilo"

View file

@ -60,6 +60,7 @@ copyFileId: "ファイルIDをコピー"
copyFolderId: "フォルダーIDをコピー"
copyProfileUrl: "プロフィールURLをコピー"
searchUser: "ユーザーを探す"
searchThisUsersNotes: "ユーザーのノートを検索"
reply: "返事"
loadMore: "まだまだあるで!"
showMore: "まだまだあるで!"
@ -114,6 +115,8 @@ cantReRenote: "リノート自体はリノートできへんで。"
quote: "引用"
inChannelRenote: "チャンネルの中でリノート"
inChannelQuote: "チャンネル内引用"
renoteToChannel: "チャンネルにリノート"
renoteToOtherChannel: "他のチャンネルにリノート"
pinnedNote: "ピン留めされとるノート"
pinned: "ピン留めしとく"
you: "あんた"
@ -152,6 +155,7 @@ editList: "リストいじる"
selectChannel: "チャンネルを選ぶ"
selectAntenna: "アンテナを選ぶ"
editAntenna: "アンテナいじる"
createAntenna: "アンテナを作成"
selectWidget: "ウィジェットを選ぶ"
editWidgets: "ウィジェットをいじる"
editWidgetsExit: "いじるのをやめる"
@ -178,6 +182,10 @@ addAccount: "アカウントを追加"
reloadAccountsList: "アカウントリストの情報を更新"
loginFailed: "ログインに失敗してもうた…"
showOnRemote: "リモートで見る"
continueOnRemote: "リモートで続行"
chooseServerOnMisskeyHub: "Misskey Hubからサーバーを選択"
specifyServerHost: "サーバーのドメインを直接指定"
inputHostName: "ドメインを入力せえや"
general: "全般"
wallpaper: "壁紙"
setWallpaper: "壁紙を設定"
@ -188,6 +196,7 @@ followConfirm: "{name}をフォローしてええか?"
proxyAccount: "プロキシアカウント"
proxyAccountDescription: "プロキシアカウントは、代わりにフォローしてくれるアカウントや。例えば、551に豚まんが無いときやったり、ユーザーがリモートユーザーをアカウントに入れたとき、リストに入れられたユーザーが誰からもフォローされてないと寂しいやん。寂しいし、アクティビティも配達されへんから、プロキシアカウントがフォローしてくれるで。ええやつやん…"
host: "ホスト"
selectSelf: "自分を選択"
selectUser: "ユーザーを選ぶ"
recipient: "宛先"
annotation: "注釈"
@ -203,6 +212,7 @@ perDay: "1日ごと"
stopActivityDelivery: "アクティビティの配送をやめる"
blockThisInstance: "このサーバーをブロックすんで"
silenceThisInstance: "サーバーサイレンスすんで?"
mediaSilenceThisInstance: "サーバーをメディアサイレンス"
operations: "操作"
software: "ソフトウェア"
version: "バージョン"
@ -224,6 +234,8 @@ blockedInstances: "ブロックしたサーバー"
blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定してな。ブロックされてもうたサーバーとはもう金輪際やり取りできひんくなるで。"
silencedInstances: "サーバーサイレンスされてんねん"
silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定すんで。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなんねん。ブロックしたインスタンスには影響せーへんで。"
mediaSilencedInstances: "メディアサイレンスしたサーバー"
mediaSilencedInstancesDescription: "メディアサイレンスしたいサーバーのホストを改行で区切って設定するで。メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われてな、カスタム絵文字が使えへんようになるで。ブロックしたインスタンスには影響せえへんで。"
muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしとるユーザー"
blockedUsers: "ブロックしとるユーザー"
@ -475,6 +487,7 @@ noMessagesYet: "まだチャットはあらへんで"
newMessageExists: "新しいメッセージがきたで"
onlyOneFileCanBeAttached: "ごめんな、メッセージに添付できるファイルはひとつだけなんよ。"
signinRequired: "ログインしてくれへん?"
signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があるで"
invitations: "来てや"
invitationCode: "招待コード"
checking: "確認しとるで"
@ -1025,6 +1038,7 @@ thisPostMayBeAnnoyingHome: "ホームに投稿"
thisPostMayBeAnnoyingCancel: "やめとく"
thisPostMayBeAnnoyingIgnore: "このまま投稿"
collapseRenotes: "見たことあるリノートは飛ばして表示するで"
collapseRenotesDescription: "リアクションやリノートをしたことがあるノートをたたんで表示するで。"
internalServerError: "サーバー内部エラー"
internalServerErrorDescription: "サーバーでなんか変なこと起こっとるわ。"
copyErrorInfo: "エラー情報をコピるで"
@ -1098,6 +1112,8 @@ preservedUsernames: "予約ユーザー名"
preservedUsernamesDescription: "予約しとくユーザー名を行ごとに挙げるで。ここで指定されたユーザー名はアカウント作るときに使えへんくなるけど、管理者は例外や。あと、もうあるアカウントも例外やな。"
createNoteFromTheFile: "このファイル使うてノート作るで"
archive: "アーカイブ"
archived: "アーカイブ済み"
unarchive: "アーカイブ解除"
channelArchiveConfirmTitle: "{name}をアーカイブしてええか?"
channelArchiveConfirmDescription: "アーカイブしたら、チャンネル一覧とか検索結果からなくなるし、新しく書き込みもできへんなるで。"
thisChannelArchived: "このチャンネル、アーカイブされとるで。"
@ -1108,6 +1124,9 @@ preventAiLearning: "生成AIの学習に使わんといて"
preventAiLearningDescription: "他の文章生成AIとか画像生成AIに、投稿したートとか画像なんかを勝手に使わんように頼むで。具体的にはnoaiフラグをHTMLレスポンスに含めるんやけど、これ聞いてくれるんはAIの気分次第やから、使われる可能性もちょっとはあるな。"
options: "オプション"
specifyUser: "ユーザー指定"
lookupConfirm: "照会するけどええか?"
openTagPageConfirm: "ハッシュタグのページを開くんか?"
specifyHost: "ホスト指定"
failedToPreviewUrl: "プレビューできへん"
update: "更新"
rolesThatCanBeUsedThisEmojiAsReaction: "ツッコミとして使えるロール"
@ -1239,10 +1258,20 @@ keepOriginalFilenameDescription: "この設定をオフにすると、アップ
noDescription: "説明文はあらへんで"
alwaysConfirmFollow: "フォローの際常に確認する"
inquiry: "問い合わせ"
tryAgain: "もう一度試しいや。"
confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示するとき確認する"
sensitiveMediaRevealConfirm: "センシティブなメディアやで。表示するんか?"
createdLists: "作成したリスト"
createdAntennas: "作成したアンテナ"
_delivery:
status: "配信状態"
stop: "配信せぇへん"
resume: "配信再開"
_type:
none: "配信しとる"
manuallySuspended: "手動停止中"
goneSuspended: "サーバー削除のため停止中"
autoSuspendedForNotResponding: "サーバー応答せえへんから停止中"
_bubbleGame:
howToPlay: "遊び方"
hold: "ホールド"
@ -1368,6 +1397,8 @@ _serverSettings:
fanoutTimelineDescription: "入れると、おのおのタイムラインを取得するときにめちゃめちゃ動きが良うなって、データベースが軽くなるわ。でも、Redisのメモリ使う量が増えるから注意な。サーバーのメモリが足りんときとか、動きが変なときは切れるで。"
fanoutTimelineDbFallback: "データベースにフォールバックする"
fanoutTimelineDbFallbackDescription: "有効にしたら、タイムラインがキャッシュん中に入ってないときにDBにもっかい問い合わせるフォールバック処理ってのをやっとくで。切ったらフォールバック処理をやらんからサーバーはもっと軽くなんねんけど、タイムラインの取得範囲がちょっと減るで。"
inquiryUrl: "問い合わせ先URL"
inquiryUrlDescription: "サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定するで。"
_accountMigration:
moveFrom: "別のアカウントからこのアカウントに引っ越す"
moveFromSub: "別のアカウントへエイリアスを作る"
@ -1684,6 +1715,7 @@ _role:
canManageAvatarDecorations: "アバターを飾るモンの管理"
driveCapacity: "ドライブ容量"
alwaysMarkNsfw: "勝手にファイルにNSFWをくっつける"
canUpdateBioMedia: "アイコンとバナーの更新を許可"
pinMax: "ノートピン留めできる数"
antennaMax: "アンテナ作れる数"
wordMuteMax: "ワードミュートの最大文字数"
@ -1935,6 +1967,7 @@ _soundSettings:
driveFileTypeWarnDescription: "音声ファイルを選びや"
driveFileDurationWarn: "音が長すぎるわ"
driveFileDurationWarnDescription: "長い音使うたらMisskey使うのに良うないかもしれへんで。それでもええか"
driveFileError: "音声が読み込めへんかったで。設定を変更せえや"
_ago:
future: "未来"
justNow: "ついさっき"
@ -2351,6 +2384,7 @@ _deck:
alwaysShowMainColumn: "いつもメインカラムを表示"
columnAlign: "カラムの寄せ"
addColumn: "カラムを追加"
newNoteNotificationSettings: "新着ノート通知の設定"
configureColumn: "カラムの設定"
swapLeft: "左に移動"
swapRight: "右に移動"
@ -2389,9 +2423,10 @@ _drivecleaner:
orderByCreatedAtAsc: "追加日の古い順"
_webhookSettings:
createWebhook: "Webhookをつくる"
modifyWebhook: "Webhookを編集"
name: "名前"
secret: "シークレット"
events: "Webhookを投げるタイミング"
trigger: "トリガー"
active: "有効"
_events:
follow: "フォローしたとき~!"
@ -2401,11 +2436,25 @@ _webhookSettings:
renote: "リノートされるとき~!"
reaction: "ツッコまれたとき~!"
mention: "メンションがあるとき~!"
_systemEvents:
abuseReport: "ユーザーから通報があったとき"
abuseReportResolved: "ユーザーからの通報を処理したとき"
userCreated: "ユーザーが作成されたとき"
deleteConfirm: "ほんまにWebhookをほかしてもええんか"
_abuseReport:
_notificationRecipient:
createRecipient: "通報の通知先を追加"
modifyRecipient: "通報の通知先を編集"
recipientType: "通知先の種類"
_recipientType:
mail: "メール"
webhook: "Webhook"
_captions:
mail: "モデレーター権限を持つユーザーのメアドに通知を送るで(通報を受けた時のみ)"
webhook: "指定したSystemWebhookに通知を送るで(通報を受けた時と通報を解決した時にそれぞれ発信)"
keywords: "キーワード"
notifiedUser: "通知先ユーザー"
notifiedWebhook: "使用するWebhook"
deleteConfirm: "通知先を削除してもええか?"
_moderationLogTypes:
createRole: "ロールを追加すんで"
@ -2444,6 +2493,8 @@ _moderationLogTypes:
deleteAvatarDecoration: "アイコンデコレーションを削除"
unsetUserAvatar: "この子のアイコン元に戻す"
unsetUserBanner: "この子のバナー元に戻す"
createSystemWebhook: "SystemWebhookを作成"
updateSystemWebhook: "SystemWebhookを更新"
_fileViewer:
title: "ファイルの詳しい情報"
type: "ファイルの種類"

View file

@ -2411,7 +2411,6 @@ _webhookSettings:
modifyWebhook: "Webhook 수정"
name: "이름"
secret: "시크릿"
events: "Webhook을 실행할 타이밍"
active: "활성화"
_events:
follow: "누군가를 팔로우했을 때"

View file

@ -1544,7 +1544,6 @@ _webhookSettings:
createWebhook: "Stwórz Webhook"
name: "Nazwa"
secret: "Sekret"
events: "Uruchomienie Webhooka"
active: "Właczono"
_events:
follow: "Po zaobserwowaniu użytkownika"

File diff suppressed because it is too large Load diff

View file

@ -60,6 +60,7 @@ copyFileId: "คัดลอกไฟล์ ID"
copyFolderId: "คัดลอกโฟลเดอร์ ID"
copyProfileUrl: "คัดลอกโปรไฟล์ URL"
searchUser: "ค้นหาผู้ใช้"
searchThisUsersNotes: "ค้นหาโน้ตของผู้ใช้"
reply: "ตอบกลับ"
loadMore: "แสดงเพิ่มเติม"
showMore: "แสดงเพิ่มเติม"
@ -154,6 +155,7 @@ editList: "แก้ไขรายชื่อ"
selectChannel: "เลือกช่อง"
selectAntenna: "เลือกเสาอากาศ"
editAntenna: "แก้ไขเสาอากาศ"
createAntenna: "สร้างเสาอากาศ"
selectWidget: "เลือกวิดเจ็ต"
editWidgets: "แก้ไขวิดเจ็ต"
editWidgetsExit: "เรียบร้อย"
@ -194,6 +196,7 @@ followConfirm: "ต้องการติดตาม {name} ใช่ไห
proxyAccount: "บัญชีพร็อกซี่"
proxyAccountDescription: "บัญชีพร็อกซี คือ บัญชีที่ทำหน้าที่ติดตาม(ผู้ใช้)ระยะไกลภายใต้เงื่อนไขบางประการ ตัวอย่างเช่น เมื่อผู้ใช้ท้องถิ่นเพิ่มผู้ใช้ระยะไกลลงรายชื่อ หากไม่มีใครติดตามผู้ใช้ระยะไกลในรายชื่อนั้น กิจกรรมก็จะไม่ถูกส่งมายังเซิร์ฟเวอร์ ดังนั้นจึงมีบัญชีพร็อกซีไว้ติดตามผู้ใช้ระยะไกลเหล่านั้น"
host: "โฮสต์"
selectSelf: "เลือกตัวเอง"
selectUser: "เลือกผู้ใช้งาน"
recipient: "ผู้รับ"
annotation: "หมายเหตุประกอบ"
@ -209,6 +212,7 @@ perDay: "ต่อวัน"
stopActivityDelivery: "หยุดส่งกิจกรรม"
blockThisInstance: "บล็อกเซิร์ฟเวอร์นี้"
silenceThisInstance: "ปิดปากเซิร์ฟเวอร์นี้"
mediaSilenceThisInstance: "ปิดปากสื่อของเซิร์ฟเวอร์นี้"
operations: "ดำเนินการ"
software: "ซอฟต์แวร์"
version: "เวอร์ชั่น"
@ -230,6 +234,8 @@ blockedInstances: "เซิร์ฟเวอร์ที่ถูกบล็
blockedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการบล็อก คั่นด้วยการขึ้นบรรทัดใหม่ เซิร์ฟเวอร์ที่ถูกบล็อกจะไม่สามารถติดต่อกับอินสแตนซ์นี้ได้"
silencedInstances: "ปิดปากเซิร์ฟเวอร์นี้แล้ว"
silencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปาก คั่นด้วยการขึ้นบรรทัดใหม่, บัญชีทั้งหมดของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในเซิร์ฟเวอร์นี้ได้หากไม่ได้ถูกติดตามกลับ | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก"
mediaSilencedInstances: "เซิร์ฟเวอร์ที่ถูกปิดปากสื่อ"
mediaSilencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปากสื่อ คั่นด้วยการขึ้นบรรทัดใหม่, ไฟล์ที่ถูกส่งจากบัญชีของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปาก แล้วจะถูกติดเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน และเอโมจิแบบกำหนดเองก็จะใช้ไม่ได้ด้วย | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก"
muteAndBlock: "ปิดเสียงและบล็อก"
mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง"
blockedUsers: "ผู้ใช้ที่ถูกบล็อก"
@ -881,7 +887,7 @@ accountDeletionInProgress: "กำลังดำเนินการลบบ
usernameInfo: "ชื่อที่ระบุบัญชีของคุณจากผู้อื่นในเซิร์ฟเวอร์นี้ คุณสามารถใช้ตัวอักษร (a~z, A~Z), ตัวเลข (0~9) หรือขีดล่าง (_) ชื่อผู้ใช้ไม่สามารถเปลี่ยนแปลงได้ในภายหลัง"
aiChanMode: "โหมด Ai "
devMode: "โหมดนักพัฒนา"
keepCw: "เก็บคำเตือนเนื้อหา"
keepCw: "คงการเตือนเนื้อหาไว้"
pubSub: "บัญชี Pub/Sub"
lastCommunication: "การสื่อสารครั้งสุดท้ายล่าสุด"
resolved: "คลี่คลายแล้ว"
@ -1028,15 +1034,15 @@ achievements: "ความสำเร็จ"
gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง"
gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ"
thisPostMayBeAnnoying: "โน้ตนี้อาจจะเป็นการรบกวนผู้อื่นนะคะ"
thisPostMayBeAnnoyingHome: "โพสต์ไปยังไทม์ไลน์หลัก"
thisPostMayBeAnnoyingCancel: "เลิก"
thisPostMayBeAnnoyingIgnore: "โพสต์ยังไงก็แล้วแต่"
thisPostMayBeAnnoyingHome: "โพสต์ลงไทม์ไลน์หลักเท่านั้น"
thisPostMayBeAnnoyingCancel: "ยกเลิก"
thisPostMayBeAnnoyingIgnore: "โพสต์ไปเลย ไม่ต้องปรับการมองเห็น"
collapseRenotes: "ยุบรีโน้ตที่คุณเคยเห็นแล้ว"
collapseRenotesDescription: "พับย่อโน้ตที่เคยตอบสนองหรือรีโน้ตแล้ว"
internalServerError: "เซิร์ฟเวอร์ภายในเกิดข้อผิดพลาด"
internalServerErrorDescription: "เกิดข้อผิดพลาดที่ไม่คาดคิดภายในเซิร์ฟเวอร์"
copyErrorInfo: "คัดลอกรายละเอียดข้อผิดพลาด"
joinThisServer: "ลงทะเบียนนเซิร์ฟเวอร์นี้"
joinThisServer: "ลงทะเบียนนเซิร์ฟเวอร์นี้"
exploreOtherServers: "มองหาเซิร์ฟเวอร์อื่น"
letsLookAtTimeline: "มาดูไทม์ไลน์กัน"
disableFederationConfirm: "ปิดใช้งานสหพันธ์เลยใช่ไหม?"
@ -1099,13 +1105,15 @@ vertical: "แนวตั้ง"
horizontal: "แนวนอน"
position: "ตำแหน่ง"
serverRules: "กฎของเซิร์ฟเวอร์"
pleaseConfirmBelowBeforeSignup: "หากต้องการลงทะเบียนนเซิร์ฟเวอร์นี้ คุณต้องตรวจสอบและยอมรับสิ่งต่อไปนี้"
pleaseConfirmBelowBeforeSignup: "หากต้องการลงทะเบียนนเซิร์ฟเวอร์นี้ คุณต้องตรวจสอบและยอมรับสิ่งต่อไปนี้"
pleaseAgreeAllToContinue: "คุณต้องยอมรับทุกช่องตรงด้านบนเพื่อดำเนินการต่อค่ะ"
continue: "ดำเนินการต่อ"
preservedUsernames: "ชื่อผู้ใช้ที่สงวนไว้"
preservedUsernamesDescription: "ระบุชื่อผู้ใช้ที่จะสงวนชื่อไว้ คั่นด้วยการขึ้นบรรทัดใหม่ ชื่อผู้ใช้ที่ระบุที่นี่จะไม่สามารถใช้งานได้อีกต่อไปเมื่อสร้างบัญชีใหม่ ยกเว้นเมื่อผู้ดูแลระบบสร้างบัญชี นอกจากนี้ บัญชีที่มีอยู่แล้วจะไม่ได้รับผลกระทบ"
createNoteFromTheFile: "เรียบเรียงโน้ตจากไฟล์นี้"
archive: "เก็บถาวร"
archived: "เก็บถาวรแล้ว"
unarchive: "เลิกการเก็บถาวร"
channelArchiveConfirmTitle: "ต้องการเก็บถาวรเจ้า {name} ใช่ไหม?"
channelArchiveConfirmDescription: "เมื่อเก็บถาวรแล้ว จะไม่ปรากฏในรายการช่องหรือผลการค้นหาอีกต่อไป และจะไม่สามารถโพสต์ใหม่ได้อีกต่อไป"
thisChannelArchived: "ช่องนี้ถูกเก็บถาวรแล้วนะ"
@ -1116,6 +1124,9 @@ preventAiLearning: "ปฏิเสธการเรียนรู้ด้ว
preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว"
options: "ตัวเลือกบทบาท"
specifyUser: "ผู้ใช้เฉพาะ"
lookupConfirm: "ต้องการเรียกดูข้อมูลใช่ไหม?"
openTagPageConfirm: "ต้องการเปิดหน้าแฮชแท็กใช่ไหม?"
specifyHost: "ระบุโฮสต์"
failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้"
update: "อัปเดต"
rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้"
@ -1250,6 +1261,8 @@ inquiry: "ติดต่อเรา"
tryAgain: "โปรดลองอีกครั้ง"
confirmWhenRevealingSensitiveMedia: "ตรวจสอบก่อนแสดงสื่อที่มีเนื้อหาละเอียดอ่อน"
sensitiveMediaRevealConfirm: "สื่อนี้มีเนื้อหาละเอียดอ่อน, ต้องการแสดงใช่ไหม?"
createdLists: "รายชื่อที่ถูกสร้าง"
createdAntennas: "เสาอากาศที่ถูกสร้าง"
_delivery:
status: "สถานะการจัดส่ง"
stop: "ระงับการส่ง"
@ -1348,9 +1361,9 @@ _initialTutorial:
localOnly: "การโพสต์ด้วย flag นี้จะไม่รวมโน้ตไปยังเซิร์ฟเวอร์อื่น ผู้ใช้บนเซิร์ฟเวอร์อื่นจะไม่สามารถดูโน้ตเหล่านี้ได้โดยตรง โดยไม่คำนึงถึงการตั้งค่าการแสดงผลข้างต้น"
_cw:
title: "คำเตือนเกี่ยวกับเนื้อหา"
description: "เนื้อหาที่เขียนด้วย “คำอธิบายประกอบ” จะแสดงแทนข้อความหลัก คลิก “ดูเพิ่มเติม” เพื่อแสดงข้อความเต็ม"
description: "เนื้อหาที่เขียนใน “คำอธิบายประกอบ” จะแสดงแทนเนื้อหาหลัก ต้องคลิก “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง"
_exampleNote:
cw: "นี่อาจจะทำให้คุณหิวอย่างแน่นอน!"
cw: " ห้ามดู ระวังหิว"
note: "เพิ่งไปกินโดนัทเคลือบช็อคโกแลตมา 🍩😋"
useCases: "ใช้สิ่งนี้เพื่อระบุโน้ตที่ต้องตามแนวทางปฏิบัติของเซิร์ฟเวอร์ หรือเพื่อควบคุมการสปอยล์และข้อความที่ละเอียดอ่อนด้วยตนเอง"
_howToMakeAttachmentsSensitive:
@ -1466,15 +1479,15 @@ _achievements:
title: "มือใหม่ III"
description: "เข้าสู่ระบบเป็นเวลารวม 15 วัน"
_login30:
title: "มิสคิส์ I"
title: "มิสคิส์ I"
description: "เข้าสู่ระบบเป็นเวลารวม 30 วัน"
_login60:
title: "มิสคิส์ II"
title: "มิสคิส์ II"
description: "เข้าสู่ระบบเป็นเวลารวม 60 วัน"
_login100:
title: "มิสคิส์ III"
title: "มิสคิส์ III"
description: "เข้าสู่ระบบเป็นเวลารวม 100 วัน"
flavor: "มิสคิสต์หัวรุนแรง"
flavor: "Violent Misskist (ทำไมเหมือนชื่อหนังสักเรื่องจังเลยนะ)"
_login200:
title: "ลูกค้าประจำ I"
description: "เข้าสู่ระบบเป็นเวลารวม 200 วัน"
@ -1954,6 +1967,7 @@ _soundSettings:
driveFileTypeWarnDescription: "กรุณาเลือกไฟล์เสียง"
driveFileDurationWarn: "เสียงยาวเกินไป"
driveFileDurationWarnDescription: "การใช้เสียงที่ยาว อาจรบกวนการใช้งาน Misskey, ต้องการดำเนินการต่อใช่ไหม?"
driveFileError: "ไม่สามารถโหลดไฟล์เสียงได้ กรุณาเปลี่ยนแปลงการตั้งค่า"
_ago:
future: "อนาคต"
justNow: "เมื่อกี๊นี้"
@ -2141,7 +2155,7 @@ _widgets:
serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์"
aiscript: " คอนโซล AiScript"
aiscriptApp: "แอป AiScript"
aichan: "ไอ"
aichan: "藍 (ไอ)"
userList: "รายชื่อผู้ใช้"
_userList:
chooseList: "เลือกรายชื่อ"
@ -2183,7 +2197,7 @@ _visibility:
followersDescription: "เฉพาะผู้ติดตามเท่านั้นที่มองเห็นได้"
specified: "ไดเร็ค"
specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น"
disableFederation: "ไม่มีสหพันธ์"
disableFederation: "การปิดใช้งานสหพันธ์"
disableFederationDescription: "อย่าส่งข้อมูลไปยังเซิร์ฟเวอร์อื่น"
_postForm:
replyPlaceholder: "ตอบกลับโน้ตนี้..."
@ -2412,7 +2426,7 @@ _webhookSettings:
modifyWebhook: "แก้ไข Webhook"
name: "ชื่อ"
secret: "ความลับ"
events: "อีเว้นท์ Webhook"
trigger: "ทริกเกอร์"
active: "เปิดใช้งาน"
_events:
follow: "เมื่อกำลังติดตามผู้ใช้"
@ -2536,7 +2550,7 @@ _externalResourceInstaller:
description: "เกิดปัญหาระหว่างการติดตั้งธีม กรุณาลองอีกครั้ง. รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript"
_dataSaver:
_media:
title: "โหลดมีเดีย"
title: "โหลดสื่อ"
description: "กันไม่ให้ภาพและวิดีโอโหลดโดยอัตโนมัติ แตะรูปภาพ/วิดีโอที่ซ่อนอยู่เพื่อโหลด"
_avatar:
title: "รูปไอคอน"
@ -2616,3 +2630,8 @@ _mediaControls:
pip: "รูปภาพในรูปภาม"
playbackRate: "ความเร็วในการเล่น"
loop: "เล่นวนซ้ำ"
_contextMenu:
title: "เมนูเนื้อหา"
app: "แอปพลิเคชัน"
appWithShift: "แอปฟลิเคชันด้วยปุ่มยกแคร่ (Shift)"
native: "UI ของเบราว์เซอร์"

View file

@ -1918,7 +1918,6 @@ _webhookSettings:
createWebhook: "Tạo Webhook"
name: "Tên"
secret: "Mã bí mật"
events: "Sự kiện Webhook"
active: "Đã bật"
_events:
reaction: "Khi nhận được sự kiện"

View file

@ -1665,6 +1665,7 @@ _achievements:
_bubbleGameDoubleExplodingHead:
title: "两个🤯"
description: "你合成出了2个游戏里最大的Emoji"
flavor: ""
_role:
new: "创建角色"
edit: "编辑角色"
@ -2425,7 +2426,7 @@ _webhookSettings:
modifyWebhook: "编辑 webhook"
name: "名称"
secret: "密钥"
events: "何时运行 Webhook"
trigger: "触发器"
active: "已启用"
_events:
follow: "关注时"

View file

@ -1967,7 +1967,7 @@ _soundSettings:
driveFileTypeWarnDescription: "請選擇音效檔案"
driveFileDurationWarn: "音效太長了"
driveFileDurationWarnDescription: "使用長音效檔可能會影響 Misskey 的使用體驗。仍要使用此檔案嗎?"
driveFileError: "無法載入語音。請設定"
driveFileError: "無法載入語音。請更設定"
_ago:
future: "未來"
justNow: "剛剛"
@ -2426,7 +2426,7 @@ _webhookSettings:
modifyWebhook: "編輯 Webhook"
name: "名字"
secret: "密鑰"
events: "何時運行 Webhook"
trigger: "觸發器"
active: "已啟用"
_events:
follow: "當你追隨時"
@ -2439,6 +2439,7 @@ _webhookSettings:
_systemEvents:
abuseReport: "當使用者檢舉時"
abuseReportResolved: "當處理了使用者的檢舉時"
userCreated: "使用者被新增時"
deleteConfirm: "請問是否要刪除 Webhook"
_abuseReport:
_notificationRecipient:
@ -2632,4 +2633,5 @@ _mediaControls:
_contextMenu:
title: "內容功能表"
app: "應用程式"
appWithShift: "Shift 鍵應用程式"
native: "瀏覽器的使用者介面"

View file

@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2024.7.0-rc.8",
"version": "2024.8.0-alpha.0",
"codename": "nasubi",
"repository": {
"type": "git",

View file

@ -15,7 +15,7 @@ import isSvg from 'is-svg';
import probeImageSize from 'probe-image-size';
import { type predictionType } from 'nsfwjs';
import { sharpBmp } from '@misskey-dev/sharp-read-bmp';
import { encode } from 'blurhash';
import * as blurhash from 'blurhash';
import { createTempDir } from '@/misc/create-temp.js';
import { AiService } from '@/core/AiService.js';
import { LoggerService } from '@/core/LoggerService.js';
@ -452,7 +452,7 @@ export class FileInfoService {
}
/**
* Calculate average color of image
* Calculate blurhash string of image
*/
@bindThis
private getBlurhash(path: string, type: string): Promise<string> {
@ -467,7 +467,7 @@ export class FileInfoService {
let hash;
try {
hash = encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5);
hash = blurhash.encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5);
} catch (e) {
return reject(e);
}

View file

@ -9,7 +9,8 @@ import type { ModerationLogsRepository } from '@/models/_.js';
import type { MiUser } from '@/models/User.js';
import { IdService } from '@/core/IdService.js';
import { bindThis } from '@/decorators.js';
import { ModerationLogPayloads, moderationLogTypes } from '@/types.js';
import type { ModerationLogPayloads } from '@/types.js';
import { moderationLogTypes } from '@/types.js';
@Injectable()
export class ModerationLogService {

View file

@ -509,7 +509,7 @@ export class NoteCreateService implements OnApplicationShutdown {
const meta = await this.metaService.fetch();
this.notesChart.update(note, true);
if (meta.enableChartsForRemoteUser || (user.host == null)) {
if (note.visibility !== 'specified' && (meta.enableChartsForRemoteUser || (user.host == null))) {
this.perUserNotesChart.update(user, note, true);
}

View file

@ -92,7 +92,7 @@ export class NoteDeleteService {
this.deliverToConcerned(user, note, content);
}
// also deliever delete activity to cascaded notes
// also deliver delete activity to cascaded notes
const federatedLocalCascadingNotes = (cascadingNotes).filter(note => !note.localOnly && note.userHost == null); // filter out local-only notes
for (const cascadingNote of federatedLocalCascadingNotes) {
if (!cascadingNote.user) continue;

View file

@ -78,9 +78,10 @@ export class ApNoteService {
@bindThis
public validateNote(object: IObject, uri: string): Error | null {
const expectHost = this.utilityService.extractDbHost(uri);
const apType = getApType(object);
if (!validPost.includes(getApType(object))) {
return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${getApType(object)}`);
if (apType == null || !validPost.includes(apType)) {
return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${apType ?? 'undefined'}`);
}
if (object.id && this.utilityService.extractDbHost(object.id) !== expectHost) {

View file

@ -48,7 +48,7 @@ import type { ApResolverService, Resolver } from '../ApResolverService.js';
import type { ApLoggerService } from '../ApLoggerService.js';
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type { ApImageService } from './ApImageService.js';
import type { IActor, IObject } from '../type.js';
import type { IActor, ICollection, IObject, IOrderedCollection } from '../type.js';
const nameLength = 128;
const summaryLength = 2048;
@ -296,6 +296,21 @@ export class ApPersonService implements OnModuleInit {
const isBot = getApType(object) === 'Service' || getApType(object) === 'Application';
const [followingVisibility, followersVisibility] = await Promise.all(
[
this.isPublicCollection(person.following, resolver),
this.isPublicCollection(person.followers, resolver),
].map((p): Promise<'public' | 'private'> => p
.then(isPublic => isPublic ? 'public' : 'private')
.catch(err => {
if (!(err instanceof StatusError) || err.isRetryable) {
this.logger.error('error occurred while fetching following/followers collection', { stack: err });
}
return 'private';
})
)
);
const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/);
const url = getOneApHrefNullable(person.url);
@ -357,6 +372,8 @@ export class ApPersonService implements OnModuleInit {
description: _description,
url,
fields,
followingVisibility,
followersVisibility,
birthday: bday?.[0] ?? null,
location: person['vcard:Address'] ?? null,
userHost: host,
@ -464,6 +481,23 @@ export class ApPersonService implements OnModuleInit {
const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32);
const [followingVisibility, followersVisibility] = await Promise.all(
[
this.isPublicCollection(person.following, resolver),
this.isPublicCollection(person.followers, resolver),
].map((p): Promise<'public' | 'private' | undefined> => p
.then(isPublic => isPublic ? 'public' : 'private')
.catch(err => {
if (!(err instanceof StatusError) || err.isRetryable) {
this.logger.error('error occurred while fetching following/followers collection', { stack: err });
// Do not update the visibiility on transient errors.
return undefined;
}
return 'private';
})
)
);
const bday = person['vcard:bday']?.match(/^\d{4}-\d{2}-\d{2}/);
const url = getOneApHrefNullable(person.url);
@ -532,6 +566,8 @@ export class ApPersonService implements OnModuleInit {
url,
fields,
description: _description,
followingVisibility,
followersVisibility,
birthday: bday?.[0] ?? null,
location: person['vcard:Address'] ?? null,
});
@ -703,4 +739,16 @@ export class ApPersonService implements OnModuleInit {
return 'ok';
}
@bindThis
private async isPublicCollection(collection: string | ICollection | IOrderedCollection | undefined, resolver: Resolver): Promise<boolean> {
if (collection) {
const resolved = await resolver.resolveCollection(collection);
if (resolved.first || (resolved as ICollection).items || (resolved as IOrderedCollection).orderedItems) {
return true;
}
}
return false;
}
}

View file

@ -60,11 +60,14 @@ export function getApId(value: string | IObject): string {
/**
* Get ActivityStreams Object type
*
* nullを返すようにしている
* 詳細: https://github.com/misskey-dev/misskey/issues/14239
*/
export function getApType(value: IObject): string {
export function getApType(value: IObject): string | null {
if (typeof value.type === 'string') return value.type;
if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0];
throw new Error('cannot detect type');
return null;
}
export function getOneApHrefNullable(value: ApObject | undefined): string | undefined {
@ -97,19 +100,23 @@ export interface IActivity extends IObject {
export interface ICollection extends IObject {
type: 'Collection';
totalItems: number;
items: ApObject;
first?: IObject | string;
items?: ApObject;
}
export interface IOrderedCollection extends IObject {
type: 'OrderedCollection';
totalItems: number;
orderedItems: ApObject;
first?: IObject | string;
orderedItems?: ApObject;
}
export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event'];
export const isPost = (object: IObject): object is IPost =>
validPost.includes(getApType(object));
export const isPost = (object: IObject): object is IPost => {
const type = getApType(object);
return type != null && validPost.includes(type);
};
export interface IPost extends IObject {
type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event';
@ -156,8 +163,10 @@ export const isTombstone = (object: IObject): object is ITombstone =>
export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application'];
export const isActor = (object: IObject): object is IActor =>
validActor.includes(getApType(object));
export const isActor = (object: IObject): object is IActor => {
const type = getApType(object);
return type != null && validActor.includes(type);
};
export interface IActor extends IObject {
type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application';
@ -240,12 +249,16 @@ export interface IKey extends IObject {
publicKeyPem: string | Buffer;
}
export const validDocumentTypes = ['Audio', 'Document', 'Image', 'Page', 'Video'];
export interface IApDocument extends IObject {
type: 'Audio' | 'Document' | 'Image' | 'Page' | 'Video';
}
export const isDocument = (object: IObject): object is IApDocument =>
['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object));
export const isDocument = (object: IObject): object is IApDocument => {
const type = getApType(object);
return type != null && validDocumentTypes.includes(type);
};
export interface IApImage extends IApDocument {
type: 'Image';
@ -323,7 +336,10 @@ export const isAccept = (object: IObject): object is IAccept => getApType(object
export const isReject = (object: IObject): object is IReject => getApType(object) === 'Reject';
export const isAdd = (object: IObject): object is IAdd => getApType(object) === 'Add';
export const isRemove = (object: IObject): object is IRemove => getApType(object) === 'Remove';
export const isLike = (object: IObject): object is ILike => getApType(object) === 'Like' || getApType(object) === 'EmojiReaction' || getApType(object) === 'EmojiReact';
export const isLike = (object: IObject): object is ILike => {
const type = getApType(object);
return type != null && ['Like', 'EmojiReaction', 'EmojiReact'].includes(type);
};
export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce';
export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block';
export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag';

View file

@ -49,6 +49,7 @@ export class FlashEntityService {
title: flash.title,
summary: flash.summary,
script: flash.script,
visibility: flash.visibility,
likedCount: flash.likedCount,
isLiked: meId ? await this.flashLikesRepository.exists({ where: { flashId: flash.id, userId: meId } }) : undefined,
});

View file

@ -63,8 +63,9 @@ export class InstanceEntityService {
@bindThis
public packMany(
instances: MiInstance[],
me?: { id: MiUser['id']; } | null | undefined,
) {
return Promise.all(instances.map(x => this.pack(x)));
return Promise.all(instances.map(x => this.pack(x, me)));
}
}

View file

@ -454,12 +454,12 @@ export class UserEntityService implements OnModuleInit {
}
const followingCount = profile == null ? null :
(profile.followingVisibility === 'public') || isMe ? user.followingCount :
(profile.followingVisibility === 'public') || isMe || iAmModerator ? user.followingCount :
(profile.followingVisibility === 'followers') && (relation && relation.isFollowing) ? user.followingCount :
null;
const followersCount = profile == null ? null :
(profile.followersVisibility === 'public') || isMe ? user.followersCount :
(profile.followersVisibility === 'public') || isMe || iAmModerator ? user.followersCount :
(profile.followersVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount :
null;

View file

@ -6,3 +6,7 @@
export type JsonValue = JsonArray | JsonObject | string | number | boolean | null;
export type JsonObject = {[K in string]?: JsonValue};
export type JsonArray = JsonValue[];
export function isJsonObject(value: JsonValue | undefined): value is JsonObject {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}

View file

@ -44,6 +44,11 @@ export const packedFlashSchema = {
type: 'string',
optional: false, nullable: false,
},
visibility: {
type: 'string',
optional: false, nullable: false,
enum: ['private', 'public'],
},
likedCount: {
type: 'number',
optional: false, nullable: true,

View file

@ -170,7 +170,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const instances = await query.limit(ps.limit).offset(ps.offset).getMany();
return await this.instanceEntityService.packMany(instances);
return await this.instanceEntityService.packMany(instances, me);
});
}
}

View file

@ -107,9 +107,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const gotPubCount = topPubInstances.map(x => x.followingCount).reduce((a, b) => a + b, 0);
return await awaitAll({
topSubInstances: this.instanceEntityService.packMany(topSubInstances),
topSubInstances: this.instanceEntityService.packMany(topSubInstances, me),
otherFollowersCount: Math.max(0, allSubCount - gotSubCount),
topPubInstances: this.instanceEntityService.packMany(topPubInstances),
topPubInstances: this.instanceEntityService.packMany(topPubInstances, me),
otherFollowingCount: Math.max(0, allPubCount - gotPubCount),
});
});

View file

@ -11,6 +11,7 @@ import { QueryService } from '@/core/QueryService.js';
import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../error.js';
export const meta = {
@ -81,6 +82,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private utilityService: UtilityService,
private followingEntityService: FollowingEntityService,
private queryService: QueryService,
private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
const user = await this.usersRepository.findOneBy(ps.userId != null
@ -93,23 +95,25 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
if (profile.followersVisibility === 'private') {
if (me == null || (me.id !== user.id)) {
throw new ApiError(meta.errors.forbidden);
}
} else if (profile.followersVisibility === 'followers') {
if (me == null) {
throw new ApiError(meta.errors.forbidden);
} else if (me.id !== user.id) {
const isFollowing = await this.followingsRepository.exists({
where: {
followeeId: user.id,
followerId: me.id,
},
});
if (!isFollowing) {
if (profile.followersVisibility !== 'public' && !await this.roleService.isModerator(me)) {
if (profile.followersVisibility === 'private') {
if (me == null || (me.id !== user.id)) {
throw new ApiError(meta.errors.forbidden);
}
} else if (profile.followersVisibility === 'followers') {
if (me == null) {
throw new ApiError(meta.errors.forbidden);
} else if (me.id !== user.id) {
const isFollowing = await this.followingsRepository.exists({
where: {
followeeId: user.id,
followerId: me.id,
},
});
if (!isFollowing) {
throw new ApiError(meta.errors.forbidden);
}
}
}
}

View file

@ -12,6 +12,7 @@ import { QueryService } from '@/core/QueryService.js';
import { FollowingEntityService } from '@/core/entities/FollowingEntityService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../error.js';
export const meta = {
@ -90,6 +91,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private utilityService: UtilityService,
private followingEntityService: FollowingEntityService,
private queryService: QueryService,
private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
const user = await this.usersRepository.findOneBy(ps.userId != null
@ -102,23 +104,25 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: user.id });
if (profile.followingVisibility === 'private') {
if (me == null || (me.id !== user.id)) {
throw new ApiError(meta.errors.forbidden);
}
} else if (profile.followingVisibility === 'followers') {
if (me == null) {
throw new ApiError(meta.errors.forbidden);
} else if (me.id !== user.id) {
const isFollowing = await this.followingsRepository.exists({
where: {
followeeId: user.id,
followerId: me.id,
},
});
if (!isFollowing) {
if (profile.followingVisibility !== 'public' && !await this.roleService.isModerator(me)) {
if (profile.followingVisibility === 'private') {
if (me == null || (me.id !== user.id)) {
throw new ApiError(meta.errors.forbidden);
}
} else if (profile.followingVisibility === 'followers') {
if (me == null) {
throw new ApiError(meta.errors.forbidden);
} else if (me.id !== user.id) {
const isFollowing = await this.followingsRepository.exists({
where: {
followeeId: user.id,
followerId: me.id,
},
});
if (!isFollowing) {
throw new ApiError(meta.errors.forbidden);
}
}
}
}

View file

@ -14,7 +14,8 @@ import { CacheService } from '@/core/CacheService.js';
import { MiFollowing, MiUserProfile } from '@/models/_.js';
import type { StreamEventEmitter, GlobalEvents } from '@/core/GlobalEventService.js';
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
import type { JsonObject } from '@/misc/json-value.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
import type { ChannelsService } from './ChannelsService.js';
import type { EventEmitter } from 'events';
import type Channel from './channel.js';
@ -112,8 +113,6 @@ export default class Connection {
const { type, body } = obj;
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
switch (type) {
case 'readNotification': this.onReadNotification(body); break;
case 'subNote': this.onSubscribeNote(body); break;
@ -154,7 +153,8 @@ export default class Connection {
}
@bindThis
private readNote(body: JsonObject) {
private readNote(body: JsonValue | undefined) {
if (!isJsonObject(body)) return;
const id = body.id;
const note = this.cachedNotes.find(n => n.id === id);
@ -166,7 +166,7 @@ export default class Connection {
}
@bindThis
private onReadNotification(payload: JsonObject) {
private onReadNotification(payload: JsonValue | undefined) {
this.notificationService.readAllNotification(this.user!.id);
}
@ -174,7 +174,8 @@ export default class Connection {
* 稿
*/
@bindThis
private onSubscribeNote(payload: JsonObject) {
private onSubscribeNote(payload: JsonValue | undefined) {
if (!isJsonObject(payload)) return;
if (!payload.id || typeof payload.id !== 'string') return;
const current = this.subscribingNotes[payload.id] ?? 0;
@ -190,7 +191,8 @@ export default class Connection {
* 稿
*/
@bindThis
private onUnsubscribeNote(payload: JsonObject) {
private onUnsubscribeNote(payload: JsonValue | undefined) {
if (!isJsonObject(payload)) return;
if (!payload.id || typeof payload.id !== 'string') return;
const current = this.subscribingNotes[payload.id];
@ -216,12 +218,13 @@ export default class Connection {
*
*/
@bindThis
private onChannelConnectRequested(payload: JsonObject) {
private onChannelConnectRequested(payload: JsonValue | undefined) {
if (!isJsonObject(payload)) return;
const { channel, id, params, pong } = payload;
if (typeof id !== 'string') return;
if (typeof channel !== 'string') return;
if (typeof pong !== 'boolean' && typeof pong !== 'undefined' && pong !== null) return;
if (typeof params !== 'undefined' && (typeof params !== 'object' || params === null || Array.isArray(params))) return;
if (typeof params !== 'undefined' && !isJsonObject(params)) return;
this.connectChannel(id, params, channel, pong ?? undefined);
}
@ -229,7 +232,8 @@ export default class Connection {
*
*/
@bindThis
private onChannelDisconnectRequested(payload: JsonObject) {
private onChannelDisconnectRequested(payload: JsonValue | undefined) {
if (!isJsonObject(payload)) return;
const { id } = payload;
if (typeof id !== 'string') return;
this.disconnectChannel(id);
@ -297,7 +301,8 @@ export default class Connection {
* @param data
*/
@bindThis
private onChannelMessageRequested(data: JsonObject) {
private onChannelMessageRequested(data: JsonValue | undefined) {
if (!isJsonObject(data)) return;
if (typeof data.id !== 'string') return;
if (typeof data.type !== 'string') return;
if (typeof data.body === 'undefined') return;

View file

@ -6,6 +6,7 @@
import Xev from 'xev';
import { Injectable } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
import Channel, { type MiChannelService } from '../channel.js';
@ -36,7 +37,7 @@ class QueueStatsChannel extends Channel {
public onMessage(type: string, body: JsonValue) {
switch (type) {
case 'requestLog':
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
if (!isJsonObject(body)) return;
if (typeof body.id !== 'string') return;
if (typeof body.length !== 'number') return;
ev.once(`queueStatsLog:${body.id}`, statsLog => {

View file

@ -9,6 +9,7 @@ import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { ReversiService } from '@/core/ReversiService.js';
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
import Channel, { type MiChannelService } from '../channel.js';
@ -44,16 +45,16 @@ class ReversiGameChannel extends Channel {
this.ready(body);
break;
case 'updateSettings':
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
if (!isJsonObject(body)) return;
if (typeof body.key !== 'string') return;
if (typeof body.value !== 'object' || body.value === null || Array.isArray(body.value)) return;
if (!isJsonObject(body.value)) return;
this.updateSettings(body.key, body.value);
break;
case 'cancel':
this.cancelGame();
break;
case 'putStone':
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
if (!isJsonObject(body)) return;
if (typeof body.pos !== 'number') return;
if (typeof body.id !== 'string') return;
this.putStone(body.pos, body.id);

View file

@ -6,6 +6,7 @@
import Xev from 'xev';
import { Injectable } from '@nestjs/common';
import { bindThis } from '@/decorators.js';
import { isJsonObject } from '@/misc/json-value.js';
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
import Channel, { type MiChannelService } from '../channel.js';
@ -36,7 +37,7 @@ class ServerStatsChannel extends Channel {
public onMessage(type: string, body: JsonValue) {
switch (type) {
case 'requestLog':
if (typeof body !== 'object' || body === null || Array.isArray(body)) return;
if (!isJsonObject(body)) return;
ev.once(`serverStatsLog:${body.id}`, statsLog => {
this.send('statsLog', statsLog);
});

View file

@ -28,6 +28,7 @@ html
meta(property='og:site_name' content= instanceName || 'Misskey')
meta(property='instance_url' content= instanceUrl)
meta(name='viewport' content='width=device-width, initial-scale=1')
meta(name='format-detection' content='telephone=no,date=no,address=no,email=no,url=no')
link(rel='icon' href= icon || '/favicon.ico')
link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png')
link(rel='manifest' href='/manifest.json')

View file

@ -20,7 +20,8 @@ import { CoreModule } from '@/core/CoreModule.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type { IActor, IApDocument, ICollection, IObject, IPost } from '@/core/activitypub/type.js';
import { MiMeta, MiNote } from '@/models/_.js';
import { MiMeta, MiNote, UserProfilesRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { secureRndstr } from '@/misc/secure-rndstr.js';
import { DownloadService } from '@/core/DownloadService.js';
import { MetaService } from '@/core/MetaService.js';
@ -86,6 +87,7 @@ async function createRandomRemoteUser(
}
describe('ActivityPub', () => {
let userProfilesRepository: UserProfilesRepository;
let imageService: ApImageService;
let noteService: ApNoteService;
let personService: ApPersonService;
@ -127,6 +129,8 @@ describe('ActivityPub', () => {
await app.init();
app.enableShutdownHooks();
userProfilesRepository = app.get(DI.userProfilesRepository);
noteService = app.get<ApNoteService>(ApNoteService);
personService = app.get<ApPersonService>(ApPersonService);
rendererService = app.get<ApRendererService>(ApRendererService);
@ -205,6 +209,53 @@ describe('ActivityPub', () => {
});
});
describe('Collection visibility', () => {
test('Public following/followers', async () => {
const actor = createRandomActor();
actor.following = {
id: `${actor.id}/following`,
type: 'OrderedCollection',
totalItems: 0,
first: `${actor.id}/following?page=1`,
};
actor.followers = `${actor.id}/followers`;
resolver.register(actor.id, actor);
resolver.register(actor.followers, {
id: actor.followers,
type: 'OrderedCollection',
totalItems: 0,
first: `${actor.followers}?page=1`,
});
const user = await personService.createPerson(actor.id, resolver);
const userProfile = await userProfilesRepository.findOneByOrFail({ userId: user.id });
assert.deepStrictEqual(userProfile.followingVisibility, 'public');
assert.deepStrictEqual(userProfile.followersVisibility, 'public');
});
test('Private following/followers', async () => {
const actor = createRandomActor();
actor.following = {
id: `${actor.id}/following`,
type: 'OrderedCollection',
totalItems: 0,
// first: …
};
actor.followers = `${actor.id}/followers`;
resolver.register(actor.id, actor);
//resolver.register(actor.followers, { … });
const user = await personService.createPerson(actor.id, resolver);
const userProfile = await userProfilesRepository.findOneByOrFail({ userId: user.id });
assert.deepStrictEqual(userProfile.followingVisibility, 'private');
assert.deepStrictEqual(userProfile.followersVisibility, 'private');
});
});
describe('Renderer', () => {
test('Render an announce with visibility: followers', () => {
rendererService.renderAnnounce('https://example.com/notes/00example', {

View file

@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { AISCRIPT_VERSION } from '@syuilo/aiscript';
import type { entities } from 'misskey-js'
export function abuseUserReport() {
@ -114,6 +115,40 @@ export function file(isSensitive = false) {
};
}
const script = `/// @ ${AISCRIPT_VERSION}
var name = ""
Ui:render([
Ui:C:textInput({
label: "Your name"
onInput: @(v) { name = v }
})
Ui:C:button({
text: "Hello"
onClick: @() {
Mk:dialog(null, \`Hello, {name}!\`)
}
})
])
`;
export function flash(): entities.Flash {
return {
id: 'someflashid',
createdAt: '2016-12-28T22:49:51.000Z',
updatedAt: '2016-12-28T22:49:51.000Z',
userId: 'someuserid',
user: userLite(),
title: 'Some Play title',
summary: 'Some Play summary',
script,
visibility: 'public',
likedCount: 0,
isLiked: false,
};
}
export function folder(id = 'somefolderid', name = 'Some Folder', parentId: string | null = null): entities.DriveFolder {
return {
id,

View file

@ -398,6 +398,7 @@ function toStories(component: string): Promise<string> {
glob('src/components/global/Mk*.vue'),
glob('src/components/global/RouterView.vue'),
glob('src/components/Mk[A-E]*.vue'),
glob('src/components/MkFlashPreview.vue'),
glob('src/components/MkGalleryPostPreview.vue'),
glob('src/components/MkSignupServerRules.vue'),
glob('src/components/MkUserSetupDialog.vue'),

View file

@ -28,7 +28,7 @@
"@tabler/icons-webfont": "3.3.0",
"@twemoji/parser": "15.1.1",
"@vitejs/plugin-vue": "5.1.0",
"@vue/compiler-sfc": "3.4.34",
"@vue/compiler-sfc": "3.4.37",
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.11",
"astring": "1.8.6",
"broadcast-channel": "7.0.0",
@ -72,7 +72,7 @@
"uuid": "10.0.0",
"v-code-diff": "1.12.0",
"vite": "5.3.5",
"vue": "3.4.34",
"vue": "3.4.37",
"vuedraggable": "next"
},
"devDependencies": {
@ -111,7 +111,7 @@
"@typescript-eslint/eslint-plugin": "7.17.0",
"@typescript-eslint/parser": "7.17.0",
"@vitest/coverage-v8": "1.6.0",
"@vue/runtime-core": "3.4.34",
"@vue/runtime-core": "3.4.37",
"acorn": "8.12.1",
"cross-env": "7.0.3",
"cypress": "13.13.1",

View file

@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { StoryObj } from '@storybook/vue3';
import MkFlashPreview from './MkFlashPreview.vue';
import { flash } from './../../.storybook/fakes.js';
export const Public = {
render(args) {
return {
components: {
MkFlashPreview,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MkFlashPreview v-bind="props" />',
};
},
args: {
flash: {
...flash(),
visibility: 'public',
},
},
parameters: {
layout: 'fullscreen',
},
decorators: [
() => ({
template: '<div style="display: flex; align-items: center; justify-content: center; height: 100vh"><div style="max-width: 700px; width: 100%; margin: 3rem"><story/></div></div>',
}),
],
} satisfies StoryObj<typeof MkFlashPreview>;
export const Private = {
...Public,
args: {
flash: {
...flash(),
visibility: 'private',
},
},
} satisfies StoryObj<typeof MkFlashPreview>;

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkA :to="`/play/${flash.id}`" class="vhpxefrk _panel">
<MkA :to="`/play/${flash.id}`" class="vhpxefrk _panel" :class="[{ gray: flash.visibility === 'private' }]">
<article>
<header>
<h1 :title="flash.title">{{ flash.title }}</h1>
@ -22,11 +22,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { } from 'vue';
import * as Misskey from 'misskey-js';
import { userName } from '@/filters/user.js';
const props = defineProps<{
//flash: Misskey.entities.Flash;
flash: any;
flash: Misskey.entities.Flash;
}>();
</script>
@ -91,6 +91,12 @@ const props = defineProps<{
}
}
&:global(.gray) {
--c: var(--bg);
background-image: linear-gradient(45deg, var(--c) 16.67%, transparent 16.67%, transparent 50%, var(--c) 50%, var(--c) 66.67%, transparent 66.67%, transparent 100%);
background-size: 16px 16px;
}
@media (max-width: 700px) {
}

View file

@ -264,6 +264,9 @@ const patronsWithIcon = [{
}, {
name: 'ささくれりょう',
icon: 'https://assets.misskey-hub.net/patrons/cf55022cee6c41da8e70a43587aaad9a.jpg',
}, {
name: 'Macop',
icon: 'https://assets.misskey-hub.net/patrons/ee052bf550014d36a643ce3dce595640.jpg',
}];
const patrons = [

View file

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div ref="el" class="hiyeyicy" :class="{ wide: !narrow }">
<div v-if="!narrow || currentPage?.route.name == null" class="nav">
<MkSpacer :contentMax="700" :marginMin="16">
<div class="lxpfedzu">
<div class="lxpfedzu _gaps">
<div class="banner">
<img :src="instance.iconUrl || '/favicon.ico'" alt="" class="icon"/>
</div>
@ -61,10 +61,10 @@ const narrow = ref(false);
const view = ref(null);
const el = ref<HTMLDivElement | null>(null);
const pageProps = ref({});
let noMaintainerInformation = isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail);
let noBotProtection = !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha && !instance.enableTurnstile;
let noEmailServer = !instance.enableEmail;
let noInquiryUrl = isEmpty(instance.inquiryUrl);
const noMaintainerInformation = computed(() => isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail));
const noBotProtection = computed(() => !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha && !instance.enableTurnstile && !instance.enableMcaptcha);
const noEmailServer = computed(() => !instance.enableEmail);
const noInquiryUrl = computed(() => isEmpty(instance.inquiryUrl));
const thereIsUnresolvedAbuseReport = ref(false);
const currentPage = computed(() => router.currentRef.value.child);
@ -235,25 +235,22 @@ const menuDef = computed(() => [{
}],
}]);
watch(narrow.value, () => {
if (currentPage.value?.route.name == null && !narrow.value) {
router.push('/admin/overview');
}
});
onMounted(() => {
ro.observe(el.value);
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
if (el.value != null) {
ro.observe(el.value);
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
}
if (currentPage.value?.route.name == null && !narrow.value) {
router.push('/admin/overview');
router.replace('/admin/overview');
}
});
onActivated(() => {
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
if (el.value != null) {
narrow.value = el.value.offsetWidth < NARROW_THRESHOLD;
}
if (currentPage.value?.route.name == null && !narrow.value) {
router.push('/admin/overview');
router.replace('/admin/overview');
}
});

View file

@ -369,7 +369,6 @@ const props = defineProps<{
}>();
const flash = ref<Misskey.entities.Flash | null>(null);
const visibility = ref<'private' | 'public'>('public');
if (props.id) {
flash.value = await misskeyApi('flash/show', {
@ -380,6 +379,7 @@ if (props.id) {
const title = ref(flash.value?.title ?? 'New Play');
const summary = ref(flash.value?.summary ?? '');
const permissions = ref(flash.value?.permissions ?? []);
const visibility = ref<'private' | 'public'>(flash.value?.visibility ?? 'public');
const script = ref(flash.value?.script ?? PRESET_DEFAULT);
function selectPreset(ev: MouseEvent) {

View file

@ -198,9 +198,6 @@ const menuDef = computed(() => [{
}],
}]);
watch(narrow, () => {
});
onMounted(() => {
ro.observe(el.value);

View file

@ -287,6 +287,11 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList
icon: basicTimelineIconClass(tl),
iconOnly: true,
})), {
icon: 'ti ti-list',
title: i18n.ts.lists,
iconOnly: true,
onClick: chooseList,
}, {
icon: 'ti ti-antenna',
title: i18n.ts.antennas,
iconOnly: true,

View file

@ -7,7 +7,7 @@ import * as Misskey from 'misskey-js';
import { $i } from '@/account.js';
export function isFollowingVisibleForMe(user: Misskey.entities.UserDetailed): boolean {
if ($i && $i.id === user.id) return true;
if ($i && ($i.id === user.id || $i.isAdmin || $i.isModerator)) return true;
if (user.followingVisibility === 'private') return false;
if (user.followingVisibility === 'followers' && !user.isFollowing) return false;
@ -15,7 +15,7 @@ export function isFollowingVisibleForMe(user: Misskey.entities.UserDetailed): bo
return true;
}
export function isFollowersVisibleForMe(user: Misskey.entities.UserDetailed): boolean {
if ($i && $i.id === user.id) return true;
if ($i && ($i.id === user.id || $i.isAdmin || $i.isModerator)) return true;
if (user.followersVisibility === 'private') return false;
if (user.followersVisibility === 'followers' && !user.isFollowing) return false;

View file

@ -39,7 +39,7 @@ export function isAvailableBasicTimeline(timeline: BasicTimelineType | undefined
case 'local':
return ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable);
case 'social':
return $i != null && instance.policies.ltlAvailable;
return $i != null && $i.policies.ltlAvailable;
case 'global':
return ($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable);
default:

View file

@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
"version": "2024.7.0-rc.8",
"version": "2024.8.0-alpha.0",
"description": "Misskey SDK for JavaScript",
"license": "MIT",
"main": "./built/index.js",

View file

@ -4672,6 +4672,8 @@ export type components = {
title: string;
summary: string;
script: string;
/** @enum {string} */
visibility: 'private' | 'public';
likedCount: number | null;
isLiked?: boolean;
};

View file

@ -11,7 +11,7 @@ describe('API', () => {
expectType<Misskey.entities.MetaResponse>(res);
});
test('conditional respose type (meta)', async () => {
test('conditional response type (meta)', async () => {
const cli = new Misskey.api.APIClient({
origin: 'https://misskey.test',
credential: 'TOKEN'
@ -30,7 +30,7 @@ describe('API', () => {
expectType<Misskey.entities.MetaResponse>(res4);
});
test('conditional respose type (users/show)', async () => {
test('conditional response type (users/show)', async () => {
const cli = new Misskey.api.APIClient({
origin: 'https://misskey.test',
credential: 'TOKEN'

View file

@ -720,10 +720,10 @@ importers:
version: 15.1.1
'@vitejs/plugin-vue':
specifier: 5.1.0
version: 5.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))
version: 5.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
'@vue/compiler-sfc':
specifier: 3.4.34
version: 3.4.34
specifier: 3.4.37
version: 3.4.37
aiscript-vscode:
specifier: github:aiscript-dev/aiscript-vscode#v0.1.11
version: https://codeload.github.com/aiscript-dev/aiscript-vscode/tar.gz/e1e1b27f2f72cd28a473e004b6da0d8fc0bd40d9
@ -849,16 +849,16 @@ importers:
version: 10.0.0
v-code-diff:
specifier: 1.12.0
version: 1.12.0(vue@3.4.34(typescript@5.5.4))
version: 1.12.0(vue@3.4.37(typescript@5.5.4))
vite:
specifier: 5.3.5
version: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)
vue:
specifier: 3.4.34
version: 3.4.34(typescript@5.5.4)
specifier: 3.4.37
version: 3.4.37(typescript@5.5.4)
vuedraggable:
specifier: next
version: 4.1.0(vue@3.4.34(typescript@5.5.4))
version: 4.1.0(vue@3.4.37(typescript@5.5.4))
devDependencies:
'@misskey-dev/summaly':
specifier: 5.1.0
@ -913,13 +913,13 @@ importers:
version: 8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))
'@storybook/vue3':
specifier: 8.2.6
version: 8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.4.34(typescript@5.5.4))
version: 8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.4.37(typescript@5.5.4))
'@storybook/vue3-vite':
specifier: 8.1.11
version: 8.1.11(bufferutil@4.0.8)(encoding@0.1.13)(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.4)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))
version: 8.1.11(bufferutil@4.0.8)(encoding@0.1.13)(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.4)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
'@testing-library/vue':
specifier: 8.1.0
version: 8.1.0(@vue/compiler-sfc@3.4.34)(@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4)))(vue@3.4.34(typescript@5.5.4))
version: 8.1.0(@vue/compiler-sfc@3.4.37)(@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4)))(vue@3.4.37(typescript@5.5.4))
'@types/escape-regexp':
specifier: 0.0.3
version: 0.0.3
@ -966,8 +966,8 @@ importers:
specifier: 1.6.0
version: 1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.77.8)(terser@5.31.3))
'@vue/runtime-core':
specifier: 3.4.34
version: 3.4.34
specifier: 3.4.37
version: 3.4.37
acorn:
specifier: 8.12.1
version: 8.12.1
@ -1592,18 +1592,10 @@ packages:
resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.23.4':
resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.24.7':
resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.22.20':
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.24.7':
resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
engines: {node: '>=6.9.0'}
@ -1636,16 +1628,6 @@ packages:
resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.23.9':
resolution: {integrity: sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/parser@7.24.5':
resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/parser@7.24.7':
resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==}
engines: {node: '>=6.0.0'}
@ -2156,14 +2138,6 @@ packages:
resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==}
engines: {node: '>=6.9.0'}
'@babel/types@7.23.5':
resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==}
engines: {node: '>=6.9.0'}
'@babel/types@7.24.0':
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
engines: {node: '>=6.9.0'}
'@babel/types@7.24.7':
resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==}
engines: {node: '>=6.9.0'}
@ -5403,29 +5377,26 @@ packages:
'@volar/typescript@2.4.0-alpha.18':
resolution: {integrity: sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==}
'@vue/compiler-core@3.4.29':
resolution: {integrity: sha512-TFKiRkKKsRCKvg/jTSSKK7mYLJEQdUiUfykbG49rubC9SfDyvT2JrzTReopWlz2MxqeLyxh9UZhvxEIBgAhtrg==}
'@vue/compiler-core@3.4.31':
resolution: {integrity: sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==}
'@vue/compiler-core@3.4.34':
resolution: {integrity: sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==}
'@vue/compiler-dom@3.4.29':
resolution: {integrity: sha512-A6+iZ2fKIEGnfPJejdB7b1FlJzgiD+Y/sxxKwJWg1EbJu6ZPgzaPQQ51ESGNv0CP6jm6Z7/pO6Ia8Ze6IKrX7w==}
'@vue/compiler-dom@3.4.31':
resolution: {integrity: sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==}
'@vue/compiler-core@3.4.37':
resolution: {integrity: sha512-ZDDT/KiLKuCRXyzWecNzC5vTcubGz4LECAtfGPENpo0nrmqJHwuWtRLxk/Sb9RAKtR9iFflFycbkjkY+W/PZUQ==}
'@vue/compiler-dom@3.4.34':
resolution: {integrity: sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==}
'@vue/compiler-sfc@3.4.34':
resolution: {integrity: sha512-x6lm0UrM03jjDXTPZgD9Ad8bIVD1ifWNit2EaWQIZB5CULr46+FbLQ5RpK7AXtDHGjx9rmvC7QRCTjsiGkAwRw==}
'@vue/compiler-dom@3.4.37':
resolution: {integrity: sha512-rIiSmL3YrntvgYV84rekAtU/xfogMUJIclUMeIKEtVBFngOL3IeZHhsH3UaFEgB5iFGpj6IW+8YuM/2Up+vVag==}
'@vue/compiler-ssr@3.4.34':
resolution: {integrity: sha512-8TDBcLaTrFm5rnF+Qm4BlliaopJgqJ28Nsrc80qazynm5aJO+Emu7y0RWw34L8dNnTRdcVBpWzJxhGYzsoVu4g==}
'@vue/compiler-sfc@3.4.37':
resolution: {integrity: sha512-vCfetdas40Wk9aK/WWf8XcVESffsbNkBQwS5t13Y/PcfqKfIwJX2gF+82th6dOpnpbptNMlMjAny80li7TaCIg==}
'@vue/compiler-ssr@3.4.37':
resolution: {integrity: sha512-TyAgYBWrHlFrt4qpdACh8e9Ms6C/AZQ6A6xLJaWrCL8GCX5DxMzxyeFAEMfU/VFr4tylHm+a2NpfJpcd7+20XA==}
'@vue/compiler-vue2@2.7.16':
resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
@ -5449,22 +5420,19 @@ packages:
typescript:
optional: true
'@vue/reactivity@3.4.34':
resolution: {integrity: sha512-ua+Lo+wBRlBEX9TtgPOShE2JwIO7p6BTZ7t1KZVPoaBRfqbC7N3c8Mpzicx173fXxx5VXeU6ykiHo7WgLzJQDA==}
'@vue/reactivity@3.4.37':
resolution: {integrity: sha512-UmdKXGx0BZ5kkxPqQr3PK3tElz6adTey4307NzZ3whZu19i5VavYal7u2FfOmAzlcDVgE8+X0HZ2LxLb/jgbYw==}
'@vue/runtime-core@3.4.34':
resolution: {integrity: sha512-PXhkiRPwcPGJ1BnyBZFI96GfInCVskd0HPNIAZn7i3YOmLbtbTZpB7/kDTwC1W7IqdGPkTVC63IS7J2nZs4Ebg==}
'@vue/runtime-core@3.4.37':
resolution: {integrity: sha512-MNjrVoLV/sirHZoD7QAilU1Ifs7m/KJv4/84QVbE6nyAZGQNVOa1HGxaOzp9YqCG+GpLt1hNDC4RbH+KtanV7w==}
'@vue/runtime-dom@3.4.34':
resolution: {integrity: sha512-dXqIe+RqFAK2Euak4UsvbIupalrhc67OuQKpD7HJ3W2fv8jlqvI7szfBCsAEcE8o/wyNpkloxB6J8viuF/E3gw==}
'@vue/runtime-dom@3.4.37':
resolution: {integrity: sha512-Mg2EwgGZqtwKrqdL/FKMF2NEaOHuH+Ks9TQn3DHKyX//hQTYOun+7Tqp1eo0P4Ds+SjltZshOSRq6VsU0baaNg==}
'@vue/server-renderer@3.4.34':
resolution: {integrity: sha512-GeyEUfMVRZMD/mZcNONEqg7MiU10QQ1DB3O/Qr6+8uXpbwdlmVgQ5Qs1/ZUAFX1X2UUtqMoGrDRbxdWfOJFT7Q==}
'@vue/server-renderer@3.4.37':
resolution: {integrity: sha512-jZ5FAHDR2KBq2FsRUJW6GKDOAG9lUTX8aBEGq4Vf6B/35I9fPce66BornuwmqmKgfiSlecwuOb6oeoamYMohkg==}
peerDependencies:
vue: 3.4.34
'@vue/shared@3.4.29':
resolution: {integrity: sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA==}
vue: 3.4.37
'@vue/shared@3.4.31':
resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==}
@ -5472,6 +5440,9 @@ packages:
'@vue/shared@3.4.34':
resolution: {integrity: sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==}
'@vue/shared@3.4.37':
resolution: {integrity: sha512-nIh8P2fc3DflG8+5Uw8PT/1i17ccFn0xxN/5oE9RfV5SVnd7G0XEFRwakrnNFE/jlS95fpGXDVG5zDETS26nmg==}
'@vue/test-utils@2.4.1':
resolution: {integrity: sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==}
peerDependencies:
@ -6828,6 +6799,10 @@ packages:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
entities@5.0.0:
resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==}
engines: {node: '>=0.12'}
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
@ -10687,10 +10662,6 @@ packages:
sortablejs@1.14.0:
resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
source-map-js@1.2.0:
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
engines: {node: '>=0.10.0'}
@ -11667,8 +11638,8 @@ packages:
peerDependencies:
typescript: '>=5.0.0'
vue@3.4.34:
resolution: {integrity: sha512-VZze05HWlA3ItreQ/ka7Sx7PoD0/3St8FEiSlSTVgb6l4hL+RjtP2/8g5WQBzZgyf8WG2f+g1bXzC7zggLhAJA==}
vue@3.4.37:
resolution: {integrity: sha512-3vXvNfkKTBsSJ7JP+LyR7GBuwQuckbWvuwAid3xbqK9ppsKt/DUvfqgZ48fgOLEfpy1IacL5f8QhUVl77RaI7A==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
@ -12478,10 +12449,10 @@ snapshots:
'@babel/helper-compilation-targets': 7.22.15
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
'@babel/helpers': 7.23.5
'@babel/parser': 7.23.9
'@babel/parser': 7.24.7
'@babel/template': 7.22.15
'@babel/traverse': 7.23.5
'@babel/types': 7.23.5
'@babel/types': 7.24.7
convert-source-map: 2.0.0
debug: 4.3.5(supports-color@8.1.1)
gensync: 1.0.0-beta.2
@ -12512,7 +12483,7 @@ snapshots:
'@babel/generator@7.23.5':
dependencies:
'@babel/types': 7.23.5
'@babel/types': 7.24.7
'@jridgewell/gen-mapping': 0.3.2
'@jridgewell/trace-mapping': 0.3.18
jsesc: 2.5.2
@ -12617,7 +12588,7 @@ snapshots:
'@babel/helper-module-imports@7.22.15':
dependencies:
'@babel/types': 7.23.5
'@babel/types': 7.24.7
'@babel/helper-module-imports@7.24.7':
dependencies:
@ -12633,7 +12604,7 @@ snapshots:
'@babel/helper-module-imports': 7.22.15
'@babel/helper-simple-access': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/helper-validator-identifier': 7.22.20
'@babel/helper-validator-identifier': 7.24.7
'@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)':
dependencies:
@ -12674,7 +12645,7 @@ snapshots:
'@babel/helper-simple-access@7.22.5':
dependencies:
'@babel/types': 7.23.5
'@babel/types': 7.24.7
'@babel/helper-simple-access@7.24.7':
dependencies:
@ -12692,18 +12663,14 @@ snapshots:
'@babel/helper-split-export-declaration@7.22.6':
dependencies:
'@babel/types': 7.23.5
'@babel/types': 7.24.7
'@babel/helper-split-export-declaration@7.24.7':
dependencies:
'@babel/types': 7.24.7
'@babel/helper-string-parser@7.23.4': {}
'@babel/helper-string-parser@7.24.7': {}
'@babel/helper-validator-identifier@7.22.20': {}
'@babel/helper-validator-identifier@7.24.7': {}
'@babel/helper-validator-option@7.23.5': {}
@ -12723,7 +12690,7 @@ snapshots:
dependencies:
'@babel/template': 7.22.15
'@babel/traverse': 7.23.5
'@babel/types': 7.23.5
'@babel/types': 7.24.7
transitivePeerDependencies:
- supports-color
@ -12734,7 +12701,7 @@ snapshots:
'@babel/highlight@7.23.4':
dependencies:
'@babel/helper-validator-identifier': 7.22.20
'@babel/helper-validator-identifier': 7.24.7
chalk: 2.4.2
js-tokens: 4.0.0
@ -12745,14 +12712,6 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.0.0
'@babel/parser@7.23.9':
dependencies:
'@babel/types': 7.23.5
'@babel/parser@7.24.5':
dependencies:
'@babel/types': 7.24.0
'@babel/parser@7.24.7':
dependencies:
'@babel/types': 7.24.7
@ -13432,8 +13391,8 @@ snapshots:
'@babel/template@7.22.15':
dependencies:
'@babel/code-frame': 7.23.5
'@babel/parser': 7.23.9
'@babel/types': 7.23.5
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
'@babel/template@7.24.0':
dependencies:
@ -13455,8 +13414,8 @@ snapshots:
'@babel/helper-function-name': 7.23.0
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.23.9
'@babel/types': 7.23.5
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
debug: 4.3.5(supports-color@8.1.1)
globals: 11.12.0
transitivePeerDependencies:
@ -13477,18 +13436,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@babel/types@7.23.5':
dependencies:
'@babel/helper-string-parser': 7.23.4
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
'@babel/types@7.24.0':
dependencies:
'@babel/helper-string-parser': 7.23.4
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
'@babel/types@7.24.7':
dependencies:
'@babel/helper-string-parser': 7.24.7
@ -16242,18 +16189,18 @@ snapshots:
dependencies:
storybook: 8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4)
'@storybook/vue3-vite@8.1.11(bufferutil@4.0.8)(encoding@0.1.13)(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.4)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))':
'@storybook/vue3-vite@8.1.11(bufferutil@4.0.8)(encoding@0.1.13)(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.4)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
dependencies:
'@storybook/builder-vite': 8.1.11(encoding@0.1.13)(prettier@3.3.3)(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))
'@storybook/core-server': 8.1.11(bufferutil@4.0.8)(encoding@0.1.13)(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.4)
'@storybook/types': 8.1.11
'@storybook/vue3': 8.1.11(encoding@0.1.13)(prettier@3.3.3)(vue@3.4.34(typescript@5.5.4))
'@storybook/vue3': 8.1.11(encoding@0.1.13)(prettier@3.3.3)(vue@3.4.37(typescript@5.5.4))
find-package-json: 1.2.0
magic-string: 0.30.10
typescript: 5.5.4
vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)
vue-component-meta: 2.0.16(typescript@5.5.4)
vue-docgen-api: 4.75.1(vue@3.4.34(typescript@5.5.4))
vue-docgen-api: 4.75.1(vue@3.4.37(typescript@5.5.4))
transitivePeerDependencies:
- '@preact/preset-vite'
- bufferutil
@ -16266,24 +16213,24 @@ snapshots:
- vite-plugin-glimmerx
- vue
'@storybook/vue3@8.1.11(encoding@0.1.13)(prettier@3.3.3)(vue@3.4.34(typescript@5.5.4))':
'@storybook/vue3@8.1.11(encoding@0.1.13)(prettier@3.3.3)(vue@3.4.37(typescript@5.5.4))':
dependencies:
'@storybook/docs-tools': 8.1.11(encoding@0.1.13)(prettier@3.3.3)
'@storybook/global': 5.0.0
'@storybook/preview-api': 8.1.11
'@storybook/types': 8.1.11
'@vue/compiler-core': 3.4.29
'@vue/compiler-core': 3.4.34
lodash: 4.17.21
ts-dedent: 2.2.0
type-fest: 2.19.0
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-component-type-helpers: 2.0.29
transitivePeerDependencies:
- encoding
- prettier
- supports-color
'@storybook/vue3@8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.4.34(typescript@5.5.4))':
'@storybook/vue3@8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.4.37(typescript@5.5.4))':
dependencies:
'@storybook/components': 8.2.6(storybook@8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4))
'@storybook/global': 5.0.0
@ -16295,7 +16242,7 @@ snapshots:
storybook: 8.2.6(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.8)(utf-8-validate@6.0.4)
ts-dedent: 2.2.0
type-fest: 2.19.0
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-component-type-helpers: 2.0.29
'@swc/cli@0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)':
@ -16609,14 +16556,14 @@ snapshots:
dependencies:
'@testing-library/dom': 10.1.0
'@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.34)(@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4)))(vue@3.4.34(typescript@5.5.4))':
'@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.37)(@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4)))(vue@3.4.37(typescript@5.5.4))':
dependencies:
'@babel/runtime': 7.23.4
'@testing-library/dom': 9.3.4
'@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4)))(vue@3.4.34(typescript@5.5.4))
vue: 3.4.34(typescript@5.5.4)
'@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4)))(vue@3.4.37(typescript@5.5.4))
vue: 3.4.37(typescript@5.5.4)
optionalDependencies:
'@vue/compiler-sfc': 3.4.34
'@vue/compiler-sfc': 3.4.37
transitivePeerDependencies:
- '@vue/server-renderer'
@ -17282,10 +17229,10 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-vue@5.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))':
'@vitejs/plugin-vue@5.1.0(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
dependencies:
vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
'@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.77.8)(terser@5.31.3))':
dependencies:
@ -17360,14 +17307,6 @@ snapshots:
path-browserify: 1.0.1
vscode-uri: 3.0.8
'@vue/compiler-core@3.4.29':
dependencies:
'@babel/parser': 7.24.7
'@vue/shared': 3.4.29
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.0
'@vue/compiler-core@3.4.31':
dependencies:
'@babel/parser': 7.24.7
@ -17384,37 +17323,40 @@ snapshots:
estree-walker: 2.0.2
source-map-js: 1.2.0
'@vue/compiler-dom@3.4.29':
'@vue/compiler-core@3.4.37':
dependencies:
'@vue/compiler-core': 3.4.29
'@vue/shared': 3.4.29
'@vue/compiler-dom@3.4.31':
dependencies:
'@vue/compiler-core': 3.4.31
'@vue/shared': 3.4.31
'@babel/parser': 7.24.7
'@vue/shared': 3.4.37
entities: 5.0.0
estree-walker: 2.0.2
source-map-js: 1.2.0
'@vue/compiler-dom@3.4.34':
dependencies:
'@vue/compiler-core': 3.4.34
'@vue/shared': 3.4.34
'@vue/compiler-sfc@3.4.34':
'@vue/compiler-dom@3.4.37':
dependencies:
'@vue/compiler-core': 3.4.37
'@vue/shared': 3.4.37
'@vue/compiler-sfc@3.4.37':
dependencies:
'@babel/parser': 7.24.7
'@vue/compiler-core': 3.4.34
'@vue/compiler-dom': 3.4.34
'@vue/compiler-ssr': 3.4.34
'@vue/shared': 3.4.34
'@vue/compiler-core': 3.4.37
'@vue/compiler-dom': 3.4.37
'@vue/compiler-ssr': 3.4.37
'@vue/shared': 3.4.37
estree-walker: 2.0.2
magic-string: 0.30.10
postcss: 8.4.40
source-map-js: 1.2.0
'@vue/compiler-ssr@3.4.34':
'@vue/compiler-ssr@3.4.37':
dependencies:
'@vue/compiler-dom': 3.4.34
'@vue/shared': 3.4.34
'@vue/compiler-dom': 3.4.37
'@vue/shared': 3.4.37
'@vue/compiler-vue2@2.7.16':
dependencies:
@ -17426,8 +17368,8 @@ snapshots:
'@vue/language-core@2.0.16(typescript@5.5.4)':
dependencies:
'@volar/language-core': 2.2.0
'@vue/compiler-dom': 3.4.31
'@vue/shared': 3.4.31
'@vue/compiler-dom': 3.4.34
'@vue/shared': 3.4.34
computeds: 0.0.1
minimatch: 9.0.4
path-browserify: 1.0.1
@ -17438,9 +17380,9 @@ snapshots:
'@vue/language-core@2.0.29(typescript@5.5.4)':
dependencies:
'@volar/language-core': 2.4.0-alpha.18
'@vue/compiler-dom': 3.4.31
'@vue/compiler-dom': 3.4.34
'@vue/compiler-vue2': 2.7.16
'@vue/shared': 3.4.31
'@vue/shared': 3.4.34
computeds: 0.0.1
minimatch: 9.0.4
muggle-string: 0.4.1
@ -17448,41 +17390,41 @@ snapshots:
optionalDependencies:
typescript: 5.5.4
'@vue/reactivity@3.4.34':
'@vue/reactivity@3.4.37':
dependencies:
'@vue/shared': 3.4.34
'@vue/shared': 3.4.37
'@vue/runtime-core@3.4.34':
'@vue/runtime-core@3.4.37':
dependencies:
'@vue/reactivity': 3.4.34
'@vue/shared': 3.4.34
'@vue/reactivity': 3.4.37
'@vue/shared': 3.4.37
'@vue/runtime-dom@3.4.34':
'@vue/runtime-dom@3.4.37':
dependencies:
'@vue/reactivity': 3.4.34
'@vue/runtime-core': 3.4.34
'@vue/shared': 3.4.34
'@vue/reactivity': 3.4.37
'@vue/runtime-core': 3.4.37
'@vue/shared': 3.4.37
csstype: 3.1.3
'@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4))':
'@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4))':
dependencies:
'@vue/compiler-ssr': 3.4.34
'@vue/shared': 3.4.34
vue: 3.4.34(typescript@5.5.4)
'@vue/shared@3.4.29': {}
'@vue/compiler-ssr': 3.4.37
'@vue/shared': 3.4.37
vue: 3.4.37(typescript@5.5.4)
'@vue/shared@3.4.31': {}
'@vue/shared@3.4.34': {}
'@vue/test-utils@2.4.1(@vue/server-renderer@3.4.34(vue@3.4.34(typescript@5.5.4)))(vue@3.4.34(typescript@5.5.4))':
'@vue/shared@3.4.37': {}
'@vue/test-utils@2.4.1(@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4)))(vue@3.4.37(typescript@5.5.4))':
dependencies:
js-beautify: 1.14.9
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-component-type-helpers: 1.8.4
optionalDependencies:
'@vue/server-renderer': 3.4.34(vue@3.4.34(typescript@5.5.4))
'@vue/server-renderer': 3.4.37(vue@3.4.37(typescript@5.5.4))
'@webgpu/types@0.1.30': {}
@ -17930,7 +17872,7 @@ snapshots:
babel-walk@3.0.0-canary-5:
dependencies:
'@babel/types': 7.24.0
'@babel/types': 7.24.7
bail@2.0.2: {}
@ -18481,8 +18423,8 @@ snapshots:
constantinople@4.0.1:
dependencies:
'@babel/parser': 7.24.5
'@babel/types': 7.24.0
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
content-disposition@0.5.4:
dependencies:
@ -18593,12 +18535,12 @@ snapshots:
css-tree@2.2.1:
dependencies:
mdn-data: 2.0.28
source-map-js: 1.0.2
source-map-js: 1.2.0
css-tree@2.3.1:
dependencies:
mdn-data: 2.0.30
source-map-js: 1.0.2
source-map-js: 1.2.0
css-what@6.1.0: {}
@ -18982,6 +18924,8 @@ snapshots:
entities@4.5.0: {}
entities@5.0.0: {}
env-paths@2.2.1: {}
envinfo@7.8.1: {}
@ -20925,7 +20869,7 @@ snapshots:
'@babel/generator': 7.23.5
'@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5)
'@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.5)
'@babel/types': 7.23.5
'@babel/types': 7.24.7
'@jest/expect-utils': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
@ -21374,8 +21318,8 @@ snapshots:
magicast@0.3.4:
dependencies:
'@babel/parser': 7.24.5
'@babel/types': 7.24.0
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
source-map-js: 1.2.0
mailcheck@1.1.1: {}
@ -23724,8 +23668,6 @@ snapshots:
sortablejs@1.14.0: {}
source-map-js@1.0.2: {}
source-map-js@1.2.0: {}
source-map-support@0.5.13:
@ -24496,14 +24438,14 @@ snapshots:
uuid@9.0.1: {}
v-code-diff@1.12.0(vue@3.4.34(typescript@5.5.4)):
v-code-diff@1.12.0(vue@3.4.37(typescript@5.5.4)):
dependencies:
diff: 5.1.0
diff-match-patch: 1.0.5
highlight.js: 11.9.0
vue: 3.4.34(typescript@5.5.4)
vue-demi: 0.14.7(vue@3.4.34(typescript@5.5.4))
vue-i18n: 9.13.1(vue@3.4.34(typescript@5.5.4))
vue: 3.4.37(typescript@5.5.4)
vue-demi: 0.14.7(vue@3.4.37(typescript@5.5.4))
vue-i18n: 9.13.1(vue@3.4.37(typescript@5.5.4))
v8-to-istanbul@9.2.0:
dependencies:
@ -24647,24 +24589,24 @@ snapshots:
vue-component-type-helpers@2.0.29: {}
vue-demi@0.14.7(vue@3.4.34(typescript@5.5.4)):
vue-demi@0.14.7(vue@3.4.37(typescript@5.5.4)):
dependencies:
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-docgen-api@4.75.1(vue@3.4.34(typescript@5.5.4)):
vue-docgen-api@4.75.1(vue@3.4.37(typescript@5.5.4)):
dependencies:
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
'@vue/compiler-dom': 3.4.29
'@vue/compiler-sfc': 3.4.34
'@vue/compiler-dom': 3.4.34
'@vue/compiler-sfc': 3.4.37
ast-types: 0.16.1
hash-sum: 2.0.0
lru-cache: 8.0.4
pug: 3.0.3
recast: 0.23.6
ts-map: 1.0.3
vue: 3.4.34(typescript@5.5.4)
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.34(typescript@5.5.4))
vue: 3.4.37(typescript@5.5.4)
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.37(typescript@5.5.4))
vue-eslint-parser@9.4.3(eslint@9.8.0):
dependencies:
@ -24679,16 +24621,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
vue-i18n@9.13.1(vue@3.4.34(typescript@5.5.4)):
vue-i18n@9.13.1(vue@3.4.37(typescript@5.5.4)):
dependencies:
'@intlify/core-base': 9.13.1
'@intlify/shared': 9.13.1
'@vue/devtools-api': 6.6.1
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.34(typescript@5.5.4)):
vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.37(typescript@5.5.4)):
dependencies:
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
vue-template-compiler@2.7.14:
dependencies:
@ -24702,20 +24644,20 @@ snapshots:
semver: 7.6.0
typescript: 5.5.4
vue@3.4.34(typescript@5.5.4):
vue@3.4.37(typescript@5.5.4):
dependencies:
'@vue/compiler-dom': 3.4.34
'@vue/compiler-sfc': 3.4.34
'@vue/runtime-dom': 3.4.34
'@vue/server-renderer': 3.4.34(vue@3.4.34(typescript@5.5.4))
'@vue/shared': 3.4.34
'@vue/compiler-dom': 3.4.37
'@vue/compiler-sfc': 3.4.37
'@vue/runtime-dom': 3.4.37
'@vue/server-renderer': 3.4.37(vue@3.4.37(typescript@5.5.4))
'@vue/shared': 3.4.37
optionalDependencies:
typescript: 5.5.4
vuedraggable@4.1.0(vue@3.4.34(typescript@5.5.4)):
vuedraggable@4.1.0(vue@3.4.37(typescript@5.5.4)):
dependencies:
sortablejs: 1.14.0
vue: 3.4.34(typescript@5.5.4)
vue: 3.4.37(typescript@5.5.4)
w3c-xmlserializer@5.0.0:
dependencies:
@ -24840,8 +24782,8 @@ snapshots:
with@7.0.2:
dependencies:
'@babel/parser': 7.24.5
'@babel/types': 7.24.0
'@babel/parser': 7.24.7
'@babel/types': 7.24.7
assert-never: 1.2.1
babel-walk: 3.0.0-canary-5