summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/PULL_REQUEST_TEMPLATE/01_bug.md (renamed from .github/PULL_REQUEST_TEMPLATE.md)0
-rw-r--r--.github/PULL_REQUEST_TEMPLATE/02_enhance.md17
-rw-r--r--.github/PULL_REQUEST_TEMPLATE/03_release.md10
-rw-r--r--.github/workflows/lint.yml30
-rw-r--r--.github/workflows/pr-preview-destroy.yml34
-rw-r--r--.vscode/settings.json3
-rw-r--r--CHANGELOG.md79
-rw-r--r--CONTRIBUTING.md16
-rw-r--r--ROADMAP.md4
-rw-r--r--codecov.yml6
-rw-r--r--locales/ar-SA.yml27
-rw-r--r--locales/bn-BD.yml27
-rw-r--r--locales/ca-ES.yml5
-rw-r--r--locales/cs-CZ.yml18
-rw-r--r--locales/de-DE.yml41
-rw-r--r--locales/el-GR.yml10
-rw-r--r--locales/en-US.yml40
-rw-r--r--locales/es-ES.yml29
-rw-r--r--locales/fr-FR.yml29
-rw-r--r--locales/id-ID.yml247
-rw-r--r--locales/it-IT.yml203
-rw-r--r--locales/ja-JP.yml56
-rw-r--r--locales/ja-KS.yml235
-rw-r--r--locales/kab-KAB.yml2
-rw-r--r--locales/ko-KR.yml39
-rw-r--r--locales/lo-LA.yml28
-rw-r--r--locales/nl-NL.yml7
-rw-r--r--locales/pl-PL.yml26
-rw-r--r--locales/pt-PT.yml11
-rw-r--r--locales/ro-RO.yml17
-rw-r--r--locales/ru-RU.yml77
-rw-r--r--locales/sk-SK.yml29
-rw-r--r--locales/sv-SE.yml3
-rw-r--r--locales/th-TH.yml45
-rw-r--r--locales/uk-UA.yml29
-rw-r--r--locales/vi-VN.yml28
-rw-r--r--locales/zh-CN.yml37
-rw-r--r--locales/zh-TW.yml48
-rw-r--r--package.json15
-rw-r--r--packages/backend/.swcrc32
-rw-r--r--packages/backend/assets/apple-touch-icon.pngbin9828 -> 49532 bytes
-rw-r--r--packages/backend/assets/icons/192.pngbin7629 -> 26568 bytes
-rw-r--r--packages/backend/assets/icons/512.pngbin20527 -> 165827 bytes
-rw-r--r--packages/backend/check_connect.js10
-rw-r--r--packages/backend/migration/1676434944993-drop-group.js8
-rw-r--r--packages/backend/migration/1676438468213-ad3.js2
-rw-r--r--packages/backend/package.json76
-rw-r--r--packages/backend/src/@types/redis-lock.d.ts8
-rw-r--r--packages/backend/src/core/AppLockService.ts2
-rw-r--r--packages/backend/src/core/MfmService.ts14
-rw-r--r--packages/backend/src/core/PushNotificationService.ts8
-rw-r--r--packages/backend/src/core/activitypub/ApInboxService.ts8
-rw-r--r--packages/backend/src/core/activitypub/ApRequestService.ts72
-rw-r--r--packages/backend/src/core/activitypub/type.ts4
-rw-r--r--packages/backend/src/core/entities/NotificationEntityService.ts7
-rw-r--r--packages/backend/src/core/entities/RoleEntityService.ts15
-rw-r--r--packages/backend/src/models/entities/Notification.ts8
-rw-r--r--packages/backend/src/models/entities/UserProfile.ts4
-rw-r--r--packages/backend/src/server/api/ApiCallService.ts4
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts20
-rw-r--r--packages/backend/src/server/api/GetterService.ts4
-rw-r--r--packages/backend/src/server/api/SigninApiService.ts18
-rw-r--r--packages/backend/src/server/api/endpoint-base.ts4
-rw-r--r--packages/backend/src/server/api/endpoints.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive/show-file.ts16
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/list.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/show.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/users.ts71
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-user.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/done.ts28
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/key-done.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/password-less.ts47
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/register.ts17
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts18
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/unregister.ts12
-rw-r--r--packages/backend/src/server/api/endpoints/i/2fa/update-key.ts78
-rw-r--r--packages/backend/src/server/api/endpoints/i/notifications.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/notes/create.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/notes/featured.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/roles/list.ts37
-rw-r--r--packages/backend/src/server/api/endpoints/roles/show.ts52
-rw-r--r--packages/backend/src/server/api/endpoints/roles/users.ts71
-rw-r--r--packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts111
-rw-r--r--packages/backend/src/server/web/manifest.json14
-rw-r--r--packages/backend/src/types.ts3
-rw-r--r--packages/backend/test/tests/mfm.ts89
-rw-r--r--packages/backend/test/tests/reaction-lib.ts83
-rw-r--r--packages/backend/test/tsconfig.json3
-rw-r--r--packages/backend/test/unit/MfmService.ts102
-rw-r--r--packages/backend/test/unit/ReactionService.ts92
-rw-r--r--packages/backend/test/unit/ap-request.ts (renamed from packages/backend/test/tests/ap-request.ts)11
-rw-r--r--packages/backend/test/unit/chart.ts2
-rw-r--r--packages/backend/test/unit/extract-mentions.ts (renamed from packages/backend/test/tests/extract-mentions.ts)6
-rw-r--r--packages/backend/tsconfig.json2
-rw-r--r--packages/frontend/.eslintrc.js1
-rw-r--r--packages/frontend/assets/about-icon.pngbin20528 -> 26568 bytes
-rw-r--r--packages/frontend/package.json35
-rw-r--r--packages/frontend/src/components/MkAbuseReportWindow.vue2
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue2
-rw-r--r--packages/frontend/src/components/MkCaptcha.vue2
-rw-r--r--packages/frontend/src/components/MkClickerGame.vue3
-rw-r--r--packages/frontend/src/components/MkContextMenu.vue10
-rw-r--r--packages/frontend/src/components/MkCwButton.vue3
-rw-r--r--packages/frontend/src/components/MkDialog.vue39
-rw-r--r--packages/frontend/src/components/MkFolder.vue35
-rw-r--r--packages/frontend/src/components/MkInput.vue6
-rw-r--r--packages/frontend/src/components/MkMediaList.vue8
-rw-r--r--packages/frontend/src/components/MkMenu.child.vue35
-rw-r--r--packages/frontend/src/components/MkMenu.vue28
-rw-r--r--packages/frontend/src/components/MkModal.vue23
-rw-r--r--packages/frontend/src/components/MkNote.vue55
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue8
-rw-r--r--packages/frontend/src/components/MkNoteHeader.vue2
-rw-r--r--packages/frontend/src/components/MkNotificationSettingWindow.vue30
-rw-r--r--packages/frontend/src/components/MkNotifications.vue2
-rw-r--r--packages/frontend/src/components/MkPageWindow.vue11
-rw-r--r--packages/frontend/src/components/MkPagination.vue39
-rw-r--r--packages/frontend/src/components/MkPostForm.vue16
-rw-r--r--packages/frontend/src/components/MkRolePreview.vue19
-rw-r--r--packages/frontend/src/components/MkSelect.vue4
-rw-r--r--packages/frontend/src/components/MkSignin.vue6
-rw-r--r--packages/frontend/src/components/MkTimeline.vue6
-rw-r--r--packages/frontend/src/components/MkUrlPreview.vue29
-rw-r--r--packages/frontend/src/components/MkUserList.vue11
-rw-r--r--packages/frontend/src/components/MkUserSelectDialog.vue5
-rw-r--r--packages/frontend/src/components/MkVisibilityPicker.vue4
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue6
-rw-r--r--packages/frontend/src/components/global/MkPageHeader.tabs.vue50
-rw-r--r--packages/frontend/src/components/global/MkPageHeader.vue13
-rw-r--r--packages/frontend/src/components/global/MkTime.vue25
-rw-r--r--packages/frontend/src/components/mfm.ts2
-rw-r--r--packages/frontend/src/const.ts3
-rw-r--r--packages/frontend/src/init.ts6
-rw-r--r--packages/frontend/src/navbar.ts3
-rw-r--r--packages/frontend/src/os.ts14
-rw-r--r--packages/frontend/src/pages/about-misskey.vue10
-rw-r--r--packages/frontend/src/pages/admin/_header_.vue2
-rw-r--r--packages/frontend/src/pages/admin/ads.vue19
-rw-r--r--packages/frontend/src/pages/admin/roles.role.vue37
-rw-r--r--packages/frontend/src/pages/admin/roles.vue2
-rw-r--r--packages/frontend/src/pages/antenna-timeline.vue6
-rw-r--r--packages/frontend/src/pages/auth.vue15
-rw-r--r--packages/frontend/src/pages/channel.vue40
-rw-r--r--packages/frontend/src/pages/clip.vue4
-rw-r--r--packages/frontend/src/pages/explore.featured.vue6
-rw-r--r--packages/frontend/src/pages/explore.roles.vue22
-rw-r--r--packages/frontend/src/pages/explore.users.vue22
-rw-r--r--packages/frontend/src/pages/explore.vue38
-rw-r--r--packages/frontend/src/pages/note.vue6
-rw-r--r--packages/frontend/src/pages/notifications.vue8
-rw-r--r--packages/frontend/src/pages/role.vue47
-rw-r--r--packages/frontend/src/pages/search.vue130
-rw-r--r--packages/frontend/src/pages/settings/2fa.qrdialog.vue82
-rw-r--r--packages/frontend/src/pages/settings/2fa.vue366
-rw-r--r--packages/frontend/src/pages/settings/index.vue2
-rw-r--r--packages/frontend/src/pages/settings/notifications.vue2
-rw-r--r--packages/frontend/src/pages/settings/plugin.vue38
-rw-r--r--packages/frontend/src/pages/settings/privacy.vue2
-rw-r--r--packages/frontend/src/pages/settings/profile.vue10
-rw-r--r--packages/frontend/src/pages/settings/security.vue12
-rw-r--r--packages/frontend/src/pages/tag.vue4
-rw-r--r--packages/frontend/src/pages/timeline.vue6
-rw-r--r--packages/frontend/src/pages/user-info.vue2
-rw-r--r--packages/frontend/src/pages/user-list-timeline.vue6
-rw-r--r--packages/frontend/src/pages/user-tag.vue38
-rw-r--r--packages/frontend/src/pages/user/home.vue4
-rw-r--r--packages/frontend/src/pages/user/index.timeline.vue4
-rw-r--r--packages/frontend/src/pages/welcome.entrance.a.vue251
-rw-r--r--packages/frontend/src/pizzax.ts30
-rw-r--r--packages/frontend/src/router.ts9
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts138
-rw-r--r--packages/frontend/src/scripts/get-user-menu.ts13
-rw-r--r--packages/frontend/src/scripts/get-user-name.ts2
-rw-r--r--packages/frontend/src/scripts/hpml/index.ts2
-rw-r--r--packages/frontend/src/scripts/hpml/type-checker.ts4
-rw-r--r--packages/frontend/src/scripts/scroll.ts16
-rw-r--r--packages/frontend/src/scripts/search.ts63
-rw-r--r--packages/frontend/src/scripts/use-document-visibility.ts19
-rw-r--r--packages/frontend/src/theme-store.ts6
-rw-r--r--packages/frontend/src/ui/classic.header.vue4
-rw-r--r--packages/frontend/src/ui/classic.sidebar.vue4
-rw-r--r--packages/frontend/src/ui/classic.vue2
-rw-r--r--packages/frontend/src/ui/deck.vue9
-rw-r--r--packages/frontend/src/ui/deck/antenna-column.vue6
-rw-r--r--packages/frontend/src/ui/deck/channel-column.vue6
-rw-r--r--packages/frontend/src/ui/deck/direct-column.vue4
-rw-r--r--packages/frontend/src/ui/deck/list-column.vue6
-rw-r--r--packages/frontend/src/ui/deck/mentions-column.vue4
-rw-r--r--packages/frontend/src/ui/deck/tl-column.vue4
-rw-r--r--packages/frontend/src/ui/visitor/a.vue5
-rw-r--r--packages/frontend/src/ui/visitor/b.vue10
-rw-r--r--packages/frontend/src/ui/visitor/header.vue6
-rw-r--r--packages/frontend/src/widgets/WidgetOnlineUsers.vue3
-rw-r--r--packages/frontend/src/widgets/WidgetTimeline.vue4
-rw-r--r--packages/shared/.eslintrc.js11
-rw-r--r--packages/sw/package.json4
-rw-r--r--packages/sw/src/scripts/get-user-name.ts6
-rw-r--r--pnpm-lock.yaml1602
198 files changed, 4061 insertions, 2745 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE/01_bug.md
index 79ca97dfa0..79ca97dfa0 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE/01_bug.md
diff --git a/.github/PULL_REQUEST_TEMPLATE/02_enhance.md b/.github/PULL_REQUEST_TEMPLATE/02_enhance.md
new file mode 100644
index 0000000000..79ca97dfa0
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/02_enhance.md
@@ -0,0 +1,17 @@
+<!-- ℹ ãŠèª­ã¿ãã ã•ã„ / README
+PRã‚りãŒã¨ã†ã”ã–ã„ã¾ã™ï¼ PRを作æˆã™ã‚‹å‰ã«ã€ã‚³ãƒ³ãƒˆãƒªãƒ“ューションガイドをã”確èªãã ã•ã„:
+Thank you for your PR! Before creating a PR, please check the contribution guide:
+https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
+-->
+
+# What
+<!-- ã“ã®PRã§ä½•ã‚’ã—ãŸã®ã‹ï¼Ÿ ã©ã†å¤‰ã‚ã‚‹ã®ã‹ï¼Ÿ -->
+<!-- What did you do with this PR? How will it change things? -->
+
+# Why
+<!-- ãªãœãã†ã™ã‚‹ã®ã‹ï¼Ÿ ã©ã†ã„ã†æ„図ãªã®ã‹ï¼Ÿ 何ãŒå›°ã£ã¦ã„ã‚‹ã®ã‹ï¼Ÿ -->
+<!-- Why do you do it? What are your intentions? What is the problem? -->
+
+# Additional info (optional)
+<!-- テスト観点ãªã© -->
+<!-- Test perspective, etc -->
diff --git a/.github/PULL_REQUEST_TEMPLATE/03_release.md b/.github/PULL_REQUEST_TEMPLATE/03_release.md
new file mode 100644
index 0000000000..0c71ea804d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/03_release.md
@@ -0,0 +1,10 @@
+# Summary
+This is a release PR.
+
+For more information on the release instructions, please see:
+https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md#release
+
+# Checklist
+- [ ] package.jsonã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒæ­£ã—ãæ›´æ–°ã•れã¦ã„ã‚‹
+- [ ] CHANGELOGãŒéŽä¸è¶³ç„¡ãæ›´æ–°ã•れã¦ã„ã‚‹
+- [ ] CIãŒå…¨ã¦é€šã£ã¦ã„ã‚‹
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 94d7d1371c..d65076ebb2 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -36,9 +36,6 @@ jobs:
- backend
- frontend
- sw
- lint:
- - typecheck
- - eslint
steps:
- uses: actions/checkout@v3.3.0
with:
@@ -54,4 +51,29 @@ jobs:
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- - run: pnpm --filter ${{ matrix.workspace }} run ${{ matrix.lint }}
+ - run: pnpm --filter ${{ matrix.workspace }} run eslint
+
+ typecheck:
+ needs: [pnpm_install]
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ strategy:
+ matrix:
+ workspace:
+ - backend
+ steps:
+ - uses: actions/checkout@v3.3.0
+ with:
+ fetch-depth: 0
+ submodules: true
+ - uses: pnpm/action-setup@v2
+ with:
+ version: 7
+ run_install: false
+ - uses: actions/setup-node@v3.6.0
+ with:
+ node-version: 18.x
+ cache: 'pnpm'
+ - run: corepack enable
+ - run: pnpm i --frozen-lockfile
+ - run: pnpm --filter ${{ matrix.workspace }} run typecheck
diff --git a/.github/workflows/pr-preview-destroy.yml b/.github/workflows/pr-preview-destroy.yml
index 49f1ba8a34..8adfad9dab 100644
--- a/.github/workflows/pr-preview-destroy.yml
+++ b/.github/workflows/pr-preview-destroy.yml
@@ -9,14 +9,46 @@ name: Destroy preview environment
jobs:
destroy-preview-environment:
runs-on: ubuntu-latest
- if: github.repository == github.event.pull_request.head.repo.full_name
steps:
+ - uses: actions/github-script@v6.3.3
+ id: check-conclusion
+ env:
+ number: ${{ github.event.number }}
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ result-encoding: string
+ script: |
+ const { data: pull } = await github.rest.pulls.get({
+ ...context.repo,
+ pull_number: process.env.number
+ });
+ const ref = pull.head.sha;
+
+ const { data: checks } = await github.rest.checks.listForRef({
+ ...context.repo,
+ ref
+ });
+
+ const check = checks.check_runs.filter(c => c.name === 'deploy-preview-environment');
+
+ if (check.length === 0) {
+ return;
+ }
+
+ const { data: result } = await github.rest.checks.get({
+ ...context.repo,
+ check_run_id: check[0].id,
+ });
+
+ return result.conclusion;
- name: Context
+ if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/context@latest
with:
token: ${{ secrets.OKTETO_TOKEN }}
- name: Destroy preview environment
+ if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/destroy-preview@latest
with:
name: pr-${{ github.event.number }}-syuilo
diff --git a/.vscode/settings.json b/.vscode/settings.json
index b7e7b20c17..c94a34194e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,6 @@
{
"search.exclude": {
"**/node_modules": true
- }
+ },
+ "typescript.tsdk": "node_modules/typescript/lib"
} \ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81d81f5de0..489fcff2cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
## 13.x.x (unreleased)
### Improvements
+- feat: 検索画é¢ã®çµ±åˆ (Khsmty)
### Bugfixes
-
@@ -11,10 +12,86 @@ You should also include the user name that made the change.
## 13.x.x (unreleased)
### Improvements
+- ãƒãƒ£ãƒ³ãƒãƒ«å†…ãƒã‚¤ãƒ©ã‚¤ãƒˆ
+- renoteã—ãŸéš›ã®è¡¨ç¤ºã‚’改善
+- ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§ä¸€å®šæ™‚間経éŽã—ãŸã‚‰ãƒšãƒ¼ã‚¸ãƒãƒ¼ã‚·ãƒ§ãƒ³ã®ã‚¢ã‚¤ãƒ†ãƒ æ›´æ–°ã‚’ã—ãªã„
+- enhance(client): MkUrlPreviewã®é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã‚’見やã™ã
+- Add dialog to remove follower
+- enhance(client): improve clip menu ux
+- 検索画é¢ã®çµ±åˆ
+- enhance(client): ノートメニューã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’é–‹ã‘るよã†ã«
+
+### Bugfixes
+- Windows環境ã§swcを使ã†ã¨æ­£ã—ãビルドã§ããªã„å•題ã®ä¿®æ­£
+- fix(client): Android Chromeã§PWAã¨ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ããªã„å•題を修正
+- 未知ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒ deleteActor ã•れãŸã‚‰å‡¦ç†ã‚’スキップã™ã‚‹
+- fix(server): notes/createã§ã€fileIdsã¨è¦‹ã¤ã‹ã£ãŸãƒ•ã‚¡ã‚¤ãƒ«ã®æ•°ãŒç•°ãªã‚‹å ´åˆã¯ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹
+
+## 13.7.5 (2023/02/24)
+
+### Note
+13.7.0以å‰ã‹ã‚‰ç›´æŽ¥ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹å ´åˆã¯å…¨ã¦ã®é€šçŸ¥ãŒå‰Šé™¤**ã•れã¾ã›ã‚“。**
+
+### Improvements
+- 紛らã‚ã—ã„ãŸã‚公開範囲ã®ã€Œãƒ­ãƒ¼ã‚«ãƒ«ã®ã¿ã€ã‚ªãƒ—ションã®å称を「連åˆãªã—ã€ã«å¤‰æ›´
+- Frontend: スマホ・タブレットã®å ´åˆã€ãƒãƒ£ãƒ³ãƒãƒ«ã®æŠ•稿フォームã«è‡ªå‹•ã§ãƒ•ォーカスã—ãªã„よã†ã«
+
+### Bugfixes
+- å…¨ã¦ã®é€šçŸ¥ãŒå‰Šé™¤ã•れã¦ã—ã¾ã†ã®ã‚’修正
+
+## 13.7.3 (2023/02/23)
+
+### Note
+~~13.7.0以å‰ã‹ã‚‰ç›´æŽ¥ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã™ã‚‹å ´åˆã¯å…¨ã¦ã®é€šçŸ¥ãŒå‰Šé™¤**ã•れã¾ã›ã‚“。**~~
+
+### Improvements
+
+### Bugfixes
+- Client: 「キャッシュを削除ã€ã—ãŸå¾Œã€ãƒ­ãƒ¼ã‚«ãƒ«ã®ã‚«ã‚¹ã‚¿ãƒ çµµæ–‡å­—ãŒè¡¨ç¤ºã•れãªããªã‚‹ã•れãªããªã‚‹å•題を修正
+- Client: 通知設定画é¢ã§ä»¥å‰ã‹ã‚‰ã‚°ãƒ«ãƒ¼ãƒ—ã®æ‹›å¾…を有効化ã—ã¦ã„ãŸå ´åˆã€é€šçŸ¥ã®è¡¨ç¤ºã«å¤±æ•—ã™ã‚‹å•題ã®ä¿®æ­£
+- Client: 通知設定画é¢ã«å¤ã„ãƒˆã‚°ãƒ«ãŒæ®‹ã£ã¦ã„ãŸå•題を修正
+
+## 13.7.2 (2023/02/23)
+
+### Note
+13.7.0以å‰ã‹ã‚‰ã‚¢ãƒƒãƒ—デートã™ã‚‹å ´åˆã¯å…¨ã¦ã®é€šçŸ¥ãŒå‰Šé™¤ã•れã¾ã™ã€‚
+
+### Improvements
+- enhance: make pwa icon maskable
+- chore(client): tweak custom emoji size
+
+### Bugfixes
+- マイグレーションãŒå¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã‚’修正
+
+## 13.7.1 (2023/02/23)
+
+### Improvements
+- pnpm buildã§ã¯swcを使ã†ã‚ˆã†ã«
+
+### Bugfixes
+- NODE_ENV=productionã§ãƒ“ルドã§ããªã„ã®ã‚’修正
+
+## 13.7.0 (2023/02/22)
+
+### Changes
+- ãƒãƒ£ãƒƒãƒˆæ©Ÿèƒ½ãŒå‰Šé™¤ã•れã¾ã—ãŸ
+
+### Improvements
- Server: URLプレビュー(summaly)ã¯ãƒ—ロキシを通ã™ã‚ˆã†ã«
+- Client: 2FA設定ã®UIã‚’ã¾ã¨ã‚‚ã«ã—ãŸ
+- セキュリティキーã®åå‰ã‚’変更ã§ãるよã†ã«
+- enhance(client): add quiz preset for play
+- 広告開始時期を設定ã§ãるよã†ã«
+- ã¿ã¤ã‘ã‚‹ã§å…¬é–‹ãƒ­ãƒ¼ãƒ«ä¸€è¦§ã¨ãã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’閲覧ã§ãるよã†ã«
+- enhance(client): MFMã®x3, x4ãŒå«ã¾ã‚Œã¦ã„ãŸã‚‰ãƒŽãƒ¼ãƒˆã‚’ãŸãŸã‚€ã‚ˆã†ã«
+- enhance(client): make possible to reload page of window
### Bugfixes
--
+- ユーザー検索ダイアログã§ãƒ­ãƒ¼ã‚«ãƒ«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’絞ã£ã¦æ¤œç´¢ã§ããªã„å•題を修正
+- fix(client): MkHeaderåŠã³ãƒ‡ãƒƒã‚­ã®ã‚«ãƒ©ãƒ ã§ãƒãƒ£ãƒ³ãƒãƒ«ä¸€è¦§ã‚’é¸æŠžã—ãŸã¨ãã€æœ€å¤§5個ã¾ã§ã—ã‹è¡¨ç¤ºã•れãªã„
+- 管ç†ç”»é¢ã®åºƒå‘Šã‚’10個以上見ãˆã‚‹ã‚ˆã†ã«
+- Moderation note ãŒä¿å­˜ã§ããªã„
+- ユーザーã®ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°æ¤œç´¢ãŒæ©Ÿèƒ½ã—ã¦ã„ãªã„ã®ã‚’修正
## 13.6.1 (2023/02/12)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 48d8a40dea..668989f122 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -83,11 +83,18 @@ An actual domain will be assigned so you can test the federation.
- The title must be in the format `Release: x.y.z`.
- `x.y.z` is the new version you are trying to release.
3. Deploy and perform a simple QA check. Also verify that the tests passed.
-4. Merge it.
+4. Merge it. (Do not squash commit)
5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases)
- The target branch must be `master`
- The tag name must be the version
+> **Note**
+> Why this instruction is necessary:
+> - To perform final QA checks
+> - To distribute responsibility
+> - To check direct commits to develop
+> - To celebrate the release together 🎉
+
## Localization (l10n)
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
You can improve our translations with your Crowdin account.
@@ -278,9 +285,10 @@ SQLã§ã¯é…列ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã¯**1å§‹ã¾ã‚Š**。
### null IN
nullãŒå«ã¾ã‚Œã‚‹å¯èƒ½æ€§ã®ã‚るカラムã«INã™ã‚‹ã¨ãã¯ã€ãã®ã¾ã¾ã ã¨ãŠã‹ã—ããªã‚‹ã®ã§ORãªã©ã§nullã®ãƒãƒ³ãƒ‰ãƒªãƒ³ã‚°ã‚’ã—よã†ã€‚
-### `undefined`ã«ã”用心
-MongoDBã®æ™‚ã¨ã¯é•ã„ã€findOneã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–å¾—ã™ã‚‹æ™‚ã«å¯¾è±¡ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒå­˜åœ¨ã—ãªã„å ´åˆ **`undefined`** ãŒè¿”ã£ã¦ãã‚‹ã®ã§æ³¨æ„。
-MongoDBã¯`null`ã§è¿”ã—ã¦ãã¦ãŸã®ã§ã€ãã®æ„Ÿè¦šã§`if (x === null)`ã¨ã‹æ›¸ãã¨ãƒã‚°ã‚‹ã€‚代ã‚りã«`if (x == null)`ã¨æ›¸ã„ã¦ãã ã•ã„
+### enumã®å‰Šé™¤ã¯æ°—ã‚’ã¤ã‘ã‚‹
+enumã®åˆ—挙ã®å†…容ã®å‰Šé™¤ã¯ã€ãã®å€¤ã‚’ã‚‚ã¤ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å…¨ã¦å‰Šé™¤ã—ãªã„ã¨ã„ã‘ãªã„
+
+削除ãŒé‡ãŸã‹ã£ãŸã‚Šä¸å¯èƒ½ã ã£ãŸã‚Šã™ã‚‹å ´åˆã¯ã€å‰Šé™¤ã—ãªã„ã§ãŠã
### Migrationä½œæˆæ–¹æ³•
packages/backendã§:
diff --git a/ROADMAP.md b/ROADMAP.md
index c95bb8d92b..420f728758 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -5,9 +5,9 @@ Also, the later tasks are more indefinite and are subject to change as developme
## (1) Improve maintainability \<current phase\>
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
-- Make the number of type errors zero (backend)
+- ~~Make the number of type errors zero (backend)~~ → Done ✔ï¸
- Improve CI
- - Fix tests
+ - ~~Fix tests~~ → Done ✔ï¸
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
- Add more tests
- ~~May need to implement a mechanism that allows for DI~~ → Done ✔ï¸
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000000..5d8d232b5e
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,6 @@
+coverage:
+ status:
+ project:
+ default:
+ only_pulls: true
+ if_ci_failed: success
diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml
index 467aed1294..fb06f77daf 100644
--- a/locales/ar-SA.yml
+++ b/locales/ar-SA.yml
@@ -379,13 +379,10 @@ about: "عن"
aboutMisskey: "عن Misskey"
administrator: "المدير"
token: "الرمز المميز"
-twoStepAuthentication: "الإستيثاق بعاملَيْن"
moderator: "مشرÙÙ"
moderation: "الإشراÙ"
nUsersMentioned: "{n} مستخدمين Ø£ÙØ´ÙŠØ± إليهم"
securityKey: "Ù…ÙØªØ§Ø­ الأمان"
-securityKeyName: "اسم Ø§Ù„Ù…ÙØªØ§Ø­"
-registerSecurityKey: "سجل Ù…ÙØªØ§Ø­ أمان"
lastUsed: "آخر استخدام"
unregister: "إلغاء التسجيل"
passwordLessLogin: "Ù„ÙØ¬ Ù…ÙÙ† دون كلمة سرية"
@@ -403,24 +400,15 @@ markAsReadAllTalkMessages: "علّم جميع الرسائل كمقروءة"
help: "المساعدة"
inputMessageHere: "اكتب رسالتك هنا"
close: "اغلق"
-group: "Ø§Ù„ÙØ±ÙŠÙ‚"
-groups: "الÙÙØ±ÙŽÙ‚"
-createGroup: "انشئ ÙØ±ÙŠÙ‚ًا"
-ownedGroups: "ÙÙØ±Ù‚ÙŠ"
-joinedGroups: "الÙÙØ±Ù‚ المÙنضم إليها"
invites: "دعوة"
-groupName: "اسم Ø§Ù„ÙØ±ÙŠÙ‚"
members: "الأعضاء"
transfer: "نقل"
-messagingWithUser: "تحدث مع مستخدم"
-messagingWithGroup: "محادثة جماعية"
title: "العنوان"
text: "النص"
enable: "تشغيل"
next: "التالية"
retype: "أعد الكتابة"
noteOf: "ملاحظات {user}"
-inviteToGroup: "دعوة إلى ÙØ±ÙŠÙ‚"
quoteAttached: "اÙÙ‚ØªÙØ¨Ø³ÙŽ"
quoteQuestion: "أتريد تضمينها كاقتباس"
noMessagesYet: "ليس هناك رسائل بعد"
@@ -442,14 +430,10 @@ passwordMatched: "التطابق صحيح!"
passwordNotMatched: "غير متطابقتان"
signinWith: "الولوج عبر {x}"
signinFailed: "ÙØ´Ù„ الولوج، خطأ ÙÙŠ اسم المستخدم أو كلمة المرور."
-tapSecurityKey: "أنقر Ù…ÙØªØ§Ø­ الأمان"
or: "أو"
language: "اللغة"
uiLanguage: "لغة واجهة المستخدم"
-groupInvited: "Ø¯ÙØ¹ÙŠØª إلى ÙØ±ÙŠÙ‚Ù"
aboutX: "عن {x}"
-youHaveNoGroups: "لا تمتلك أية ÙÙØ±ÙŽÙ‚"
-joinOrCreateGroup: "احصل على دعوة Ù„ÙØ±ÙŠÙ‚ أو أنشئ واحدًا."
noHistory: "السجل ÙØ§Ø±Øº"
signinHistory: "تاريخ تسجيل الدخول"
doing: "انتظر لحظة"
@@ -790,8 +774,6 @@ deleteAccountConfirm: "سيحذ٠حسابك نهائيًا، أتريد المØ
incorrectPassword: "كلمة السر خاطئة."
voteConfirm: "متيقّÙÙ† من تصويتك لـ {choice}ØŸ"
hide: "Ø¥Ø®ÙØ§Ø¡"
-leaveGroup: "مغادرة Ø§Ù„ÙØ±ÙŠÙ‚"
-leaveGroupConfirm: "متيقن من مغادرة \"{name}\"؟"
welcomeBackWithName: "مرحبًا بك مجددًا {name}"
clickToFinishEmailVerification: "انقر [{ok}] لاستيثاق بريدك الإلكتروني."
overridedDeviceKind: "نوع الجهاز"
@@ -1019,12 +1001,11 @@ _tutorial:
step7_3: "حظًا سعيدًا واستمتع بوقتك مع ميسكي! 🚀"
_2fa:
alreadyRegistered: "سجلت سلÙًا جهازًا للاستيثاق بعاملين."
- registerDevice: "سجّل جهازًا جديدًا"
- registerKey: "تسجيل Ù…ÙØªØ§Ø­ أمان جديد"
step1: "أولًا ثبّت تطبيق استيثاق على جهازك (مثل {a} و{b})."
step2: "امسح رمز الاستجابة السريعة الموجد على الشاشة."
step3: "أدخل الرمز الموجود ÙÙŠ تطبيقك لإكمال التثبيت."
step4: "من هذه اللحظة أثناء ولوجك Ø³ÙŠÙØ·Ù„ب منك الرمز."
+ renewTOTPCancel: "ليس اﻵن"
_permissions:
"read:account": "اعرض معلومات حسابك"
"write:account": "تعديل معلومات حسابك"
@@ -1133,8 +1114,6 @@ _visibility:
followersDescription: "اجعلها مرئية Ù„Ù…ØªØ§Ø¨ÙØ¹ÙŠÙƒ Ùقط"
specified: "مباشرة"
specifiedDescription: "اجعلها مرئية لمستخدمين محددين"
- localOnly: "المحلي Ùقط"
- localOnlyDescription: "ليس مرئيًا للمستخدمين Ø§Ù„Ø¨ÙØ¹Ø§Ø¯"
_postForm:
replyPlaceholder: "رد على هذه الملاحظة…"
quotePlaceholder: "اقتبس هذه الملاحظة…"
@@ -1255,12 +1234,9 @@ _notification:
youGotReply: "ردّ عليك {name}"
youGotQuote: "اقتبس منك {name}"
youRenoted: "إعادت نشر من {name}"
- youGotMessagingMessageFromUser: "لقد تلقيت رسالة Ù…ÙÙ† {name}"
- youGotMessagingMessageFromGroup: "لقد أرسÙلَت رسالة إلى Ø§Ù„ÙØ±ÙŠÙ‚ {name}"
youWereFollowed: "يتابعك"
youReceivedFollowRequest: "تلقيتَ طلب متابعة"
yourFollowRequestAccepted: "Ù‚ÙØ¨Ù„ طلب المتابعة"
- youWereInvitedToGroup: "Ø¯ÙØ¹ÙŠØª إلى ÙØ±ÙŠÙ‚Ù"
pollEnded: "ظهرت نتائج الاستطلاع"
unreadAntennaNote: "هوائي {name}"
_types:
@@ -1273,7 +1249,6 @@ _notification:
reaction: "Ø§Ù„ØªÙØ§Ø¹Ù„ات"
receiveFollowRequest: "طلبات المتابعة المتلقاة"
followRequestAccepted: "طلبات المتابعة المقبولة"
- groupInvited: "دعوات Ø§Ù„ÙØ±ÙŠÙ‚"
app: "إشعارات التطبيقات المرتبطة"
_actions:
followBack: "تابعك بالمثل"
diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml
index 92e3785936..18898bf4d6 100644
--- a/locales/bn-BD.yml
+++ b/locales/bn-BD.yml
@@ -382,12 +382,9 @@ about: "আপনার সমà§à¦ªà¦°à§à¦•ে"
aboutMisskey: "Misskey সমà§à¦ªà¦°à§à¦•ে"
administrator: "পà§à¦°à¦¶à¦¾à¦¸à¦•"
token: "টোকেন"
-twoStepAuthentication: "২-ধাপ পà§à¦°à¦®à¦¾à¦£à§€à¦•রণ"
moderator: "মডারেটর"
nUsersMentioned: "{n} জনকে উলà§à¦²à§‡à¦– করা হয়েছে"
securityKey: "সিকিউরিটি কী"
-securityKeyName: "কী'র নাম"
-registerSecurityKey: "সিকিউরিটি কী নিবনà§à¦§à¦¨ করà§à¦¨"
lastUsed: "শেষ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦° করা হয়েছে"
unregister: "নিবনà§à¦§à¦¨à¦®à§à¦•à§à¦¤ হন"
passwordLessLogin: "পাসওয়ারà§à¦¡-বিহীন লগইন সেট আপ করà§à¦¨"
@@ -405,24 +402,15 @@ markAsReadAllTalkMessages: "সমসà§à¦¤ মেসেজ পঠিত হিà
help: "সহায়তা"
inputMessageHere: "à¦à¦–ানে মেসেজ লিখà§à¦¨"
close: "বনà§à¦§"
-group: "গà§à¦°à§à¦ª"
-groups: "গà§à¦°à§à¦ªà¦¸à¦®à§‚হ"
-createGroup: "গà§à¦°à§à¦ª তৈরী করà§à¦¨"
-ownedGroups: "আপনার গà§à¦°à§à¦ªà¦—à§à¦²à¦¿"
-joinedGroups: "যেসব গà§à¦°à§à¦ªà§‡ আপনি আছেন"
invites: "আমনà§à¦¤à§à¦°à¦£"
-groupName: "গà§à¦°à§à¦ªà§‡à¦° নাম"
members: "সদসà§à¦¯à¦¬à§ƒà¦¨à§à¦¦"
transfer: "হসà§à¦¤à¦¾à¦¨à§à¦¤à¦°"
-messagingWithUser: "পà§à¦°à¦¾à¦‡à¦­à§‡à¦Ÿ চà§à¦¯à¦¾à¦Ÿ"
-messagingWithGroup: "গà§à¦°à§à¦ª চà§à¦¯à¦¾à¦Ÿ"
title: "শিরোনাম"
text: "পাঠà§à¦¯"
enable: "সকà§à¦°à¦¿à§Ÿ"
next: "পরবরà§à¦¤à§€"
retype: "পà§à¦¨à¦ƒ পà§à¦°à¦¬à§‡à¦¶"
noteOf: "{user} à¦à¦° নোট"
-inviteToGroup: "গà§à¦°à§à¦ªà§‡ আমনà§à¦¤à§à¦°à¦£ জানান"
quoteAttached: "উদà§à¦§à§ƒà¦¤"
quoteQuestion: "উদà§à¦§à§ƒà¦¤à¦¿ হিসাবে সংযà§à¦•à§à¦¤ করবেন?"
noMessagesYet: "কোন মেসেজ নেই"
@@ -444,15 +432,11 @@ passwordMatched: "মিলেছে"
passwordNotMatched: "মিলেনি"
signinWith: "{x} à¦à¦° সাহাযà§à¦¯à§‡ সাইন ইন করà§à¦¨"
signinFailed: "লগ ইন করা যায়নি। আপনার বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর নাম à¦à¦¬à¦‚ পাসওয়ারà§à¦¡ চেক করà§à¦¨."
-tapSecurityKey: "সিকিউরিটি কী সà§à¦ªà¦°à§à¦¶ করà§à¦¨"
or: "অথবা"
language: "ভাষা"
uiLanguage: "UI à¦à¦° ভাষা"
-groupInvited: "আপনি à¦à¦•টি গà§à¦°à§à¦ªà§‡ আমনà§à¦¤à§à¦°à¦¿à¦¤ হয়েছেন"
aboutX: "{x} সমà§à¦ªà¦°à§à¦•ে"
disableDrawer: "ডà§à¦°à¦¯à¦¼à¦¾à¦° মেনৠপà§à¦°à¦¦à¦°à§à¦¶à¦¨ করবেন না"
-youHaveNoGroups: "আপনার কোন গà§à¦°à§à¦ª নেই "
-joinOrCreateGroup: "à¦à¦•টি বিদà§à¦¯à¦®à¦¾à¦¨ গà§à¦°à§à¦ªà§‡à¦° আমনà§à¦¤à§à¦°à¦£ পান বা à¦à¦•টি নতà§à¦¨ গà§à¦°à§à¦ª তৈরি করà§à¦¨à§·"
noHistory: "কোনো ইতিহাস নেই"
signinHistory: "পà§à¦°à¦¬à§‡à¦¶ করার ইতিহাস"
doing: "পà§à¦°à¦•à§à¦°à¦¿à§Ÿà¦¾ করছে..."
@@ -820,8 +804,6 @@ deleteAccountConfirm: "আপনার অà§à¦¯à¦¾à¦•াউনà§à¦Ÿ মà§à¦›à
incorrectPassword: "আপনার দেওয়া পাসওয়ারà§à¦¡à¦Ÿà¦¿ ভà§à¦²à¥¤"
voteConfirm: "\"{choice}\" ঠভোট দিতে চান?"
hide: "লà§à¦•ান"
-leaveGroup: "গà§à¦°à§à¦ª ছেড়ে চলে যান"
-leaveGroupConfirm: "\"{name}\" গà§à¦°à§à¦ª ছেড়ে চলে যেতে চান?"
useDrawerReactionPickerForMobile: "মোবাইলে রিঅà§à¦¯à¦¾à¦•শন পিকারকে ডà§à¦°à¦¯à¦¼à¦¾à¦°à§‡ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করà§à¦¨"
welcomeBackWithName: "আবার সà§à¦¬à¦¾à¦—তম, {name}"
clickToFinishEmailVerification: " [{ok}] কà§à¦²à¦¿à¦• করার মাধà§à¦¯à¦®à§‡ আপনার ইমেল ঠিকানা নিশà§à¦šà¦¿à¦¤ করà§à¦¨à¥¤"
@@ -1081,8 +1063,6 @@ _tutorial:
step7_3: "à¦à¦–ন Misskey উপভোগ করà§à¦¨ 🚀"
_2fa:
alreadyRegistered: "আপনি ইতিমধà§à¦¯à§‡ à¦à¦•টি 2-ফà§à¦¯à¦¾à¦•à§à¦Ÿà¦° অথেনটিকেশন ডিভাইস নিবনà§à¦§à¦¨ করেছেন৷"
- registerDevice: "নতà§à¦¨ ডিভাইস নিবনà§à¦§à¦¨ করà§à¦¨"
- registerKey: "সিকিউরিটি কী নিবনà§à¦§à¦¨ করà§à¦¨"
step1: "পà§à¦°à¦¥à¦®à§‡, আপনার ডিভাইসে {a} বা {b} à¦à¦° মতো à¦à¦•টি অথেনটিকেশন অà§à¦¯à¦¾à¦ª ইনসà§à¦Ÿà¦² করà§à¦¨à§·"
step2: "à¦à¦°à¦ªà¦°à§‡, অà§à¦¯à¦¾à¦ªà§‡à¦° সাহাযà§à¦¯à§‡ পà§à¦°à¦¦à¦°à§à¦¶à¦¿à¦¤ QR কোডটি সà§à¦•à§à¦¯à¦¾à¦¨ করà§à¦¨à¥¤"
step2Url: "ডেসà§à¦•টপ অà§à¦¯à¦¾à¦ªà§‡, নিমà§à¦¨à¦²à¦¿à¦–িত URL লিখà§à¦¨:"
@@ -1134,7 +1114,6 @@ _antennaSources:
homeTimeline: "আপনি অনà§à¦¸à¦°à¦£ করছেন, à¦à¦®à¦¨ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের নোট"
users: "à¦à¦• বা à¦à¦•াধিক নিরà§à¦¦à¦¿à¦·à§à¦Ÿ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর নোট"
userList: "নিরà§à¦¦à¦¿à¦·à§à¦Ÿ তালিকায় নাম থাকা বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের নোট"
- userGroup: "নিরà§à¦¦à¦¿à¦·à§à¦Ÿ গà§à¦°à§à¦ªà§‡ থাকা বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীদের নোট"
_weekday:
sunday: "রবিবার"
monday: "সোমবার"
@@ -1203,8 +1182,6 @@ _visibility:
followersDescription: "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° আপনার অনà§à¦¸à¦°à¦£à¦•ারীদের নিকট পোসà§à¦Ÿ করà§à¦¨"
specified: "ডাইরেকà§à¦Ÿ নোট"
specifiedDescription: "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° নিরà§à¦¦à¦¿à¦·à§à¦Ÿ বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à¦•ারীর নিকট পাঠান"
- localOnly: "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° লোকাল"
- localOnlyDescription: "রিমোট বà§à¦¯à¦¾à¦¬à¦¹à¦¾à¦°à¦•ারীদের নিকট দৃশà§à¦¯à¦®à¦¾à¦¨ নয়"
_postForm:
replyPlaceholder: "নোটটির জবাব দিন..."
quotePlaceholder: "নোটটিকে উদà§à¦§à§ƒà¦¤ করà§à¦¨..."
@@ -1332,12 +1309,9 @@ _notification:
youGotReply: "{name} আপনাকে জবাব দিয়েছে"
youGotQuote: "{name} আপনাকে উদà§à¦§à§ƒà¦¤ করেছে"
youRenoted: "{name} à¦à¦° Renote"
- youGotMessagingMessageFromUser: "{name} আপনাকে মেসেজ করেছে"
- youGotMessagingMessageFromGroup: "{name} গà§à¦°à§à¦ªà§‡ à¦à¦•টি নতà§à¦¨ মেসেজ আছে"
youWereFollowed: "আপনাকে অনà§à¦¸à¦°à¦£ করছে"
youReceivedFollowRequest: "অনà§à¦¸à¦°à¦£ করার জনà§à¦¯ অনà§à¦°à§‹à¦§ পাওয়া গেছে"
yourFollowRequestAccepted: "আপনার অনà§à¦¸à¦°à¦£ করার অনà§à¦°à§‹à¦§ গৃহীত হয়েছে"
- youWereInvitedToGroup: "আপনি à¦à¦•টি গà§à¦°à§à¦ªà§‡ আমনà§à¦¤à§à¦°à¦¿à¦¤ হয়েছেন"
pollEnded: "পোলের ফলাফল দেখা যাবে"
emptyPushNotificationMessage: "আপডেট করা পà§à¦¶ বিজà§à¦žà¦ªà§à¦¤à¦¿"
_types:
@@ -1351,7 +1325,6 @@ _notification:
pollEnded: "পোল শেষ"
receiveFollowRequest: "পà§à¦°à¦¾à¦ªà§à¦¤ অনà§à¦¸à¦°à¦£à§‡à¦° অনà§à¦°à§‹à¦§à¦¸à¦®à§‚হ"
followRequestAccepted: "গৃহীত অনà§à¦¸à¦°à¦£à§‡à¦° অনà§à¦°à§‹à¦§à¦¸à¦®à§‚হ"
- groupInvited: "গà§à¦°à§à¦ªà§‡à¦° আমনà§à¦¤à§à¦°à¦¨à¦¸à¦®à§‚হ"
app: "লিঙà§à¦• করা অà§à¦¯à¦¾à¦ª থেকে বিজà§à¦žà¦ªà§à¦¤à¦¿"
_actions:
followBack: "ফলো বà§à¦¯à¦¾à¦• করেছে"
diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index d89e22631c..2b1168f780 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -315,13 +315,10 @@ userList: "Llistes"
about: "Informació"
aboutMisskey: "Quant a Misskey"
administrator: "Administrador/a"
-twoStepAuthentication: "Verificació en dos passos"
moderator: "Moderador/a"
moderation: "Moderació"
nUsersMentioned: "{n} usuaris mencionats"
securityKey: "Clau de seguretat"
-securityKeyName: "Nom de la clau"
-registerSecurityKey: "Registra la clau de seguretat"
unregister: "Cancel·la el registre"
passwordLessLogin: "Inici de sessió sense contrasenya"
resetPassword: "Restableix la contrasenya"
@@ -334,7 +331,6 @@ help: "Ajuda"
invites: "Convida"
next: "Següent"
noteOf: "Publicació de: {user}"
-inviteToGroup: "Convida'l al grup"
invitations: "Convida"
tags: "Etiquetes"
docSource: "Font del document"
@@ -393,7 +389,6 @@ _antennaSources:
homeTimeline: "Publicacions dels usuaris seguits"
users: "Publicacions d'usuaris específics"
userList: "Publicacions d'una llista d'usuaris"
- userGroup: "Publicacions d'usuaris d'un grup"
_widgets:
profile: "Perfil"
instanceInfo: "Informació del fitxer d'instal·lació"
diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml
index eaafd5ee10..32891ff9fd 100644
--- a/locales/cs-CZ.yml
+++ b/locales/cs-CZ.yml
@@ -337,12 +337,9 @@ about: "Informace"
aboutMisskey: "O Misskey"
administrator: "Administrátor"
token: "Token"
-twoStepAuthentication: "Dvoufaktorová autentikace"
moderator: "Moderátor"
nUsersMentioned: "{n} uživatelů zmínilo"
securityKey: "BezpeÄnostní klíÄ"
-securityKeyName: "Název klíÄe"
-registerSecurityKey: "Registrovat bezpeÄnostní klíÄ"
lastUsed: "Naposledy použito"
unregister: "Odstranit"
resetPassword: "Resetovat heslo"
@@ -359,13 +356,7 @@ markAsReadAllTalkMessages: "OznaÄit vÅ¡echny zprávy za pÅ™eÄtené"
help: "Nápověda"
inputMessageHere: "Sem zadejte zprávu"
close: "Zavřít"
-group: "Skupina"
-groups: "Skupiny"
-createGroup: "Vytvořit skupinu"
-ownedGroups: "Vlastněné skupiny"
-joinedGroups: "Členství ve skupinách"
invites: "Pozvat"
-groupName: "Název skupiny"
members: "Členové"
transfer: "Převod"
title: "Titulek"
@@ -374,7 +365,6 @@ enable: "Povolit"
next: "Další"
retype: "Zadejte znovu"
noteOf: "{user} poznámky"
-inviteToGroup: "Pozvat do skupiny"
quoteAttached: "Citace"
quoteQuestion: "Přiložit jako citaci?"
noMessagesYet: "Zatím tu nejsou žádné zprávy"
@@ -396,14 +386,10 @@ passwordMatched: "Hesla se schodují"
passwordNotMatched: "Hesla se neschodují"
signinWith: "Přihlásit se s {x}"
signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo."
-tapSecurityKey: "ŤuknÄ›te na bezpeÄnostní klíÄ"
or: "Nebo"
language: "Jazyk"
uiLanguage: "Jazyk uživatelského rozhraní"
-groupInvited: "Pozvat do skupiny"
aboutX: "O {x}"
-youHaveNoGroups: "Nemáte žádné skupiny"
-joinOrCreateGroup: "Můžete požádat o pozvání do stávající skupiny nebo vytvořit novou."
noHistory: "Žádná historie"
signinHistory: "Historie přihlášení"
category: "Kategorie"
@@ -677,9 +663,6 @@ _time:
second: "Sekund"
minute: "Minut"
hour: "Hodin"
-_2fa:
- registerDevice: "Přidat zařízení"
- registerKey: "PÅ™idat bezpeÄnostní klíÄ"
_weekday:
sunday: "Neděle"
monday: "Pondělí"
@@ -773,7 +756,6 @@ _pages:
button: "TlaÄítko"
_notification:
youWereFollowed: "Máte nového následovníka"
- youWereInvitedToGroup: "Pozvat do skupiny"
_types:
all: "Vše"
follow: "Sledovaní"
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index fb80b92850..e68207f902 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -103,6 +103,8 @@ renoted: "Renote getätigt."
cantRenote: "Renote dieses Beitrags nicht möglich."
cantReRenote: "Renote einer Renote nicht möglich."
quote: "Zitieren"
+inChannelRenote: "Kanal-interner Renote"
+inChannelQuote: "Kanal-internes Zitat"
pinnedNote: "Angeheftete Notiz"
pinned: "Angeheftet"
you: "Du"
@@ -391,13 +393,10 @@ about: "Über"
aboutMisskey: "Über Misskey"
administrator: "Administrator"
token: "Token"
-twoStepAuthentication: "Zwei-Faktor-Authentifizierung"
moderator: "Moderator"
moderation: "Moderation"
nUsersMentioned: "Von {n} Benutzern erwähnt"
securityKey: "Sicherheitsschlüssel"
-securityKeyName: "Schlüsselname"
-registerSecurityKey: "Sicherheitsschlüssel registrieren"
lastUsed: "Zuletzt benutzt"
unregister: "Deaktivieren"
passwordLessLogin: "Passwortloses Anmelden einrichten"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "Alle Chats als gelesen markieren"
help: "Hilfe"
inputMessageHere: "Hier Nachricht eingeben"
close: "Schließen"
-group: "Gruppe"
-groups: "Gruppen"
-createGroup: "Gruppe erstellen"
-ownedGroups: "Meine Gruppen"
-joinedGroups: "Beigetretene Gruppen"
invites: "Einladungen"
-groupName: "Gruppenname"
members: "Mitglieder"
transfer: "Übertragen"
-messagingWithUser: "Privatchat"
-messagingWithGroup: "Gruppenchat"
title: "Titel"
text: "Text"
enable: "Aktivieren"
next: "Weiter"
retype: "Erneut eingeben"
noteOf: "Notiz von {user}"
-inviteToGroup: "Zu Gruppe einladen"
quoteAttached: "Zitat"
quoteQuestion: "Als Zitat anhängen?"
noMessagesYet: "Noch keine Nachrichten vorhanden"
@@ -454,19 +444,17 @@ passwordMatched: "Stimmt überein"
passwordNotMatched: "Stimmt nicht überein"
signinWith: "Mit {x} anmelden"
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
-tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
or: "Oder"
language: "Sprache"
uiLanguage: "Sprache der Benutzeroberfläche"
-groupInvited: "Du wurdest in eine Gruppe eingeladen"
aboutX: "Über {x}"
emojiStyle: "Emoji-Stil"
native: "Nativ"
disableDrawer: "Keine ausfahrbaren Menüs verwenden"
-youHaveNoGroups: "Keine Gruppen vorhanden"
-joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
noHistory: "Kein Verlauf gefunden"
signinHistory: "Anmeldungsverlauf"
+enableAdvancedMfm: "Erweitertes MFM aktivieren"
+enableAnimatedMfm: "Animiertes MFM aktivieren"
doing: "In Bearbeitung …"
category: "Kategorie"
tags: "Schlagwörter"
@@ -836,8 +824,6 @@ deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzde
incorrectPassword: "Falsches Passwort."
voteConfirm: "Wirklich für „{choice}“ abstimmen?"
hide: "Inhalt verbergen"
-leaveGroup: "Gruppe verlassen"
-leaveGroupConfirm: "Möchtest du „{name}“ wirklich verlassen?"
useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen"
welcomeBackWithName: "Willkommen zurück, {name}"
clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen."
@@ -945,6 +931,14 @@ 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."
+thisPostMayBeAnnoying: "Dieser Beitrag stört eventuell andere Benutzer."
+thisPostMayBeAnnoyingHome: "Zur Startseite schicken"
+thisPostMayBeAnnoyingCancel: "Abbrechen"
+thisPostMayBeAnnoyingIgnore: "Trotzdem schicken"
+collapseRenotes: "Bereits gesehene Renotes verkürzt anzeigen"
+internalServerError: "Serverinterner Fehler"
+internalServerErrorDescription: "Im Server ist ein unerwarteter Fehler aufgetreten."
+copyErrorInfo: "Fehlerdetails kopieren"
_achievements:
earnedAt: "Freigeschaltet am"
_types:
@@ -1491,14 +1485,14 @@ _tutorial:
step8_3: "Diese Einstellung kannst du jederzeit ändern."
_2fa:
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert."
- registerDevice: "Neues Gerät registrieren"
- registerKey: "Neuen Sicherheitsschlüssel registrieren"
step1: "Installiere zuerst eine Authentifizierungsapp (z.B. {a} oder {b}) auf deinem Gerät."
step2: "Dann, scanne den angezeigten QR-Code mit deinem Gerät."
step2Url: "Nutzt du ein Desktopprogramm kannst du alternativ diese URL eingeben:"
step3: "Gib zum Abschluss den Token ein, der von deiner App angezeigt wird."
step4: "Alle folgenden Anmeldungsversuche werden ab sofort die Eingabe eines solchen Tokens benötigen."
securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Anmeldung mit Hilfe eines FIDO2-kompatiblen Hardware-Sicherheitsschlüssels einrichten."
+ removeKeyConfirm: "Das Backup {name} löschen?"
+ renewTOTPCancel: "Nein, danke"
_permissions:
"read:account": "Deine Benutzerkontoinformationen lesen"
"write:account": "Deine Benutzerkontoinformationen bearbeiten"
@@ -1547,7 +1541,6 @@ _antennaSources:
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
users: "Notizen von einem oder mehreren angegebenen Benutzern"
userList: "Notizen von allen Benutzern einer Liste"
- userGroup: "Notizen von allen Benutzern einer Gruppe"
_weekday:
sunday: "Sonntag"
monday: "Montag"
@@ -1622,8 +1615,6 @@ _visibility:
followersDescription: "Nur für Follower sichtbar"
specified: "Direkt"
specifiedDescription: "Nur für bestimmte Benutzer sichtbar"
- localOnly: "Nur Lokal"
- localOnlyDescription: "Unsichtbar für Benutzer anderer Instanzen"
_postForm:
replyPlaceholder: "Dieser Notiz antworten …"
quotePlaceholder: "Diese Notiz zitieren …"
@@ -1761,12 +1752,9 @@ _notification:
youGotReply: "{name} hat dir geantwortet"
youGotQuote: "{name} hat dich zitiert"
youRenoted: "Renote deiner Notiz von {name}"
- youGotMessagingMessageFromUser: "{name} hat dir eine Chatnachricht gesendet"
- youGotMessagingMessageFromGroup: "In die Gruppe {name} wurde eine Chatnachricht gesendet"
youWereFollowed: "ist dir gefolgt"
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
- youWereInvitedToGroup: "{userName} hat dich in eine Gruppe eingeladen"
pollEnded: "Umfrageergebnisse sind verfügbar"
unreadAntennaNote: "Antenne {name}"
emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert"
@@ -1782,7 +1770,6 @@ _notification:
pollEnded: "Ende von Umfragen"
receiveFollowRequest: "Erhaltene Follow-Anfragen"
followRequestAccepted: "Akzeptierte Follow-Anfragen"
- groupInvited: "Erhaltene Gruppeneinladungen"
app: "Benachrichtigungen von Apps"
_actions:
followBack: "folgt dir nun auch"
diff --git a/locales/el-GR.yml b/locales/el-GR.yml
index 889be05578..0721ba6e99 100644
--- a/locales/el-GR.yml
+++ b/locales/el-GR.yml
@@ -230,21 +230,13 @@ moderator: "Συντονιστής"
moderation: "Συντονισμός"
cacheClear: "ΕκκαθάÏιση Ï€ÏοσωÏινής μνήμης"
markAsReadAllNotifications: "Όλες οι ειδοποιήσεις διαβάστηκαν"
-group: "Ομάδα"
-groups: "Ομάδες"
-createGroup: "ΔημιουÏγία ομάδας"
-ownedGroups: "Οι ομάδες σας"
-groupName: "Όνομα ομάδας"
members: "Μέλη"
transfer: "ΜεταφοÏά"
-messagingWithUser: "Ιδιωτική συνομιλία"
-messagingWithGroup: "Ομαδική συνομιλία"
title: "Τίτλος"
text: "Κείμενο"
enable: "ΕνεÏγοποίηση"
next: "Επόμενο"
noteOf: "Σημείωμα από {user}"
-inviteToGroup: "ΠÏόσκληση στην ομάδα"
quoteAttached: "ΠαÏάθεση"
signinRequired: "ΠαÏακαλοÏμε δημιουÏγήστε λογαÏιασμό ή συνδεθείτε Ï€Ïιν συνεχίσετε"
category: "ΚατηγοÏία"
@@ -337,7 +329,6 @@ _antennaSources:
homeTimeline: "Σημειώματα από μέλη που ακολουθείτε"
users: "Σημειώματα από συγκεκÏιμένα μέλη"
userList: "Σημειώματα από καθοÏισμένη λίστα μελών"
- userGroup: "Σημειώματα από μέλη καθοÏισμένης ομάδας"
_widgets:
profile: "ΠÏοφίλ"
instanceInfo: "ΠληÏοφοÏίες του instance"
@@ -382,7 +373,6 @@ _pages:
blocks:
image: "Εικόνες"
_notification:
- youGotMessagingMessageFromUser: "{name} σάς έστειλε ένα μήνυμα συνομιλίας"
youWereFollowed: "σε ακολοÏθησε"
_types:
follow: "Îέοι ακόλουθοι"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index beb5242b1c..1ee5620916 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -103,6 +103,8 @@ renoted: "Renoted."
cantRenote: "This post can't be renoted."
cantReRenote: "A renote can't be renoted."
quote: "Quote"
+inChannelRenote: "Channel-only Renote"
+inChannelQuote: "Channel-only Quote"
pinnedNote: "Pinned note"
pinned: "Pin to profile"
you: "You"
@@ -391,13 +393,10 @@ about: "About"
aboutMisskey: "About Misskey"
administrator: "Administrator"
token: "Token"
-twoStepAuthentication: "Two-factor authentication"
moderator: "Moderator"
moderation: "Moderation"
nUsersMentioned: "Mentioned by {n} users"
securityKey: "Security key"
-securityKeyName: "Key name"
-registerSecurityKey: "Register a security key"
lastUsed: "Last used"
unregister: "Unregister"
passwordLessLogin: "Password-less login"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "Mark all messages as read"
help: "Help"
inputMessageHere: "Enter message here"
close: "Close"
-group: "Group"
-groups: "Groups"
-createGroup: "Create a group"
-ownedGroups: "Owned Groups"
-joinedGroups: "Joined groups"
invites: "Invites"
-groupName: "Group name"
members: "Members"
transfer: "Transfer"
-messagingWithUser: "Private chat"
-messagingWithGroup: "Group chat"
title: "Title"
text: "Text"
enable: "Enable"
next: "Next"
retype: "Enter again"
noteOf: "Note by {user}"
-inviteToGroup: "Invite to group"
quoteAttached: "Quote"
quoteQuestion: "Append as quote?"
noMessagesYet: "No messages yet"
@@ -454,21 +444,17 @@ passwordMatched: "Matches"
passwordNotMatched: "Does not match"
signinWith: "Sign in with {x}"
signinFailed: "Unable to sign in. The entered username or password is incorrect."
-tapSecurityKey: "Tap your security key"
or: "Or"
language: "Language"
uiLanguage: "User interface language"
-groupInvited: "You've been invited to a group"
aboutX: "About {x}"
emojiStyle: "Emoji style"
native: "Native"
disableDrawer: "Don't use drawer-style menus"
-youHaveNoGroups: "You have no groups"
-joinOrCreateGroup: "Get invited to a group or create your own."
noHistory: "No history available"
signinHistory: "Login history"
enableAdvancedMfm: "Enable advanced MFM"
-enableAnimatedMfm: "Enable MFM with animation"
+enableAnimatedMfm: "Enable animated MFM"
doing: "Processing..."
category: "Category"
tags: "Tags"
@@ -819,6 +805,7 @@ lastCommunication: "Last communication"
resolved: "Resolved"
unresolved: "Unresolved"
breakFollow: "Remove follower"
+breakFollowConfirm: "Are you sure want to remove follower?"
itsOn: "Enabled"
itsOff: "Disabled"
emailRequiredForSignup: "Require email address for sign-up"
@@ -838,8 +825,6 @@ deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
incorrectPassword: "Incorrect password."
voteConfirm: "Confirm your vote for \"{choice}\"?"
hide: "Hide"
-leaveGroup: "Leave group"
-leaveGroupConfirm: "Are you sure you want to leave \"{name}\"?"
useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile"
welcomeBackWithName: "Welcome back, {name}"
clickToFinishEmailVerification: "Please click [{ok}] to complete email verification."
@@ -951,6 +936,10 @@ thisPostMayBeAnnoying: "This note may annoy others."
thisPostMayBeAnnoyingHome: "Post to home timeline"
thisPostMayBeAnnoyingCancel: "Cancel"
thisPostMayBeAnnoyingIgnore: "Post anyway"
+collapseRenotes: "Collapse renotes you've already seen"
+internalServerError: "Internal Server Error"
+internalServerErrorDescription: "The server has run into an unexpected error."
+copyErrorInfo: "Copy error details"
_achievements:
earnedAt: "Unlocked at"
_types:
@@ -1159,7 +1148,7 @@ _achievements:
description: "You've clicked here"
_justPlainLucky:
title: "Just Plain Lucky"
- description: "Has a chance to be obtained with a probability of 0.01% every 10 seconds"
+ description: "Has a chance to be obtained with a probability of 0.005% every 10 seconds"
_setNameToSyuilo:
title: "God Complex"
description: "Set your name to \"syuilo\""
@@ -1497,14 +1486,14 @@ _tutorial:
step8_3: "You can always change this setting later."
_2fa:
alreadyRegistered: "You have already registered a 2-factor authentication device."
- registerDevice: "Register a new device"
- registerKey: "Register a security key"
step1: "First, install an authentication app (such as {a} or {b}) on your device."
step2: "Then, scan the QR code displayed on this screen."
step2Url: "You can also enter this URL if you're using a desktop program:"
step3: "Enter the token provided by your app to finish setup."
step4: "From now on, any future login attempts will ask for such a login token."
securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup authentication via hardware security keys that support FIDO2 to further secure your account."
+ removeKeyConfirm: "Delete the {name} backup?"
+ renewTOTPCancel: "Not now"
_permissions:
"read:account": "View your account information"
"write:account": "Edit your account information"
@@ -1553,7 +1542,6 @@ _antennaSources:
homeTimeline: "Notes from followed users"
users: "Notes from specific users"
userList: "Notes from a specified list of users"
- userGroup: "Notes from users in a specified group"
_weekday:
sunday: "Sunday"
monday: "Monday"
@@ -1628,8 +1616,6 @@ _visibility:
followersDescription: "Make visible to your followers only"
specified: "Direct"
specifiedDescription: "Make visible for specified users only"
- localOnly: "Local only"
- localOnlyDescription: "Not visible to remote users"
_postForm:
replyPlaceholder: "Reply to this note..."
quotePlaceholder: "Quote this note..."
@@ -1767,12 +1753,9 @@ _notification:
youGotReply: "{name} replied to you"
youGotQuote: "{name} quoted you"
youRenoted: "Renote from {name}"
- youGotMessagingMessageFromUser: "{name} sent you a chat message"
- youGotMessagingMessageFromGroup: "A chat message was sent to the {name} group"
youWereFollowed: "followed you"
youReceivedFollowRequest: "You've received a follow request"
yourFollowRequestAccepted: "Your follow request was accepted"
- youWereInvitedToGroup: "{userName} invited you to a group"
pollEnded: "Poll results have become available"
unreadAntennaNote: "Antenna {name}"
emptyPushNotificationMessage: "Push notifications have been updated"
@@ -1788,7 +1771,6 @@ _notification:
pollEnded: "Polls ending"
receiveFollowRequest: "Received follow requests"
followRequestAccepted: "Accepted follow requests"
- groupInvited: "Group invitations"
app: "Notifications from linked apps"
_actions:
followBack: "followed you back"
diff --git a/locales/es-ES.yml b/locales/es-ES.yml
index 093818f5a2..6f638b3369 100644
--- a/locales/es-ES.yml
+++ b/locales/es-ES.yml
@@ -391,13 +391,10 @@ about: "Información"
aboutMisskey: "Sobre Misskey"
administrator: "Administrador"
token: "Token"
-twoStepAuthentication: "Autenticación de dos factores"
moderator: "Moderador"
moderation: "Moderación"
nUsersMentioned: "{n} usuarios mencionados"
securityKey: "Clave de seguridad"
-securityKeyName: "Nombre de la Clave"
-registerSecurityKey: "Registrar clave de seguridad"
lastUsed: "Última vez usado"
unregister: "Cancelar registro"
passwordLessLogin: "Iniciar sesión sin contraseña"
@@ -415,24 +412,15 @@ markAsReadAllTalkMessages: "Marcar todos los chats como leídos"
help: "Ayuda"
inputMessageHere: "Escribe el mensaje aquí"
close: "Cerrar"
-group: "Grupo"
-groups: "Grupos"
-createGroup: "Crear grupo"
-ownedGroups: "Tus"
-joinedGroups: "Grupos a los que me uní"
invites: "Invitar"
-groupName: "Nombre del grupo"
members: "Miembros"
transfer: "Transferir"
-messagingWithUser: "Chatear con usuario"
-messagingWithGroup: "Chatear en grupo"
title: "Título"
text: "Texto"
enable: "Activar"
next: "Siguiente"
retype: "Intentar de nuevo"
noteOf: "Notas de {user}"
-inviteToGroup: "Invitar al grupo"
quoteAttached: "Cita añadida"
quoteQuestion: "¿Quiere añadir una cita?"
noMessagesYet: "Aún no hay chat"
@@ -454,17 +442,13 @@ passwordMatched: "Correcto"
passwordNotMatched: "Las contraseñas no son las mismas"
signinWith: "Inicie sesión con {x}"
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos."
-tapSecurityKey: "Toque la clave de seguridad"
or: "O"
language: "Idioma"
uiLanguage: "Idioma de visualización de la interfaz"
-groupInvited: "Invitado al grupo"
aboutX: "Acerca de {x}"
emojiStyle: "Estilo de emoji"
native: "Nativo"
disableDrawer: "No mostrar los menús en cajones"
-youHaveNoGroups: "Sin grupos"
-joinOrCreateGroup: "Obtenga una invitación para unirse al grupos o puede crear su propio grupo."
noHistory: "No hay datos en el historial"
signinHistory: "Historial de ingresos"
doing: "Voy en camino"
@@ -836,8 +820,6 @@ deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
incorrectPassword: "La contraseña es incorrecta"
voteConfirm: "¿Confirma su voto a {choice}?"
hide: "Ocultar"
-leaveGroup: "Dejar el grupo"
-leaveGroupConfirm: "¿Desea salir de {name}?"
useDrawerReactionPickerForMobile: "Mostrar panel de reacciones en móviles"
welcomeBackWithName: "Bienvenido otra vez, {name}"
clickToFinishEmailVerification: "Cliquée {ok} y verifique su correo"
@@ -1489,14 +1471,14 @@ _tutorial:
step8_3: "La configuración de las notificaciones puede modificarse posteriormente."
_2fa:
alreadyRegistered: "Ya has completado la configuración."
- registerDevice: "Registrar dispositivo"
- registerKey: "Registrar clave"
step1: "Primero, instale en su dispositivo la aplicación de autenticación {a} o {b} u otra."
step2: "Luego, escanee con la aplicación el código QR mostrado en pantalla."
step2Url: "En una aplicación de escritorio se puede ingresar la siguiente URL:"
step3: "Para terminar, ingrese el token mostrado en la aplicación."
step4: "Ahora cuando inicie sesión, ingrese el mismo token"
securityKeyInfo: "Se puede configurar el inicio de sesión usando una clave de seguridad de hardware que soporte FIDO2 o con un certificado de huella digital o con un PIN"
+ removeKeyConfirm: "¿Borrar el respaldo \"{name}\"?"
+ renewTOTPCancel: "No gracias"
_permissions:
"read:account": "Ver información de la cuenta"
"write:account": "Editar información de la cuenta"
@@ -1545,7 +1527,6 @@ _antennaSources:
homeTimeline: "Notas de los usuarios que sigues"
users: "Notas de un usuario o varios"
userList: "Notas de los usuarios de una lista"
- userGroup: "Notas de los usuarios de una grupo"
_weekday:
sunday: "Domingo"
monday: "Lunes"
@@ -1620,8 +1601,6 @@ _visibility:
followersDescription: "Visible sólo para tus seguidores"
specified: "Mensaje directo"
specifiedDescription: "Visible sólo para los usuarios elegidos"
- localOnly: "Solo local"
- localOnlyDescription: "Oculto para usuarios remotos"
_postForm:
replyPlaceholder: "Responder a esta nota"
quotePlaceholder: "Citar esta nota"
@@ -1759,12 +1738,9 @@ _notification:
youGotReply: "Respuesta de {name}"
youGotQuote: "Citado por {name}"
youRenoted: "Renotado por {name}"
- youGotMessagingMessageFromUser: "{name} comenzó un chat contigo"
- youGotMessagingMessageFromGroup: "Tienes un chat de {name}"
youWereFollowed: "te ha seguido"
youReceivedFollowRequest: "Has mandado una solicitud de seguimiento"
yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada"
- youWereInvitedToGroup: "Invitado al grupo"
pollEnded: "Estan disponibles los resultados de la encuesta"
unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Se han actualizado las notificaciones push"
@@ -1780,7 +1756,6 @@ _notification:
pollEnded: "La encuesta terminó"
receiveFollowRequest: "Recibió una solicitud de seguimiento"
followRequestAccepted: "El seguimiento fue aceptado"
- groupInvited: "Invitado al grupo"
app: "Notificaciones desde aplicaciones"
_actions:
followBack: "Te sigue de vuelta"
diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index bb976334e9..de6156e39d 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -388,13 +388,10 @@ about: "Informations"
aboutMisskey: "À propos de Misskey"
administrator: "Administrateur"
token: "Jeton"
-twoStepAuthentication: "Authentification à deux facteurs"
moderator: "Modérateur·rice·s"
moderation: "Modérations"
nUsersMentioned: "{n} utilisateur·rice·s mentionné·e·s"
securityKey: "Clé de sécurité"
-securityKeyName: "Nom de la clé"
-registerSecurityKey: "Enregistrer une clé de sécurité"
lastUsed: "Dernier utilisé"
unregister: "Se désinscrire"
passwordLessLogin: "Se connecter sans mot de passe"
@@ -412,24 +409,15 @@ markAsReadAllTalkMessages: "Marquer toutes les discussions comme lues"
help: "Aide"
inputMessageHere: "Écrivez votre message ici"
close: "Fermer"
-group: "Groupe"
-groups: "Groupes"
-createGroup: "Créer un groupe"
-ownedGroups: "Mes groupes"
-joinedGroups: "Groupes rejoints"
invites: "Invitations"
-groupName: "Nom du groupe"
members: "Membres"
transfer: "Transférer"
-messagingWithUser: "Discuter avec un·e autre utilisateur·rice"
-messagingWithGroup: "Discuter avec un groupe"
title: "Titre"
text: "Texte"
enable: "Activer"
next: "Suivant"
retype: "Confirmation"
noteOf: "Notes de {user}"
-inviteToGroup: "Inviter dans un groupe"
quoteAttached: "Avec citation"
quoteQuestion: "Souhaitez-vous ajouter une citation ?"
noMessagesYet: "Pas encore de discussion"
@@ -451,17 +439,13 @@ passwordMatched: "Les mots de passe correspondent"
passwordNotMatched: "Les mots de passe ne correspondent pas"
signinWith: "Se connecter avec {x}"
signinFailed: "Échec d’authentification. Veuillez vérifier que votre nom d’utilisateur et mot de passe sont corrects."
-tapSecurityKey: "Appuyez sur votre clé de sécurité"
or: "OU"
language: "Langue"
uiLanguage: "Langue d’affichage de l’interface"
-groupInvited: "Invité au groupe"
aboutX: "À propos de {x}"
emojiStyle: "Style des émojis"
native: "Natif"
disableDrawer: "Les menus ne s'affichent pas dans le tiroir"
-youHaveNoGroups: "Vous n’avez aucun groupe"
-joinOrCreateGroup: "Vous pouvez être invité·e à rejoindre des groupes existants ou créer votre propre nouveau groupe."
noHistory: "Pas d'historique"
signinHistory: "Historique de connexion"
doing: "En cours..."
@@ -831,8 +815,6 @@ deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?"
incorrectPassword: "Le mot de passe est incorrect."
voteConfirm: "Confirmez-vous votre vote pour « {choice} » ?"
hide: "Masquer"
-leaveGroup: "Quitter le groupe"
-leaveGroupConfirm: "Êtes vous sûr de vouloir quitter \"{name}\" ?"
useDrawerReactionPickerForMobile: "Afficher le sélecteur de réactions en tant que panneau sur mobile"
welcomeBackWithName: "Heureux de vous revoir, {name}"
clickToFinishEmailVerification: "Veuillez cliquer sur [{ok}] afin de compléter la vérification par courriel."
@@ -1171,14 +1153,14 @@ _tutorial:
step8_2: "En les activant, vous recevrez des notifications pour les mentions, les réactions, les suivis, etc., même lorsque Misskey n'est pas ouvert."
_2fa:
alreadyRegistered: "Configuration déjà achevée."
- registerDevice: "Ajouter un nouvel appareil"
- registerKey: "Enregistrer une clef"
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
step2: "Ensuite, scannez le code QR affiché sur l’écran."
step2Url: "Vous pouvez également saisir cette URL si vous utilisez un programme de bureau :"
step3: "Entrez le jeton affiché sur votre application pour compléter la configuration."
step4: "À partir de maintenant, ce même jeton vous sera demandé à chacune de vos connexions."
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil."
+ removeKeyConfirm: "Voulez-vous supprimer {name} ?"
+ renewTOTPCancel: "Pas maintenant"
_permissions:
"read:account": "Afficher les informations du compte"
"write:account": "Mettre à jour les informations de votre compte"
@@ -1224,7 +1206,6 @@ _antennaSources:
homeTimeline: "Notes venant des utilisateur·rice·s auxquel·les je suis abonné"
users: "Notes venant de la part d’utilisateur·rice·s précis"
userList: "Notes venant d’une liste spécifique"
- userGroup: "Notes venant d’utilisateur·rice·s du groupe spécifié"
_weekday:
sunday: "Dimanche"
monday: "Lundi"
@@ -1296,8 +1277,6 @@ _visibility:
followersDescription: "Publier à vos abonné·e·s uniquement"
specified: "Direct"
specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
- localOnly: "Local seulement"
- localOnlyDescription: "Caché pour les utilisateurs distant"
_postForm:
replyPlaceholder: "Répondre à cette note ..."
quotePlaceholder: "Citez cette note ..."
@@ -1425,12 +1404,9 @@ _notification:
youGotReply: "Réponse de {name}"
youGotQuote: "Cité·e par {name}"
youRenoted: "{name} vous a Renoté"
- youGotMessagingMessageFromUser: "{name} vous envoyé un message"
- youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}"
youWereFollowed: "Vous suit"
youReceivedFollowRequest: "Vous avez reçu une demande d’abonnement"
yourFollowRequestAccepted: "Votre demande d’abonnement a été accepté"
- youWereInvitedToGroup: "Invité·e au groupe"
pollEnded: "Les résultats du sondage sont disponibles"
unreadAntennaNote: "Antenne {name}"
emptyPushNotificationMessage: "Les notifications push ont été mises à jour"
@@ -1445,7 +1421,6 @@ _notification:
pollEnded: "Sondages se cloturant"
receiveFollowRequest: "Demande d'abonnement reçue"
followRequestAccepted: "Demande d'abonnement acceptée"
- groupInvited: "Invitation à un groupe"
app: "Notifications provenant des apps"
_actions:
followBack: "Suivre"
diff --git a/locales/id-ID.yml b/locales/id-ID.yml
index 002eead689..d3d1a16219 100644
--- a/locales/id-ID.yml
+++ b/locales/id-ID.yml
@@ -84,7 +84,7 @@ error: "Galat"
somethingHappened: "Terjadi kesalahan"
retry: "Coba lagi"
pageLoadError: "Gagal memuat halaman."
-pageLoadErrorDescription: "Umumnya disebabkan jaringan atau tembolok perambah. Cobalah bersihkan tembolok peramban lalu tunggu sesaat sebelum mencoba kembali."
+pageLoadErrorDescription: "Umumnya disebabkan jaringan atau tembolok peramban. Cobalah bersihkan tembolok peramban lalu tunggu sesaat sebelum mencoba kembali."
serverIsDead: "Tidak ada respon dari peladen. Mohon tunggu dan coba beberapa saat lagi."
youShouldUpgradeClient: "Untuk melihat halaman ini, mohon muat ulang untuk memutakhirkan klienmu."
enterListName: "Masukkan nama daftar"
@@ -103,6 +103,8 @@ renoted: "Telah direnote"
cantRenote: "Postingan ini tidak dapat direnote"
cantReRenote: "Renote tidak dapat direnote"
quote: "Kutip"
+inChannelRenote: "Hanya renote dalam kanal"
+inChannelQuote: "Hanya kutip dalam kanal"
pinnedNote: "Catatan yang disematkan"
pinned: "Sematkan ke profil"
you: "Kamu"
@@ -129,6 +131,7 @@ unblockConfirm: "Apakah kamu yakin ingin membuka blokir akun ini?"
suspendConfirm: "Apakah kamu yakin ingin membekukan akun ini?"
unsuspendConfirm: "Apakah kamu yakin ingin membuka pembekuan akun ini?"
selectList: "Pilih daftar"
+selectChannel: "Pilih kanal"
selectAntenna: "Pilih Antena"
selectWidget: "Pilih gawit"
editWidgets: "Sunting gawit"
@@ -256,6 +259,8 @@ noMoreHistory: "Tidak ada sejarah lagi"
startMessaging: "Mulai mengirim pesan"
nUsersRead: "Dibaca oleh {n}"
agreeTo: "Saya setuju kepada {0}"
+agreeBelow: "Saya setuju dengan di bawah ini"
+basicNotesBeforeCreateAccount: "Catatan penting"
tos: "Syarat dan ketentuan"
start: "Mulai"
home: "Beranda"
@@ -388,13 +393,10 @@ about: "Informasi"
aboutMisskey: "Tentang Misskey"
administrator: "Admin"
token: "Token"
-twoStepAuthentication: "Otentikasi dua faktor"
moderator: "Moderator"
moderation: "Moderasi"
nUsersMentioned: "{n} pengguna disebut"
securityKey: "Kunci keamanan"
-securityKeyName: "Nama kunci"
-registerSecurityKey: "Daftarkan kunci keamanan"
lastUsed: "Terakhir digunakan"
unregister: "Batalkan pendaftaran"
passwordLessLogin: "Setel login tanpa kata sandi"
@@ -412,24 +414,15 @@ markAsReadAllTalkMessages: "Tandai semua pesan telah dibaca"
help: "Bantuan"
inputMessageHere: "Ketik pesan disini"
close: "Tutup"
-group: "Grup"
-groups: "Grup"
-createGroup: "Buat grup"
-ownedGroups: "Grup yang dimiliki"
-joinedGroups: "Grup yang diikuti"
invites: "Undang"
-groupName: "Nama grup"
members: "Anggota"
transfer: "Transfer"
-messagingWithUser: "Obrolan dengan pengguna lain"
-messagingWithGroup: "Obrolan di dalam grup"
title: "Judul"
text: "Teks"
enable: "Aktifkan"
next: "Selanjutnya"
retype: "Masukkan ulang"
noteOf: "Catatan milik {user}"
-inviteToGroup: "Undang ke grup"
quoteAttached: "Dikutip"
quoteQuestion: "Apakah kamu ingin menambahkan kutipan?"
noMessagesYet: "Tidak ada pesan"
@@ -451,19 +444,17 @@ passwordMatched: "Kata sandi sama"
passwordNotMatched: "Kata sandi tidak sama"
signinWith: "Masuk dengan {x}"
signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan salah."
-tapSecurityKey: "Ketuk kunci keamanan kamu"
or: "atau"
language: "Bahasa"
uiLanguage: "Bahasa antarmuka pengguna"
-groupInvited: "Telah diundang ke grup"
aboutX: "Tentang {x}"
emojiStyle: "Gaya emoji"
native: "Native"
disableDrawer: "Jangan gunakan menu bergaya laci"
-youHaveNoGroups: "Kamu tidak memiliki grup"
-joinOrCreateGroup: "Bergabunglah dengan grup atau kamu dapat membuat grupmu sendiri."
noHistory: "Tidak ada riwayat"
signinHistory: "Riwayat masuk"
+enableAdvancedMfm: "Nyalakan MFM tingkat lanjut"
+enableAnimatedMfm: "Nyalakan animasi MFM"
doing: "Sedang berkerja..."
category: "Kategori"
tags: "Tandai"
@@ -833,8 +824,6 @@ deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?"
incorrectPassword: "Kata sandi salah."
voteConfirm: "Konfirmasi suara kamu untuk ({choice})?"
hide: "Sembunyikan"
-leaveGroup: "Keluar grup"
-leaveGroupConfirm: "Apakah kamu yakin untuk keluar dari \"{name}\"?"
useDrawerReactionPickerForMobile: "Tampilkan bilah reaksi sebagai laci di ponsel"
welcomeBackWithName: "Selamat datang kembali, {name}."
clickToFinishEmailVerification: "Mohon klik [{ok}] untuk menyelesaikan verifikasi email."
@@ -860,6 +849,8 @@ failedToFetchAccountInformation: "Gagal untuk mendapatkan informasi akun"
rateLimitExceeded: "Batas sudah terlampaui"
cropImage: "potong gambar"
cropImageAsk: "Ingin memotong gambar?"
+cropYes: "Potong"
+cropNo: "Gunakan apa adanya"
file: "Berkas"
recentNHours: "{n} jam terakhir"
recentNDays: "{n} hari terakhir"
@@ -926,10 +917,87 @@ didYouLikeMisskey: "Apakah kamu mulai menyukai Misskey?"
pleaseDonate: "{host} menggunakan perangkat lunak bebas yaitu Misskey. Kami sangat mengapresiasi sekali donasi dari kamu agar pengembangan Misskey tetap dapat berlanjut!"
roles: "Peran"
role: "Peran"
+normalUser: "Pengguna umum"
+undefined: "Tak terdefinisi"
+assign: "Tetapkan\n"
+unassign: "Batalkan penetapan"
color: "Warna"
+manageCustomEmojis: "Kelola Emoji Kustom"
+youCannotCreateAnymore: "Kamu melewati batas pembuatan."
+cannotPerformTemporary: "Sementara Tidak Tersedia"
+cannotPerformTemporaryDescription: "Aksi ini tidak dapat dilakukan sementara karena melewati batas eksekusi. Mohon tunggu sejenak dan coba lagi."
+preset: "Prasetel"
+selectFromPresets: "Pilih dari prasetel"
+achievements: "Pencapaian"
+gotInvalidResponseError: "Respon peladen tidak valid"
+gotInvalidResponseErrorDescription: "Peladen tidak dapat dijangkau atau sedang dalam perawatan. Mohon coba lagi nanti."
+thisPostMayBeAnnoying: "Catatan ini mungkin dapat mengganggu orang lain."
+thisPostMayBeAnnoyingHome: "Catat ke linimasa beranda"
+thisPostMayBeAnnoyingCancel: "Batalkan"
+thisPostMayBeAnnoyingIgnore: "Tetap catat"
+collapseRenotes: "Tutup renote yang sudah kamu lihat"
+internalServerError: "Kesalahan internal peladen"
+internalServerErrorDescription: "Peladen sedang mengalami galat tak terduga"
+copyErrorInfo: "Salin detil galat"
_achievements:
+ earnedAt: "Terbuka pada"
_types:
+ _notes1:
+ title: "Cus, baru gabung Misskey nih!"
+ description: "Catat catatan pertama kamu"
+ flavor: "Selamat bersenang-senang dengan Misskey!"
+ _notes10:
+ title: "Beberapa catatan"
+ description: "Catat 10 catatan"
+ _notes100:
+ title: "Banyak catatan"
+ description: "Catat 100 catatan"
+ _notes500:
+ title: "Tertumpuk catatan"
+ description: "Catat 500 catatan"
+ _notes1000:
+ title: "Gunung catatan"
+ description: "Catat 1000 catatan"
+ _notes5000:
+ title: "Luapan catatan"
+ description: "Catat 5000 catatan"
+ _notes10000:
+ title: "Catatan super"
+ description: "Catat 10 ribu catatan"
+ _notes20000:
+ title: "Butuh... banyak... catatan..."
+ description: "Catat 20 ribu catatan"
+ _notes30000:
+ title: "Catat, catat, catat !"
+ description: "Catat 30 ribu catatan"
+ _notes40000:
+ title: "Pabrik catatan"
+ description: "Catat 40 ribu catatan"
+ _notes50000:
+ title: "Planet catatan"
+ description: "Catat 50 ribu catatan"
+ _notes60000:
+ title: "Kuasar catatan"
+ description: "Catat 60 ribu catatan"
+ _notes70000:
+ title: "Lubang hitam catatan"
+ description: "Catat 70 ribu catatan"
+ _notes80000:
+ title: "Galaksi catatan"
+ description: "Catat 80 ribu catatan"
+ _notes90000:
+ title: "Semesta catatan"
+ description: "Catat 90 ribu catatan"
+ _notes100000:
+ title: "ALL YOUR NOTE ARE BELONG TO US"
+ description: "Catat 100 ribu catatan"
+ flavor: "Banyak bacot ya kamu."
+ _login3:
+ title: "Pemula I"
+ description: "Login selama 3 hari"
+ flavor: "Mulai hari ini, panggil gue Misskist"
_login7:
+ title: "Pemula II"
description: "Login selama 7 hari"
flavor: "Sudah mulai terbiasa?"
_login15:
@@ -1002,7 +1070,80 @@ _achievements:
_following100:
title: "100 Teman"
description: "Ikuti 100 pengguna lain"
+ _following300:
+ title: "Kelebihan teman"
+ description: "Mengikuti 300 pengguna lain"
+ _followers1:
+ title: "Pengikut pertama"
+ description: "Dapatkan 1 pengikut"
+ _followers10:
+ title: "Ikuti aku!"
+ description: "Dapatkan 10 pengikut"
+ _followers50:
+ title: "Rame-rame"
+ description: "Dapatkan 50 pengikut"
+ _followers100:
+ title: "Terkenal"
+ description: "Dapatkan 100 pengikut"
+ _followers300:
+ title: "Mohon antri satu baris"
+ description: "Dapatkan 300 pengikut"
+ _followers500:
+ title: "Stasiun Informasi"
+ description: "Dapatkan 500 pengikut"
+ _followers1000:
+ title: "Influencer"
+ description: "Dapatkan 1000 pengikut"
+ _collectAchievements30:
+ title: "Kolektor pencapaian"
+ description: "Dapatkan 30 pencapaian"
+ _viewAchievements3min:
+ title: "Suka Pencapaian"
+ description: "Lugat daftar pencapaianmu setidaknya 3 menit"
+ _iLoveMisskey:
+ title: "I Love Misskey"
+ description: "Catat \"I ⤠#Misskey\""
+ flavor: "Tim pengembang misskey sangat mengapresiasi dukungan kamu!"
+ _foundTreasure:
+ title: "Berburu Harta Karun"
+ description: "Kamu telah menemukan harta karun tersembunyi"
+ _client30min:
+ title: "Istirahat pendek"
+ description: "Habiskan waktu 30 menit di Misskey"
+ _noteDeletedWithin1min:
+ title: "Eh, salah coy!"
+ description: "Hapus catatan kurang dari semenit kamu catat"
+ _postedAtLateNight:
+ title: "Nokturnal"
+ description: "Catat catatan di tengah malam hari"
+ flavor: "Udah waktunya boboq."
+ _postedAt0min0sec:
+ title: "Jam ngomong"
+ description: "Catat catatan di jam 00.00"
+ flavor: "Tik Tok Tik Toeeeng"
+ _selfQuote:
+ title: "Rujukan mandiri"
+ description: "Kutip catatanmu sendiri"
+ _htl20npm:
+ title: "Linimasa mengalir"
+ description: "Memiliki linimasa beranda dengan kecepatan melebihi 20 cpm (catatan per menit)"
+ _viewInstanceChart:
+ title: "Analis"
+ description: "Lihat bagan instansimu"
+ _outputHelloWorldOnScratchpad:
+ title: "Halo, dunia!"
+ description: "Munculkan \"hello world\" di Scratchpad"
+ _open3windows:
+ title: "Jendela ganda"
+ description: "Memiliki setidaknya 3 jendela yang terbuka secara bersamaan"
+ _driveFolderCircularReference:
+ title: "Referensi Siklus"
+ description: "Mencoba membuat folder bersarang rekursif di Drive"
+ _reactWithoutRead:
+ title: "Beneran udah dibaca?"
+ description: "Mereaksi catatan dengan 100 karakter panjangnya dalam 3 detik setelah dicatat"
_clickedClickHere:
+ title: "Klik di sini"
description: "Kamu telah mengeklik disini"
_justPlainLucky:
title: "Lagi Beruntung"
@@ -1025,6 +1166,7 @@ _achievements:
_loggedInOnNewYearsDay:
title: "Selamat Tahun Baru!"
description: "Login di hari pertama tahun baru"
+ flavor: "Untuk tahun baru yang berkah bagi instansi ini"
_cookieClicked:
title: "Permainan dimana kamu mengeklik kue"
description: "Mengeklik kue"
@@ -1053,6 +1195,9 @@ _role:
baseRole: "Templat peran"
useBaseValue: "Gunakan nilai templat peran"
chooseRoleToAssign: "Pilih peran yang ditugaskan"
+ iconUrl: "URL ikon"
+ asBadge: "Tampilkan sebagai lencana"
+ descriptionOfAsBadge: "Ikon peran ini akan ditampilkan bersebelahan dengan username pengguna yang memiliki peran ini jika dinyalakan."
canEditMembersByModerator: "Perbolehkan moderator untuk menyunting daftar anggota untuk peran ini"
descriptionOfCanEditMembersByModerator: "Ketika dinyalakan, moderator beserta administrator dapat menugaskan ataupun mencabut pengguna ke peran ini. Ketika dimatikan, hanya administrator saja yang dapat menugaskan pengguna ke peran ini."
priority: "Prioritas"
@@ -1068,6 +1213,36 @@ _role:
canManageCustomEmojis: "Dapat mengelola Emoji kustom"
driveCapacity: "Kapasitas Drive"
pinMax: "Jumlah maksimal catatan yang disematkan"
+ antennaMax: "Jumlah maksimum antena"
+ wordMuteMax: "Jumlah maksimum karakter yang diperbolehkan dalam membisukan kata"
+ webhookMax: "Jumlah maksimum Webhook"
+ clipMax: "Jumlah maksimum Klip"
+ noteEachClipsMax: "Jumlah maksimum catatan di dalam Klip"
+ userListMax: "Jumlah maksimum daftar pengguna"
+ userEachUserListsMax: "Jumlah maksimum pengguna dalam dsftar pengguna"
+ rateLimitFactor: "Batas kecepatan"
+ descriptionOfRateLimitFactor: "Batas kecepatan yang rendah tidak begitu membatasi, batas kecepatan tinggi lebih membatasi. "
+ canHideAds: "Dapat menyembunyikan iklan"
+ _condition:
+ isLocal: "Pengguna lokal"
+ isRemote: "Pengguna remote"
+ createdLessThan: "Telah berlalu kurang dari X sejak pembuatan akun"
+ createdMoreThan: "Telah berlalu lebih dari X sejak pembuatan akun"
+ followersLessThanOrEq: "Memiliki pengikut X atau kurang dari tersebut"
+ followersMoreThanOrEq: "Memiliki pengikut X atau lebih dari tersebut"
+ followingLessThanOrEq: "Mengikuti X pengguna atau kurang dari itu"
+ followingMoreThanOrEq: "Mengikuti X pengguna atau lebih dari itu"
+ and: "Kondisi-AND"
+ or: "Kondisi-OR"
+ not: "Kondisi-NOT"
+_sensitiveMediaDetection:
+ description: "Mengurangi usaha moderasi server dengan mengenali media NSFW srcara otomatis menggunakan Machine Learning. Fungsi ini akan sedikit menaikkan beban peladen."
+ sensitivity: "Sensitivitas deteksi"
+ sensitivityDescription: "Mengurangi sensitivitas akan mengurangi misdeteksi (false positive) sedangkan meningkatkannya akan menambah misdeteksi (false positive)."
+ setSensitiveFlagAutomatically: "Tandai sebagai NSFW"
+ setSensitiveFlagAutomaticallyDescription: "Hasil dari deteksi internal akan dipertahankan meskipun fungsi ini dimatikan."
+ analyzeVideos: "Nyalakan analisis terhadap video"
+ analyzeVideosDescription: "Analisa video sebagai tambahan dari gambar. Ini akan sedikit meningkatkan beban ke peladen."
_emailUnavailable:
used: "Alamat surel ini telah digunakan"
format: "Format tidak valid."
@@ -1111,6 +1286,24 @@ _plugin:
install: "Memasang plugin"
installWarn: "Mohon jangan memasang plugin yang tidak dapat dipercayai."
manage: "Manajemen plugin"
+_preferencesBackups:
+ list: "Cadangan yang dibuat"
+ saveNew: "Simpan cadangan baru"
+ loadFile: "Muat dari berkas"
+ apply: "Terapkan pada perangkat ini"
+ save: "Simpan perubahan"
+ inputName: "Mohon masukkan nama untuk cadangan ini"
+ cannotSave: "Gagal menyimpan"
+ nameAlreadyExists: "Cadangan bernama \"{name}\" sudah ada. Mohon gunakan nama lain."
+ applyConfirm: "Apakah kamu yakin untuk menerapkan cadangan \"{name}\" ke perangkat ini? Pengaturan yang sudah ada di perangkat ini nantinya akan ditimpa."
+ saveConfirm: "Simpan cadangan sebagai {name}?"
+ deleteConfirm: "Hapus cadangan {name}?"
+ renameConfirm: "Ganti cadangan ini dari \"{old}\" ke \"{new}\"?"
+ noBackups: "Tidak ada cadangan. Kamu dapat mencadangkan pengaturanmu di peladen ini dengan menggunakan \"Buat cadangan baru\"."
+ createdAt: "Dibuat pada: {date} {time}"
+ updatedAt: "Diperbarui pada: {date} {time}"
+ cannotLoad: "Gagal memuat"
+ invalidFile: "Format berkas tidak valid"
_registry:
scope: "Lingkup"
key: "Kunci"
@@ -1287,17 +1480,19 @@ _tutorial:
step7_1: "Yay, Selamat! Kamu sudah menyelesaikan tutorial dasar Misskey."
step7_2: "Jika kamu ingin mempelajari lebih lanjut tentang Misskey, cobalah berkunjung ke bagian {help}."
step7_3: "Semoga berhasil dan bersenang-senanglah! 🚀"
+ step8_1: "Yang terakhir, apakah kamu ingin menyalakam pemberitahuan push?"
+ step8_2: "Menyalakan ini akan memungkinkan kamu menerima pemberitahuan untuk sebutan, reaksi, ikuti, dll. Bahkan ketika Misskey sedang tidak dibuka."
step8_3: "Kamu dapat mengganti pengaturan ini nanti."
_2fa:
alreadyRegistered: "Kamu telah mendaftarkan perangkat otentikasi dua faktor."
- registerDevice: "Daftarkan perangkat baru"
- registerKey: "Daftarkan kunci keamanan baru"
step1: "Pertama, pasang aplikasi otentikasi (seperti {a} atau {b}) di perangkat kamu."
step2: "Lalu, pindai kode QR yang ada di layar."
step2Url: "Di aplikasi desktop, masukkan URL berikut:"
step3: "Masukkan token yang telah disediakan oleh aplikasimu untuk menyelesaikan pemasangan."
step4: "Mulai sekarang, upaya login apapun akan meminta token login dari aplikasi otentikasi kamu."
securityKeyInfo: "Kamu dapat memasang otentikasi WebAuthN untuk mengamankan proses login lebih lanjut dengan tidak hanya perangkat keras kunci keamanan yang mendukung FIDO2, namun juga sidik jari atau otentikasi PIN pada perangkatmu."
+ removeKeyConfirm: "Hapus cadangan {name}?"
+ renewTOTPCancel: "Tidak sekarang."
_permissions:
"read:account": "Lihat informasi akun"
"write:account": "Sunting informasi akun"
@@ -1332,18 +1527,20 @@ _permissions:
"read:gallery-likes": "Lihat daftar postingan galeri yang disukai"
"write:gallery-likes": "Sunting daftar postingan galeri yang disukai"
_auth:
+ shareAccessTitle: "Mendapatkan ijin akses aplikasi"
shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?"
shareAccessAsk: "Apakah kamu ingin mengijinkan aplikasi ini untuk mengakses akun kamu?"
+ permission: "{name} meminta ijin berikut"
permissionAsk: "Aplikasi ini membutuhkan beberapa ijin, yaitu:"
pleaseGoBack: "Mohon kembali ke aplikasi kamu"
callback: "Mengembalikan kamu ke aplikasi"
denied: "Akses ditolak"
+ pleaseLogin: "Mohon masuk untuk otorisasi aplikasi."
_antennaSources:
all: "Semua catatan"
homeTimeline: "Catatan dari pengguna yang diikuti"
users: "Catatan dari pengguna tertentu"
userList: "Catatan dari daftar tertentu"
- userGroup: "Catatan dari pengguna dalam grup yang ditentukan"
_weekday:
sunday: "Minggu"
monday: "Senin"
@@ -1418,8 +1615,6 @@ _visibility:
followersDescription: "Catat ke pengikut saja"
specified: "Langsung"
specifiedDescription: "Catat ke pengguna yang ditentukan saja"
- localOnly: "Hanya lokal"
- localOnlyDescription: "Hanya dapat dilihat di instansi lokal"
_postForm:
replyPlaceholder: "Balas ke catatan ini..."
quotePlaceholder: "Kutip catatan ini..."
@@ -1557,12 +1752,9 @@ _notification:
youGotReply: "{name} membalas kamu"
youGotQuote: "{name} mengutip kamu"
youRenoted: "{name} me-renote kamu"
- youGotMessagingMessageFromUser: "{name} mengirimi kamu pesan"
- youGotMessagingMessageFromGroup: "Sebuah pesan telah dikirim ke grup {name}"
youWereFollowed: "Mengikuti kamu"
youReceivedFollowRequest: "Kamu menerima permintaan mengikuti"
yourFollowRequestAccepted: "Permintaan mengikuti kamu telah diterima"
- youWereInvitedToGroup: "Telah diundang ke grup"
pollEnded: "Hasil Kuesioner telah keluar"
unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Pembaruan notifikasi dorong"
@@ -1578,7 +1770,6 @@ _notification:
pollEnded: "Jajak pendapat berakhir"
receiveFollowRequest: "Permintaan mengikuti diterima"
followRequestAccepted: "Permintaan mengikuti disetujui"
- groupInvited: "Diundang ke grup"
app: "Pemberitahuan dari aplikasi"
_actions:
followBack: "Ikuti Kembali"
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index fbee5d9719..0ce65eea85 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -11,7 +11,7 @@ password: "Password"
forgotPassword: "Hai dimenticato la password?"
fetchingAsApObject: "Recuperando dal Fediverso..."
ok: "OK"
-gotIt: "Ho capito"
+gotIt: "ok!"
cancel: "Annulla"
noThankYou: "No grazie"
enterUsername: "Inserisci un nome utente"
@@ -46,7 +46,7 @@ copyContent: "Copia il contenuto"
copyLink: "Copia il link"
delete: "Elimina"
deleteAndEdit: "Elimina e modifica"
-deleteAndEditConfirm: "Vuoi davvero cancellare questa nota e scriverla di nuovo? Verrano eliminate anche tutte le reazioni, Rinote e risposte collegate."
+deleteAndEditConfirm: "Vuoi davvero cancellare questa nota e scriverla di nuovo? Verranno eliminate anche tutte le reazioni, rinote e risposte collegate."
addToList: "Aggiungi alla lista"
sendMessage: "Invia messaggio"
copyRSS: "Copia RSS"
@@ -75,7 +75,7 @@ lists: "Liste"
noLists: "Nessuna lista"
note: "Nota"
notes: "Note"
-following: "Follows"
+following: "LÇ segui"
followers: "Followers"
followsYou: "Ti segue"
createList: "Aggiungi una nuova lista"
@@ -84,12 +84,12 @@ error: "Errore"
somethingHappened: "Si è verificato un problema"
retry: "Riprova"
pageLoadError: "Caricamento pagina non riuscito. "
-pageLoadErrorDescription: "Questo viene normalmente causato dalla rete o dalla cache del browser. Si prega di pulire la cache, o di attendere e riprovare più tardi."
+pageLoadErrorDescription: "Questo problema viene normalmente causato da errori di rete o dalla cache del browser. Si prega di pulire la cache, o di attendere e riprovare più tardi."
serverIsDead: "Il server non risponde. Si prega di attendere e riprovare più tardi."
youShouldUpgradeClient: "Per visualizzare la pagina è necessario aggiornare il client alla nuova versione e ricaricare."
enterListName: "Nome della lista"
privacy: "Privacy"
-makeFollowManuallyApprove: "Richiedi di approvare i follower manualmente"
+makeFollowManuallyApprove: "Approva i follower manualmente"
defaultNoteVisibility: "Privacy predefinita delle note"
follow: "Segui"
followRequest: "Richiesta di follow"
@@ -103,6 +103,8 @@ renoted: "Rinotato!"
cantRenote: "È impossibile rinotare questa nota."
cantReRenote: "È impossibile rinotare una Rinota."
quote: "Cita"
+inChannelRenote: "Rinota nel canale"
+inChannelQuote: "Cita nel canale"
pinnedNote: "Nota fissata"
pinned: "Fissa sul profilo"
you: "Tu"
@@ -119,7 +121,7 @@ markAsSensitive: "Segna come sensibile"
unmarkAsSensitive: "Segna come non sensibile"
enterFileName: "Nome del file"
mute: "Silenzia"
-unmute: "Riattiva"
+unmute: "Riattiva l'audio"
block: "Blocca"
unblock: "Sblocca"
suspend: "Sospendi"
@@ -129,6 +131,7 @@ unblockConfirm: "Vuoi davvero sbloccare il profilo?"
suspendConfirm: "Vuoi sospendere questo profilo?"
unsuspendConfirm: "Vuoi revocare la sospensione si questo profilo?"
selectList: "Seleziona una lista"
+selectChannel: "Seleziona canale"
selectAntenna: "Scegli un'antenna"
selectWidget: "Seleziona il riquadro"
editWidgets: "Modifica i riquadri"
@@ -140,7 +143,7 @@ emojiName: "Nome dell'emoji"
emojiUrl: "URL dell'emoji"
addEmoji: "Aggiungi un emoji"
settingGuide: "Configurazione suggerita"
-cacheRemoteFiles: "Memorizzazione nella cache dei file remoti"
+cacheRemoteFiles: "Memorizza i file remoti nella cache"
cacheRemoteFilesDescription: "Disabilitando questa opzione, i file remoti verranno linkati direttamente senza essere memorizzati nella cache. Sarà possibile risparmiare spazio di archiviazione sul server, ma il traffico aumenterà in quanto non verranno generate anteprime."
flagAsBot: "Io sono un robot"
flagAsBotDescription: "Attiva questo campo se il profilo esegue principalmente operazioni automatiche. L'attivazione segnala agli altri sviluppatori come comportarsi per evitare catene d’interazione infinite con altri bot. I sistemi interni di Misskey si adegueranno al fine di trattare questo profilo come bot."
@@ -151,7 +154,7 @@ flagShowTimelineRepliesDescription: "Se è attiva, la timeline mostra le rispost
autoAcceptFollowed: "Accetta automaticamente le richieste di follow da utenti che già segui"
addAccount: "Aggiungi profilo"
loginFailed: "Accesso non riuscito"
-showOnRemote: "Sfoglia sull'istanza remota"
+showOnRemote: "Visualizza sull'istanza remota"
general: "Generali"
wallpaper: "Sfondo"
setWallpaper: "Imposta sfondo"
@@ -206,14 +209,14 @@ intro: "L'installazione di Misskey è terminata! Si prega di creare il profilo a
done: "Fine"
processing: "In elaborazione"
preview: "Anteprima"
-default: "Predefinito"
+default: "Medio"
defaultValueIs: "Predefinito: {value}"
noCustomEmojis: "Nessun emoji"
noJobs: "Nessun lavoro"
federating: "Federazione"
blocked: "Bloccato"
suspended: "Sospensione"
-all: "Tutti"
+all: "Tutte"
subscribing: "Iscrizione"
publishing: "Pubblicazione"
notResponding: "Nessuna risposta"
@@ -231,7 +234,7 @@ more: "Di più!"
featured: "Tendenze"
usernameOrUserId: "Nome utente o ID utente"
noSuchUser: "Nessun utente trovato"
-lookup: "Cercare"
+lookup: "Cerca"
announcements: "Annunci"
imageUrl: "URL dell'immagine"
remove: "Elimina"
@@ -256,6 +259,8 @@ noMoreHistory: "Non c'è più cronologia da visualizzare"
startMessaging: "Nuovo messaggio"
nUsersRead: "Letto da {n} persone"
agreeTo: "Sono d'accordo con {0}"
+agreeBelow: "Accetto quanto riportato sotto"
+basicNotesBeforeCreateAccount: "Note importanti"
tos: "Termini di servizio"
start: "Inizia!"
home: "Home"
@@ -283,7 +288,7 @@ selectFolders: "Seleziona cartella"
renameFile: "Rinomina file"
folderName: "Nome della cartella"
createFolder: "Nuova cartella"
-renameFolder: "Rinominare cartella"
+renameFolder: "Rinomina cartella"
deleteFolder: "Elimina cartella"
addFile: "Allega"
emptyDrive: "Il Drive è vuoto"
@@ -300,7 +305,7 @@ avatar: "Foto del profilo"
banner: "Intestazione"
nsfw: "Contenuti sensibili"
whenServerDisconnected: "Quando la connessione col server è persa"
-disconnectedFromServer: "Disconness@ dal server"
+disconnectedFromServer: "Il server si è disconnesso"
reload: "Ricarica"
doNothing: "Nessun'azione"
reloadConfirm: "Vuoi ricaricare?"
@@ -311,9 +316,9 @@ reject: "Rifiuta"
normal: "Normale"
instanceName: "Nome dell'istanza"
instanceDescription: "Descrizione dell'istanza"
-maintainerName: "Nome dell'Amministratore"
-maintainerEmail: "Indirizzo e-mail dell'Amministratore"
-tosUrl: "Termini di servizio URL"
+maintainerName: "Nome dell'amministratore"
+maintainerEmail: "Indirizzo e-mail dell'amministratore"
+tosUrl: "URL dei termini del servizio e della privacy"
thisYear: "Anno"
thisMonth: "Mese"
today: "Oggi"
@@ -322,13 +327,13 @@ monthX: "{month}"
yearX: "{year}"
pages: "Pagine"
integration: "App collegate"
-connectService: "Connessione"
-disconnectService: "Disconnessione "
-enableLocalTimeline: "Abilita Timeline locale"
-enableGlobalTimeline: "Abilita Timeline federata"
+connectService: "Connetti"
+disconnectService: "Disconnetti"
+enableLocalTimeline: "Abilita la timeline locale"
+enableGlobalTimeline: "Abilita la timeline federata"
disablingTimelinesInfo: "Anche disabilitandole, gli Amministratori e i Moderatori potranno comunque accedervi."
registration: "Iscriviti"
-enableRegistration: "Permettere nuove registrazioni"
+enableRegistration: "Consenti a chiunque di registrarsi"
invite: "Invita"
driveCapacityPerLocalAccount: "Capienza del Drive per profilo locale"
driveCapacityPerRemoteAccount: "Capienza del Drive per profilo remoto"
@@ -388,13 +393,10 @@ about: "Informazioni"
aboutMisskey: "Informazioni di Misskey"
administrator: "Amministratore"
token: "Token"
-twoStepAuthentication: "Autenticazione a due fattori"
moderator: "Moderatore"
moderation: "moderazione"
nUsersMentioned: "{n} profili menzionati"
securityKey: "Chiave di sicurezza"
-securityKeyName: "Nome della chiave"
-registerSecurityKey: "Registra una chiave di sicurezza"
lastUsed: "Ultima attività"
unregister: "Annulla l'iscrizione"
passwordLessLogin: "Accedi senza password"
@@ -412,24 +414,15 @@ markAsReadAllTalkMessages: "Segna tutte le chat come lette"
help: "Guida"
inputMessageHere: "Scrivi messaggio qui"
close: "Chiudi"
-group: "Gruppo"
-groups: "Gruppi"
-createGroup: "Nuovo gruppo"
-ownedGroups: "I miei gruppi"
-joinedGroups: "Gruppi a cui mi sono unit@"
invites: "Inviti"
-groupName: "Nome del gruppo"
members: "Membri"
transfer: "Trasferisci"
-messagingWithUser: "Iniziare una chat con un altr@ utente"
-messagingWithGroup: "Chattare in gruppo"
title: "Titolo"
text: "Testo"
enable: "Abilita"
next: "Avanti"
retype: "Conferma"
noteOf: "Note di {user}"
-inviteToGroup: "Invitare al gruppo"
quoteAttached: "Citazione allegata"
quoteQuestion: "Vuoi aggiungere una citazione?"
noMessagesYet: "Ancora nessuna chat"
@@ -451,19 +444,17 @@ passwordMatched: "Corretta"
passwordNotMatched: "Le password non corrispondono."
signinWith: "Accedi con {x}"
signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente."
-tapSecurityKey: "Premi la chiave di sicurezza"
or: "oppure"
language: "Lingua"
uiLanguage: "Lingua di visualizzazione dell'interfaccia"
-groupInvited: "Invitat@ al gruppo"
aboutX: "Informazioni su {x}"
emojiStyle: "Stile emoji"
native: "Nativo"
disableDrawer: "Non mostrare il menù sul drawer"
-youHaveNoGroups: "Nessun gruppo"
-joinOrCreateGroup: "Puoi creare il tuo gruppo o essere invitat@ a gruppi che già esistono."
noHistory: "Nessuna cronologia"
signinHistory: "Storico degli accessi al profilo"
+enableAdvancedMfm: "Attiva MFM avanzati"
+enableAnimatedMfm: "Attiva MFM animati"
doing: "In corso..."
category: "Categoria"
tags: "Tag"
@@ -473,7 +464,7 @@ existingAccount: "Profilo esistente"
regenerate: "Generare di nuovo"
fontSize: "Dimensione carattere"
noFollowRequests: "Non hai alcuna richiesta di follow"
-openImageInNewTab: "Aprire immagini in una nuova scheda"
+openImageInNewTab: "Apri le immagini in un nuovo tab"
dashboard: "Pannello di controllo"
local: "Locale"
remote: "Remoto"
@@ -602,7 +593,7 @@ smtpPass: "Password"
emptyToDisableSmtpAuth: "Lasciare il nome utente e la password vuoti per disabilitare la verifica SMTP"
smtpSecure: "Usare la porta SSL/TLS implicito per le connessioni SMTP"
smtpSecureInfo: "Disabilitare quando è attivo STARTTLS."
-testEmail: "Testare la consegna di posta elettronica"
+testEmail: "Testa la consegna di posta elettronica"
wordMute: "Filtri parole"
regexpError: "errore regex"
regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
@@ -615,7 +606,7 @@ metrics: "Statistiche"
overview: "Anteprima"
logs: "Log"
delayed: "Ritardo"
-database: "Base di dati"
+database: "Base dati"
channel: "Canale"
create: "Crea"
notificationSetting: "Impostazioni notifiche"
@@ -704,7 +695,7 @@ narrow: "Stretto"
reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricamento della pagina. Vuoi ricaricare adesso?"
needReloadToApply: "È necessario riavviare per rendere effettive le modifiche."
showTitlebar: "Visualizza la barra del titolo"
-clearCache: "Svuota cache"
+clearCache: "Svuota la cache"
onlineUsersCount: "{n} utenti online"
nUsers: "{n} utenti"
nNotes: "{n}Note"
@@ -729,9 +720,9 @@ currentVersion: "Versione attuale"
latestVersion: "Ultima versione"
youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
-usageAmount: "In utilizzo"
+usageAmount: "In uso"
capacity: "Capacità"
-inUse: "In utilizzo"
+inUse: "In uso"
editCode: "Modifica codice"
apply: "Applica"
receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
@@ -817,7 +808,7 @@ breakFollow: "Smetti di seguire"
itsOn: "Abilitato"
itsOff: "Disabilitato"
emailRequiredForSignup: "L'ndirizzo e-mail è obbligatorio per registrarsi"
-unread: "Non letto"
+unread: "Non lette"
filter: "Filtri"
controlPanel: "Pannello di controllo"
manageAccounts: "Gestisci i profili"
@@ -833,8 +824,6 @@ deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?"
incorrectPassword: "La password è errata."
voteConfirm: "Votare per「{choice}�"
hide: "Nascondere"
-leaveGroup: "Esci dal gruppo"
-leaveGroupConfirm: "Uscire da「{name}�"
useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile"
welcomeBackWithName: "Ciao, {name}! Eccoti di nuovo!"
clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo email."
@@ -857,9 +846,11 @@ oneDay: "1 giorno"
oneWeek: "1 settimana"
reflectMayTakeTime: "Potrebbe essere necessario un po' di tempo perché ciò abbia effetto."
failedToFetchAccountInformation: "Impossibile recuperare le informazioni sul profilo"
-rateLimitExceeded: "Superato il limite di velocità."
-cropImage: "Ritaglio dell'immagine"
-cropImageAsk: "Si desidera ritagliare l'immagine?"
+rateLimitExceeded: "Superato il limite di richieste."
+cropImage: "Ritaglia l'immagine"
+cropImageAsk: "Vuoi ritagliare l'immagine?"
+cropYes: "Ritaglia"
+cropNo: "Non ritagliare"
file: "Allegati"
recentNHours: "Ultime {n} ore"
recentNDays: "Ultimi {n} giorni"
@@ -938,6 +929,16 @@ cannotPerformTemporaryDescription: "L'attività non può essere svolta, poiché
preset: "Preimpostato"
selectFromPresets: "Seleziona preimpostato"
achievements: "Obiettivi raggiunti"
+gotInvalidResponseError: "Risposta del server non valida"
+gotInvalidResponseErrorDescription: "Il server potrebbe essere irraggiungibile o in manutenzione. Riprova più tardi."
+thisPostMayBeAnnoying: "Questa nota potrebbe essere offensiva"
+thisPostMayBeAnnoyingHome: "Pubblica sulla timeline principale"
+thisPostMayBeAnnoyingCancel: "Annulla"
+thisPostMayBeAnnoyingIgnore: "Pubblica lo stesso"
+collapseRenotes: "Comprimi i Rinota già letti"
+internalServerError: "Errore interno del server"
+internalServerErrorDescription: "Si è verificato un errore imprevisto all'interno del server"
+copyErrorInfo: "Copia le informazioni sull'errore"
_achievements:
earnedAt: "Data di conseguimento"
_types:
@@ -993,53 +994,53 @@ _achievements:
flavor: "Hai molto da scrivere?"
_login3:
title: "Principiante I"
- description: "Accedi per un totale di 3 giorni"
+ description: "Hai totalizzato 3 accessi!"
flavor: "Da oggi, chiamatemi Misskist"
_login7:
title: "Principiante II"
- description: "Accedi per un totale di 7 giorni"
+ description: "Hai totalizzato 7 accessi!"
flavor: "Ti sembra di avere la situazione sotto controllo?"
_login15:
title: "Principiante III"
- description: "Accedi per un totale di 15 giorni"
+ description: "Hai totalizzato 15 accessi!"
_login30:
title: "Misskist I"
- description: "Accedi per un totale di 30 giorni"
+ description: "Hai totalizzato 30 accessi!"
_login60:
title: "Misskeist II"
- description: "Accedi per un totale di 60 giorni"
+ description: "Hai totalizzato 60 accessi!"
_login100:
title: "Misskeist III"
- description: "Accedi per un totale di 100 giorni"
+ description: "Hai totalizzato 100 accessi!"
flavor: "Violent Misskeist"
_login200:
- title: "Regolare I"
- description: "Accedi per un totale di 200 giorni"
+ title: "Regolare I livello"
+ description: "Hai totalizzato 200 accessi!"
_login300:
- title: "Regolare II"
- description: "Accedi per un totale di 300 giorni"
+ title: "Regolare II livello"
+ description: "Hai totalizzato 300 accessi!"
_login400:
- title: "Regolare III"
- description: "Accedi per un totale di 400 giorni"
+ title: "Regolare III livello"
+ description: "Hai totalizzato 400 accessi!"
_login500:
- title: "Professionista I"
- description: "Accedi per un totale di 500 giorni"
+ title: "Professionista I livello"
+ description: "Hai totalizzato 500 accessi!"
flavor: "Amici cari, mi piacciono le Note"
_login600:
- title: "Professionista II"
- description: "Accedi per un totale di 600 giorni"
+ title: "Professionista II livello"
+ description: "Hai totalizzato 600 accessi!"
_login700:
- title: "Professionista III"
- description: "Accedi per un totale di 700 giorni"
+ title: "Professionista III livello"
+ description: "Hai totalizzato 700 accessi!"
_login800:
- title: "Maestro di Note I"
- description: "Accedi per un totale di 800 giorni"
+ title: "Maestro di Note I livello"
+ description: "Hai totalizzato 800 accessi!"
_login900:
- title: "Maestro di Note II"
- description: "Accedi per un totale di 900 giorni"
+ title: "Maestro di Note II livello"
+ description: "Hai totalizzato 900 accessi!"
_login1000:
- title: "Maestro di Note III"
- description: "Accedi per un totale di 1.000 giorni"
+ title: "Maestro di Note III livello"
+ description: "Hai totalizzato 1000 accessi!"
flavor: "Grazie per aver usato Misskey!"
_noteClipped1:
title: "Devo clippare!"
@@ -1051,7 +1052,7 @@ _achievements:
title: "Fornitura stelline"
description: "Qualcuno ha preferito una delle tue Note"
_profileFilled:
- title: "Perfettamente"
+ title: "Preparazione perfetta!"
description: "Imposta il tuo profilo"
_markedAsCat:
title: "Io sono un gatto"
@@ -1459,10 +1460,10 @@ _time:
_tutorial:
title: "Come usare Misskey"
step1_1: "Eccoci!"
- step1_2: "Questa pagina si chiama una \" Timeline \". Mostra in ordine cronologico le \" note \" delle persone che segui."
- step1_3: "Attualmente la tua Timeline è vuota perché non segui alcun profilo e non hai pubblicato alcuna nota ancora."
+ step1_2: "Questa pagina si chiama \"Timeline \" e mostra in ordine cronologico le \"note\" delle persone che segui."
+ step1_3: "Attualmente la tua Timeline è vuota perché non segui alcun profilo e non hai ancora pubblicato alcuna nota."
step2_1: "Prima di scrivere una «Nota» o di seguire altri profili, prepara il tuo profilo!"
- step2_2: "Aggiungere qualche informazione su di te aumenterà le tue possibilità di essere seguit@ da altre persone. "
+ step2_2: "Se aggiungi informazioni personali aumenterai le tue possibilità di essere seguit@ da altre persone. "
step3_1: "Hai finito di impostare il tuo profilo?"
step3_2: "Ora puoi pubblicare una «Nota». Proviamo subito! Premi il bottone con l'icona «penna» per iniziare a scrivere in una finestra di dialogo. "
step3_3: "Scritto il testo della nota, puoi pubblicarla premendo il pulsante nella parte superiore destra della finestra di dialogo."
@@ -1481,24 +1482,24 @@ _tutorial:
step7_3: "Da ultimo, buon divertimento su Misskey! 🚀"
step8_1: "Per concludere, vuoi attivare le notifiche push?"
step8_2: "Attivandole, otterrai notifiche di follow, reazioni e menzioni anche quando Misskey è chiuso."
- step8_3: "Puoi anche modificare questa impostazione successivamente."
+ step8_3: "Potrai modificare questa impostazione."
_2fa:
alreadyRegistered: "La configurazione è stata già completata."
- registerDevice: "Aggiungi dispositivo"
- registerKey: "Chiave di registro."
step1: "Innanzitutto, installare sul dispositivo un'applicazione di autenticazione come {a} o {b}."
step2: "Quindi, scansionare il codice QR visualizzato con l'app."
step2Url: "Nell'applicazione desktop inserire il seguente URL: "
step3: "Inserite il token visualizzato nell'app e il gioco è fatto."
step4: "D'ora in poi, quando si accede, si inserisce il token nello stesso modo."
securityKeyInfo: "È possibile impostare il dispositivo per accedere utilizzando una chiave di sicurezza hardware che supporta FIDO2 o un'impronta digitale o un PIN sul dispositivo."
+ removeKeyConfirm: "Vuoi davvero eliminare \"{name}\"?"
+ renewTOTPCancel: "No grazie"
_permissions:
- "read:account": "Visualizzare le informazioni sul profilo"
- "write:account": "Modificare le informazioni sul profilo"
+ "read:account": "Visualizza le informazioni sul profilo"
+ "write:account": "Modifica le informazioni sul profilo"
"read:blocks": "Visualizza i profili bloccati"
"write:blocks": "Gestisci i profili bloccati"
- "read:drive": "Aprire il Drive"
- "write:drive": "Gestire il Drive"
+ "read:drive": "Apri il Drive"
+ "write:drive": "Gestisci il Drive"
"read:favorites": "Visualizza i tuoi preferiti"
"write:favorites": "Gestisci i tuoi preferiti"
"read:following": "Vedi le informazioni di follow"
@@ -1526,18 +1527,20 @@ _permissions:
"read:gallery-likes": "Visualizza i contenuti della galleria."
"write:gallery-likes": "Manipolazione dei \"Mi piace\" della galleria."
_auth:
+ shareAccessTitle: "Permessi dell'applicazione"
shareAccess: "Vuoi autorizzare {name} ad accedere al tuo profilo?"
shareAccessAsk: "Vuoi autorizzare questa App ad accedere al tuo profilo?"
+ permission: "{name} richiede i permessi seguenti"
permissionAsk: "Questa app richiede le seguenti autorizzazioni:"
pleaseGoBack: "Si prega di ritornare sulla app"
callback: "Ritornando sulla app"
denied: "Accesso negato"
+ pleaseLogin: "Per favore accedi al tuo account per cambiare i permessi dell'applicazione"
_antennaSources:
all: "Tutte le note"
homeTimeline: "Note dagli utenti che segui"
users: "Note dagli utenti selezionati"
userList: "Note dagli utenti della lista selezionata"
- userGroup: "Note dagli utenti del gruppo selezionato"
_weekday:
sunday: "Domenica"
monday: "Lunedì"
@@ -1610,21 +1613,19 @@ _visibility:
homeDescription: "Visibile solo sulla timeline \"Home\""
followers: "Followers"
followersDescription: "Visibile solo per i tuoi followers"
- specified: "Diretta"
+ specified: "Nota diretta"
specifiedDescription: "Visibile solo ai profili menzionati"
- localOnly: "Soltanto locale"
- localOnlyDescription: "Non visibile ai profili remoti"
_postForm:
- replyPlaceholder: "Nota la tua risposta.."
- quotePlaceholder: "Cita Nota..."
- channelPlaceholder: "Pubblica in canale"
+ replyPlaceholder: "Rispondi a questa nota..."
+ quotePlaceholder: "Cita questa nota..."
+ channelPlaceholder: "Pubblica sul canale..."
_placeholders:
- a: "Che succede?"
- b: "È successo qualcosa?"
- c: "Che cos'hai in mente?"
+ a: "Come va?"
+ b: "Hai qualcosa da raccontare? Inizia pure..."
+ c: "Stai pensando a qualcosa?"
d: "Vuoi dire qualcosa?"
- e: "Scrivi qualcosa qui"
- f: "Aspettando che scriva..."
+ e: "Puoi scrivere qui..."
+ f: "Inizia pure a scrivere..."
_profile:
name: "Nome"
username: "Nome utente"
@@ -1655,9 +1656,9 @@ _charts:
notesIncDec: "Variazione del numero di note"
localNotesIncDec: "Variazione del numero di note locali"
remoteNotesIncDec: "Variazione del numero di note distanti"
- notesTotal: "Conteggio totale di note"
+ notesTotal: "Numero di note in totale"
filesIncDec: "Variazione del numero dei file"
- filesTotal: "Numero totale di file"
+ filesTotal: "Numero di file in totale"
storageUsageIncDec: "Variazione dell'utilizzo dell'immagazzinamento"
storageUsageTotal: "Utilizzo totale dell'immagazzinamento"
_instanceCharts:
@@ -1749,14 +1750,11 @@ _notification:
fileUploaded: "File caricato correttamente"
youGotMention: "{name} ti ha menzionato"
youGotReply: "{name} ti ha risposto"
- youGotQuote: "{name} ha citato il tuo Nota e ha detto"
+ youGotQuote: "{name} ha citato la tua Nota e ha detto"
youRenoted: "{name} ha rinotato"
- youGotMessagingMessageFromUser: "{name} ti ha mandato un messaggio"
- youGotMessagingMessageFromGroup: "{name} ti ha mandato un messaggio nella chat"
youWereFollowed: "Ha iniziato a seguirti"
youReceivedFollowRequest: "Hai ricevuto una richiesta di follow"
yourFollowRequestAccepted: "La tua richiesta di follow è stata accettata"
- youWereInvitedToGroup: "Invitat@ al gruppo"
pollEnded: "Risultati del sondaggio."
unreadAntennaNote: "Antenna {name}"
emptyPushNotificationMessage: "Le notifiche push sono state aggiornate."
@@ -1772,7 +1770,6 @@ _notification:
pollEnded: "Sondaggio chiuso."
receiveFollowRequest: "Richiesta di follow ricevuta"
followRequestAccepted: "Richiesta di follow accettata"
- groupInvited: "Invito a un gruppo"
app: "Notifiche da applicazioni"
_actions:
followBack: "Segui"
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index b1f484f6b2..73f9718aac 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -392,17 +392,20 @@ userList: "リスト"
about: "情報"
aboutMisskey: "Misskeyã«ã¤ã„ã¦"
administrator: "管ç†è€…"
-token: "トークン"
-twoStepAuthentication: "二段階èªè¨¼"
+token: "確èªã‚³ãƒ¼ãƒ‰"
+2fa: "二è¦ç´ èªè¨¼"
+totp: "èªè¨¼ã‚¢ãƒ—リ"
+totpDescription: "èªè¨¼ã‚¢ãƒ—リを使ã£ã¦ãƒ¯ãƒ³ã‚¿ã‚¤ãƒ ãƒ‘スワードを入力"
moderator: "モデレーター"
moderation: "モデレーション"
nUsersMentioned: "{n}äººãŒæŠ•ç¨¿"
+securityKeyAndPasskey: "セキュリティキー・パスキー"
securityKey: "セキュリティキー"
-securityKeyName: "キーã®åå‰"
-registerSecurityKey: "セキュリティキーを登録ã™ã‚‹"
lastUsed: "最後ã®ä½¿ç”¨"
+lastUsedAt: "最後ã®ä½¿ç”¨: {t}"
unregister: "登録を解除"
-passwordLessLogin: "パスワード無ã—ログイン"
+passwordLessLogin: "パスワードレスログイン"
+passwordLessLoginDescription: "パスワードを使用ã›ãšã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã‚„パスキーãªã©ã®ã¿ã§ãƒ­ã‚°ã‚¤ãƒ³ã—ã¾ã™"
resetPassword: "パスワードをリセット"
newPasswordIs: "æ–°ã—ã„パスワードã¯ã€Œ{password}ã€ã§ã™"
reduceUiAnimation: "UIã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’減らã™"
@@ -447,7 +450,6 @@ passwordMatched: "一致ã—ã¾ã—ãŸ"
passwordNotMatched: "一致ã—ã¦ã„ã¾ã›ã‚“"
signinWith: "{x}ã§ãƒ­ã‚°ã‚¤ãƒ³"
signinFailed: "ログインã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ユーザーåã¨ãƒ‘スワードを確èªã—ã¦ãã ã•ã„。"
-tapSecurityKey: "セキュリティキーã«ã‚¿ãƒƒãƒ"
or: "ã‚‚ã—ãã¯"
language: "言語"
uiLanguage: "UIã®è¡¨ç¤ºè¨€èªž"
@@ -810,6 +812,7 @@ lastCommunication: "ç›´è¿‘ã®é€šä¿¡"
resolved: "解決済ã¿"
unresolved: "未解決"
breakFollow: "フォロワーを解除"
+breakFollowConfirm: "フォロワー解除ã—ã¾ã™ã‹ï¼Ÿ"
itsOn: "オンã«ãªã£ã¦ã„ã¾ã™"
itsOff: "オフã«ãªã£ã¦ã„ã¾ã™"
emailRequiredForSignup: "アカウント登録ã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å¿…é ˆã«ã™ã‚‹"
@@ -944,6 +947,10 @@ collapseRenotes: "見ãŸã“ã¨ã®ã‚ã‚‹Renoteã‚’çœç•¥ã—ã¦è¡¨ç¤º"
internalServerError: "サーãƒãƒ¼å†…部エラー"
internalServerErrorDescription: "サーãƒãƒ¼å†…部ã§äºˆæœŸã—ãªã„エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
copyErrorInfo: "エラー情報をコピー"
+joinThisServer: "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«ç™»éŒ²ã™ã‚‹"
+exploreOtherServers: "ä»–ã®ã‚µãƒ¼ãƒãƒ¼ã‚’探ã™"
+letsLookAtTimeline: "タイムラインを見ã¦ã¿ã‚‹"
+disableFederationWarn: "連åˆãŒç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚無効ã«ã—ã¦ã‚‚投稿ãŒéžå…¬é–‹ã«ã¯ãªã‚Šã¾ã›ã‚“。ã»ã¨ã‚“ã©ã®å ´åˆã€ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“。"
_achievements:
earnedAt: "ç²å¾—日時"
@@ -1483,6 +1490,7 @@ _ago:
weeksAgo: "{n}週間å‰"
monthsAgo: "{n}ヶ月å‰"
yearsAgo: "{n}å¹´å‰"
+ invalid: "ã‚りã¾ã›ã‚“"
_time:
second: "ç§’"
@@ -1519,14 +1527,29 @@ _tutorial:
_2fa:
alreadyRegistered: "æ—¢ã«è¨­å®šã¯å®Œäº†ã—ã¦ã„ã¾ã™ã€‚"
- registerDevice: "デãƒã‚¤ã‚¹ã‚’登録"
- registerKey: "キーを登録"
+ registerTOTP: "èªè¨¼ã‚¢ãƒ—リã®è¨­å®šã‚’é–‹å§‹"
+ passwordToTOTP: "パスワードを入力ã—ã¦ãã ã•ã„"
step1: "ã¾ãšã€{a}ã‚„{b}ãªã©ã®èªè¨¼ã‚¢ãƒ—リをãŠä½¿ã„ã®ãƒ‡ãƒã‚¤ã‚¹ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¾ã™ã€‚"
step2: "次ã«ã€è¡¨ç¤ºã•れã¦ã„ã‚‹QRコードをアプリã§ã‚¹ã‚­ãƒ£ãƒ³ã—ã¾ã™ã€‚"
- step2Url: "デスクトップアプリã§ã¯æ¬¡ã®URLを入力ã—ã¾ã™:"
- step3: "アプリã«è¡¨ç¤ºã•れã¦ã„るトークンを入力ã—ã¦å®Œäº†ã§ã™ã€‚"
- step4: "ã“れã‹ã‚‰ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãã‚‚ã€åŒã˜ã‚ˆã†ã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã—ã¾ã™ã€‚"
- securityKeyInfo: "FIDO2をサãƒãƒ¼ãƒˆã™ã‚‹ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã‚‚ã—ãã¯ç«¯æœ«ã®æŒ‡ç´‹èªè¨¼ã‚„PINを使用ã—ã¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã‚ˆã†ã«è¨­å®šã§ãã¾ã™ã€‚"
+ step2Click: "QRコードをクリックã™ã‚‹ã¨ã€ãŠä½¿ã„ã®ç«¯æœ«ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹èªè¨¼ã‚¢ãƒ—リやキーリングã«ç™»éŒ²ã§ãã¾ã™ã€‚"
+ step2Url: "デスクトップアプリã§ã¯æ¬¡ã®URIを入力ã—ã¾ã™:"
+ step3Title: "確èªã‚³ãƒ¼ãƒ‰ã‚’入力"
+ step3: "アプリã«è¡¨ç¤ºã•れã¦ã„る確èªã‚³ãƒ¼ãƒ‰ï¼ˆãƒˆãƒ¼ã‚¯ãƒ³ï¼‰ã‚’入力ã—ã¦å®Œäº†ã§ã™ã€‚"
+ step4: "ã“れã‹ã‚‰ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãã‚‚ã€åŒã˜ã‚ˆã†ã«ç¢ºèªã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¾ã™ã€‚"
+ securityKeyNotSupported: "ãŠä½¿ã„ã®ãƒ–ラウザã¯ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。"
+ registerTOTPBeforeKey: "セキュリティキー・パスキーを登録ã™ã‚‹ã«ã¯ã€ã¾ãšèªè¨¼ã‚¢ãƒ—リã®è¨­å®šã‚’行ãªã£ã¦ãã ã•ã„。"
+ securityKeyInfo: "FIDO2をサãƒãƒ¼ãƒˆã™ã‚‹ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã€ç«¯æœ«ã®ç”Ÿä½“èªè¨¼ã‚„PINロックã€ãƒ‘スキーã¨ã„ã£ãŸã€WebAuthnç”±æ¥ã®éµã‚’登録ã—ã¾ã™ã€‚"
+ chromePasskeyNotSupported: "Chromeã®ãƒ‘スキーã¯ç¾åœ¨ã‚µãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“。"
+ registerSecurityKey: "セキュリティキー・パスキーを登録ã™ã‚‹"
+ securityKeyName: "キーã®åå‰ã‚’入力"
+ tapSecurityKey: "ãƒ–ãƒ©ã‚¦ã‚¶ã®æŒ‡ç¤ºã«å¾“ã„ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã‚„パスキーを登録ã—ã¦ãã ã•ã„"
+ removeKey: "セキュリティキーを削除"
+ removeKeyConfirm: "{name}を削除ã—ã¾ã™ã‹ï¼Ÿ"
+ whyTOTPOnlyRenew: "セキュリティキーãŒç™»éŒ²ã•れã¦ã„ã‚‹å ´åˆã€èªè¨¼ã‚¢ãƒ—リã®è¨­å®šã¯è§£é™¤ã§ãã¾ã›ã‚“。"
+ renewTOTP: "èªè¨¼ã‚¢ãƒ—リをå†è¨­å®š"
+ renewTOTPConfirm: "今ã¾ã§ã®èªè¨¼ã‚¢ãƒ—リã®ç¢ºèªã‚³ãƒ¼ãƒ‰ã¯ä½¿ç”¨ã§ããªããªã‚Šã¾ã™"
+ renewTOTPOk: "å†è¨­å®šã™ã‚‹"
+ renewTOTPCancel: "ã‚„ã‚ã¦ãŠã"
_permissions:
"read:account": "ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®æƒ…報を見る"
@@ -1657,8 +1680,8 @@ _visibility:
followersDescription: "自分ã®ãƒ•ォロワーã®ã¿ã«å…¬é–‹"
specified: "ダイレクト"
specifiedDescription: "指定ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿ã«å…¬é–‹"
- localOnly: "ローカルã®ã¿"
- localOnlyDescription: "リモートユーザーã«ã¯éžå…¬é–‹"
+ disableFederation: "連åˆãªã—"
+ disableFederationDescription: "他インスタンスã¸ã®é…信を行ã„ã¾ã›ã‚“"
_postForm:
replyPlaceholder: "ã“ã®ãƒŽãƒ¼ãƒˆã«è¿”ä¿¡..."
@@ -1826,6 +1849,7 @@ _notification:
pollEnded: "アンケートãŒçµ‚了"
receiveFollowRequest: "フォロー申請をå—ã‘å–ã£ãŸ"
followRequestAccepted: "フォローãŒå—ç†ã•れãŸ"
+ achievementEarned: "実績ã®ç²å¾—"
app: "連æºã‚¢ãƒ—リã‹ã‚‰ã®é€šçŸ¥"
_actions:
@@ -1861,3 +1885,7 @@ _deck:
channel: "ãƒãƒ£ãƒ³ãƒãƒ«"
mentions: "ã‚ãªãŸå®›ã¦"
direct: "ダイレクト"
+
+_dialog:
+ charactersExceeded: "最大文字数を超ãˆã¦ã„ã¾ã™ï¼ ç¾åœ¨ {current} / åˆ¶é™ {max}"
+ charactersBelow: "æœ€å°æ–‡å­—数を下回ã£ã¦ã„ã¾ã™ï¼ ç¾åœ¨ {current} / åˆ¶é™ {min}"
diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml
index cbbd928b2c..68664067c2 100644
--- a/locales/ja-KS.yml
+++ b/locales/ja-KS.yml
@@ -67,7 +67,7 @@ import: "インãƒãƒ¼ãƒˆ"
export: "エクスãƒãƒ¼ãƒˆ"
files: "ファイル"
download: "ダウンロード"
-driveFileDeleteConfirm: "ファイル「{name}ã€ã‚’消ã—ã¦ã—ã‚‚ã†ã¦ãˆãˆã‹ï¼Ÿã“ã®ãƒ•ァイルを添付ã—ãŸãƒŽãƒ¼ãƒˆã‚‚消ãˆã¦ã¾ã†ã§ã€‚"
+driveFileDeleteConfirm: "ファイル「{name}ã€ã‚’ã»ã‹ã—ã¦ãˆãˆã‹ï¼Ÿã“ã®ãƒ•ァイルを添付ã—ãŸãƒŽãƒ¼ãƒˆã‚‚消ãˆã¦ã¾ã†ã§ã€‚"
unfollowConfirm: "{name}ã®ãƒ•ォローを解除ã—ã¦ã‚‚ãˆãˆã‚“ã‹ï¼Ÿ"
exportRequested: "エクスãƒãƒ¼ãƒˆã—ã¦ãªã€ã£ã¦ãƒªã‚¯ã‚¨ã‚¹ãƒˆã—ãŸã‘ã©ã€ã“れ多分ã‚ã£ã¡ã‚ƒæ™‚é–“ã‹ã‹ã‚‹ã§ã€‚エクスãƒãƒ¼ãƒˆçµ‚ã‚ã£ãŸã‚‰ã€Œãƒ‰ãƒ©ã‚¤ãƒ–ã€ã«çªã£è¾¼ã‚“ã©ãã§ã€‚"
importRequested: "インãƒãƒ¼ãƒˆã—ã¦ãªã€ã£ã¦ãƒªã‚¯ã‚¨ã‚¹ãƒˆã—ãŸã‘ã©ã€ã“れ多分ã‚ã£ã¡ã‚ƒæ™‚é–“ã‹ã‹ã‚‹ã§ã€‚"
@@ -83,7 +83,7 @@ manageLists: "リストã®ç®¡ç†"
error: "エラー"
somethingHappened: "ãªã‚“ã‹ã‚¢ã‚«ãƒ³ã“ã¨ãŒèµ·ã“ã£ãŸã§"
retry: "ã‚‚ã£ãºã‚“やる?"
-pageLoadError: "ページã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¦ã—ã‚‚ã†ãŸã§â€¦"
+pageLoadError: "ページã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¦ã‚‚ã†ãŸã‚…"
pageLoadErrorDescription: "ã“ã‚Œã¯æ™®é€šã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‹ãƒ–ラウザキャッシュãŒåŽŸå› ã‚„ã‹ã‚‰ã­ã€‚キャッシュをクリアã™ã‚‹ã‹ã€ã‚‚ã†ã¡ã£ã¨ã ã‘å¾…ã£ã¦ãれã¸ã‚“ã‹ï¼Ÿ"
serverIsDead: "サーãƒãƒ¼ã‹ã‚‰ã®å¿œç­”ãŒãªã„ã§ã€‚ã‚‚ã†ã¡ã‚‡ã„å¾…ã£ã¦ã‹ã‚‰è©¦ã—ã¦ã¿ã¦ãªã€‚"
youShouldUpgradeClient: "ã“ã®ãƒšãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã«ã¯ã€ãƒªãƒ­ãƒ¼ãƒ‰ã—ã¦æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚’使ã£ã¦ãªãƒ¼ã€‚"
@@ -103,6 +103,8 @@ renoted: "Renoteã—ãŸã§ã€‚"
cantRenote: "ã“ã®æŠ•ç¨¿ã¯Renoteã§ãã¸ã‚“らã—ã„。"
cantReRenote: "Renote自体ã¯Renoteã§ãã¸ã‚“ã§ã€‚"
quote: "引用"
+inChannelRenote: "ãƒãƒ£ãƒ³ãƒãƒ«å†…Renote"
+inChannelQuote: "ãƒãƒ£ãƒ³ãƒãƒ«å†…引用"
pinnedNote: "ピン留ã‚ã•れã¨ã‚‹ãƒŽãƒ¼ãƒˆ"
pinned: "ピン留ã‚ã—ã¨ã"
you: "ã‚ã‚“ãŸ"
@@ -151,7 +153,7 @@ flagShowTimelineReplies: "タイムラインã«ãƒŽãƒ¼ãƒˆã¸ã®è¿”信を表示ã™
flagShowTimelineRepliesDescription: "オンã«ã—ãŸã‚‰ã€ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒŽãƒ¼ãƒˆã®ä»–ã«ã‚‚ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ä»–ã®ãƒŽãƒ¼ãƒˆã¸ã®è¿”信を表示ã™ã‚‹ã§ã€‚"
autoAcceptFollowed: "フォローã—ã¨ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰ã®ãƒ•ã‚©ãƒ­ãƒ¼ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å‹æ‰‹ã«è¨±å¯ã—ã¨ã"
addAccount: "アカウントを追加"
-loginFailed: "ログインã«å¤±æ•—ã—ã¦ã—ã‚‚ã†ãŸâ€¦"
+loginFailed: "ログインã«å¤±æ•—ã—ã¦ã‚‚ã†ãŸâ€¦"
showOnRemote: "リモートã§è¦‹ã‚‹"
general: "全般"
wallpaper: "å£ç´™"
@@ -243,7 +245,7 @@ resetAreYouSure: "リセットã—ã¦ãˆãˆã‚“?"
saved: "ä¿å­˜ã—ãŸã§ï¼"
messaging: "ãƒãƒ£ãƒƒãƒˆ"
upload: "アップロード"
-keepOriginalUploading: "オリジナル画åƒã‚’ä¿æŒã™ã‚‹ã§"
+keepOriginalUploading: "オリジナル画åƒã‚’ä¿æŒã™ã‚‹ã‚"
keepOriginalUploadingDescription: "ç”»åƒã‚’上ã’ã‚‹ã¨ãã«ã‚ªãƒªã‚¸ãƒŠãƒ«ç‰ˆã‚’ä¿æŒã™ã‚‹ã§ã€‚オフã«ã—ãŸã‚‰ä¸Šã’ãŸã¨ãã«ãƒ–ラウザã§Web公開用ã®ç”»åƒã‚’生æˆã™ã‚‹ã§ã€‚ "
fromDrive: "ドライブã‹ã‚‰"
fromUrl: "URLã‹ã‚‰"
@@ -391,13 +393,10 @@ about: "情報"
aboutMisskey: "Misskeyã£ã¦ãªã‚“や?"
administrator: "管ç†è€…"
token: "トークン"
-twoStepAuthentication: "二段階èªè¨¼"
moderator: "モデレーター"
moderation: "モデレーション"
nUsersMentioned: "{n}äººãŒæŠ•ç¨¿"
securityKey: "セキュリティキー"
-securityKeyName: "キーã®åå‰"
-registerSecurityKey: "セキュリティキーを登録ã™ã‚‹ã§"
lastUsed: "最後ã«ã¤ã“ã†ãŸæ—¥"
unregister: "登録やã‚ã‚‹"
passwordLessLogin: "パスワード無ãã¦ã‚‚ログインã§ãるよã†ã«ã™ã‚‹"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "ãƒãƒ£ãƒƒãƒˆã¯ã‚‚ã†ãœã‚“ã¶èª­ã‚“ã ã‚ã£"
help: "ヘルプ"
inputMessageHere: "ã“ã“ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ›¸ã„ã¦ã‚„"
close: "é–‰ã˜ã‚‹"
-group: "グループ"
-groups: "グループ"
-createGroup: "グループを作るã§"
-ownedGroups: "所有ã—ã¨ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—"
-joinedGroups: "å‚加ã—ã¨ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—"
invites: "æ¥ã¦ã‚„"
-groupName: "グループå"
members: "メンãƒãƒ¼"
transfer: "譲渡"
-messagingWithUser: "ユーザーã¨ãƒãƒ£ãƒƒãƒˆ"
-messagingWithGroup: "グループã§ãƒãƒ£ãƒƒãƒˆ"
title: "タイトル"
text: "テキスト"
enable: "有効ã«ã™ã‚‹ã§"
next: "次"
retype: "ã‚‚ã£ã‹ã„入力"
noteOf: "{user}ã®ãƒŽãƒ¼ãƒˆ"
-inviteToGroup: "ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›ã"
quoteAttached: "引用付ã„ã¨ã‚‹ã§"
quoteQuestion: "引用ã¨ã—ã¦æ·»ä»˜ã—ã¦ã‚‚ãˆãˆã‹ï¼Ÿ"
noMessagesYet: "ã¾ã ãƒãƒ£ãƒƒãƒˆã¯ã‚らã¸ã‚“ã§"
@@ -454,17 +444,13 @@ passwordMatched: "よã—ï¼ä¸€è‡´ã‚„ï¼"
passwordNotMatched: "一致ã—ã¨ã‚‰ã‚“ã§ï¼Ÿ"
signinWith: "{x}ã§ãƒ­ã‚°ã‚¤ãƒ³"
signinFailed: "ログインã§ãã‚“ã‹ã£ãŸã§ã€‚ã‚‚ã£ã‹ã„ユーザーåã¨ãƒ‘スワードを確èªã—ã¦ã¿ã¦ãªã€‚"
-tapSecurityKey: "セキュリティキーã«ã‚¿ãƒƒãƒã—ã¦ãª"
or: "ãれã‹"
language: "言語"
uiLanguage: "UIã®è¡¨ç¤ºè¨€èªž"
-groupInvited: "ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›å¾…ã•れã¨ã‚‹ã§"
aboutX: "{x}ã«ã¤ã„ã¦"
emojiStyle: "絵文字ã®ã‚¹ã‚¿ã‚¤ãƒ«"
native: "ãƒã‚¤ãƒ†ã‚£ãƒ–"
disableDrawer: "メニューをドロワーã§è¡¨ç¤ºã›ã‡ã¸ã‚“"
-youHaveNoGroups: "グループãŒã‚らã¸ã‚“ã­ã‡ã€‚"
-joinOrCreateGroup: "既存ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›å¾…ã—ã¦ã‚‚らã†ã‹ã€æ–°ã—ãグループ作ã£ã¦ã‹ã‚‰ã‚„ã£ã¦ãª"
noHistory: "履歴ã¯ã‚らã¸ã‚“ã­ã‡ã€‚"
signinHistory: "ログイン履歴"
enableAdvancedMfm: "ã‚„ã‚„ã“ã—ã„MFMã‚‚ã‚りã«ã™ã‚‹"
@@ -838,10 +824,8 @@ deleteAccountConfirm: "アカウントを消ã™ã§ï¼Ÿãˆãˆã‚“ã‹ï¼Ÿ"
incorrectPassword: "パスワードãŒã¡ã‚ƒã†ã§ã€‚"
voteConfirm: "「{choice}ã€ã«æŠ•票ã™ã‚‹ã‚“ã‹ï¼Ÿ"
hide: "éš ã™"
-leaveGroup: "グループã‹ã‚‰æŠœã‘ã‚‹ã§"
-leaveGroupConfirm: "「{name}ã€ã‹ã‚‰æŠœã‘るん?"
useDrawerReactionPickerForMobile: "ケータイã¨ã‹ã®ã¨ãドロワーã§è¡¨ç¤ºã™ã‚‹ã§"
-welcomeBackWithName: "ã¾ã„ã©ã€{name}ã•ã‚“"
+welcomeBackWithName: "ã¾ã„ã©ã€{name}ã¯ã‚“"
clickToFinishEmailVerification: "[{ok}]を押ã—ã¦ãƒ¡ã‚¢ãƒ‰ã®ç¢ºèªã‚’終ã‚らã›ã¦ãªãƒ¼"
overridedDeviceKind: "デãƒã‚¤ã‚¹ã‚¿ã‚¤ãƒ—"
smartphone: "スマホ"
@@ -898,7 +882,7 @@ fast: "速ã„"
sensitiveMediaDetection: "センシティブãªãƒ¡ãƒ‡ã‚£ã‚¢ã®æ¤œå‡º"
localOnly: "ローカルã®ã¿"
remoteOnly: "リモートã®ã¿"
-failedToUpload: "アップロードã«å¤±æ•—ã—ãŸã§"
+failedToUpload: "アップロードã«å¤±æ•—ã—ã¦ã‚‚ã†ãŸã‚…"
cannotUploadBecauseInappropriate: "ä¸é©åˆ‡ãªå†…容をå«ã‚€ã‹ã‚‚ã—れã¸ã‚“ã£ã¦åˆ¤å®šã•れãŸã§ã‚¢ãƒƒãƒ—ロードã§ãã¾ã¸ã‚“。"
cannotUploadBecauseNoFreeSpace: "ドライブã®ç©ºã容é‡ãŒç„¡ã„ã§ã‚¢ãƒƒãƒ—ロードã§ãã¾ã¸ã‚“。"
beta: "ベータ"
@@ -948,35 +932,224 @@ achievements: "実績"
gotInvalidResponseError: "サーãƒãƒ¼é»™ã£ã¨ã‚‹ã‚ã€çŸ¥ã‚‰ã‚“ã‘ã©"
gotInvalidResponseErrorDescription: "サーãƒãƒ¼ã„ã¾æ—¥æ›œæ—¥ã€‚ã¾ãŸãã¦æœˆæ›œæ—¥ã€‚"
thisPostMayBeAnnoying: "ã“ã®æŠ•ç¨¿ã¯è¿·æƒ‘ã‹ã‚‚ã—らんã§ã€‚"
+thisPostMayBeAnnoyingHome: "ãƒ›ãƒ¼ãƒ ã«æŠ•ç¨¿"
+thisPostMayBeAnnoyingCancel: "ã‚„ã‚ã¨ã"
+thisPostMayBeAnnoyingIgnore: "ã“ã®ã¾ã¾æŠ•稿"
collapseRenotes: "見ãŸã“ã¨ã‚ã‚‹Renoteã¯çœç•¥ã‚„ã§"
+internalServerError: "サーãƒãƒ¼å†…部エラー"
+internalServerErrorDescription: "サーãƒãƒ¼å†…部ã§ã‚ˆã†åˆ†ã‹ã‚‰ã‚“エラーやã‚"
+copyErrorInfo: "エラー情報をコピー"
_achievements:
earnedAt: "è²°ã£ãŸæ—¥ãƒ"
_types:
_notes1:
title: "ã¾ã„ã©ï¼"
description: "åˆã‚ã¦ãƒŽãƒ¼ãƒˆæŠ•稿ã—ãŸã£ãŸ"
+ flavor: "Misskeyを楽ã—ã‚“ã§ãªï½ž"
_notes10:
title: "ノートã®å¤©ä¿å±±"
+ description: "ノートを10回投稿ã—ãŸ"
_notes100:
title: "ノートã®çœŸç”°å±±"
+ description: "ノートを100回投稿ã—ãŸ"
_notes500:
title: "ノートã®ç”Ÿé§’å±±"
+ description: "ノートを500回投稿ã—ãŸ"
+ _notes1000:
+ title: "ノートã®å±±"
+ description: "ノートを1,000回投稿ã—ãŸ"
_notes5000:
title: "箕é¢ã®æ»ã‹ã‚‰ãƒŽãƒ¼ãƒˆ"
+ description: "ノートを5,000回投稿ã—ãŸ"
+ _notes10000:
+ title: "スーパーノート"
+ description: "ノートを10,000回投稿ã—ãŸ"
+ _notes20000:
+ title: "ニードモアノート"
+ description: "ノートを20,000回投稿ã—ãŸ"
+ _notes30000:
+ title: "ノートノートノート"
+ description: "ノートを30,000回投稿ã—ãŸ"
+ _notes40000:
+ title: "ノート工場"
+ description: "ノートを40,000回投稿ã—ãŸ"
+ _notes50000:
+ title: "ãƒŽãƒ¼ãƒˆã®æƒ‘星"
+ description: "ノートを50,000回投稿ã—ãŸ"
+ _notes60000:
+ title: "ノートクエーサー"
+ description: "ノートを60,000回投稿ã—ãŸ"
+ _notes70000:
+ title: "ブラックノートホール"
+ description: "ノートを70,000回投稿ã—ãŸ"
+ _notes80000:
+ title: "ノートギャラクシー"
+ description: "ノートを80,000回投稿ã—ãŸ"
+ _notes90000:
+ title: "ノートãƒãƒ¼ã‚¹"
+ description: "ノートを90,000回投稿ã—ãŸ"
+ _notes100000:
+ title: "ALL YOUR NOTE ARE BELONG TO US"
+ description: "ノートを100,000回投稿ã—ãŸ"
+ flavor: "ãã‚“ãªã«æ›¸ãã“ã¨ã‚ã‚‹ã‚“ã‹ï¼Ÿ"
_login3:
+ title: "ビギナーⅠ"
+ description: "通算3日ログインã—ãŸ"
flavor: "今日ã‹ã‚‰ãƒ¯ã‚·ã¯ãƒŸã‚¹ã‚­ã‚¹ãƒˆã‚„ã§"
+ _login7:
+ title: "ビギナーⅡ"
+ description: "通算7日ログインã—ãŸ"
+ flavor: "慣れã¦ããŸã‚“ã¡ã‚ƒã†ï¼Ÿ"
+ _login15:
+ title: "ビギナーⅢ"
+ description: "通算15日ログインã—ãŸ"
+ _login30:
+ title: "ミスキストⅠ"
+ description: "通算30日ログインã—ãŸ"
+ _login60:
+ title: "ミスキストⅡ"
+ description: "通算60日ログインã—ãŸ"
+ _login100:
+ title: "ミスキストⅢ"
+ description: "通算100日ログインã—ãŸ"
+ flavor: "ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ãƒŸã‚¹ã‚­ã‚¹ãƒˆã«ã¤ã"
+ _login200:
+ title: "常連ã•ã‚“â… "
+ description: "通算200日ログインã—ãŸ"
+ _login300:
+ title: "常連ã•ã‚“â…¡"
+ description: "通算300日ログインã—ãŸ"
+ _login400:
+ title: "常連ã•ã‚“â…¢"
+ description: "通算400日ログインã—ãŸ"
+ _login500:
+ title: "ベテランã•ã‚“â… "
+ description: "通算500日ログインã—ãŸ"
+ flavor: "ã‚ã‚“ãŸã‚‰ã€ã†ã¡ã¯ãƒŽãƒ¼ãƒˆãŒå¥½ãã‚„"
+ _login600:
+ title: "ベテランã•ã‚“â…¡"
+ description: "通算600日ログインã—ãŸ"
+ _login700:
+ title: "ベテランã•ã‚“â…¢"
+ description: "通算700日ログインã—ãŸ"
+ _login800:
+ title: "ノートマイスターⅠ"
+ description: "通算800日ログインã—ãŸ"
+ _login900:
+ title: "ノートマイスターⅡ"
+ description: "通算900日ログインã—ãŸ"
+ _login1000:
+ title: "ノートマイスターⅢ"
+ description: "通算1,000日ログインã—ãŸ"
+ flavor: "Misskeyよã†ã•ん使ã¦ã‚‚ã‚ã¦ãŠãŠãã«ãªï¼"
+ _noteClipped1:
+ title: "アカンã©ã‚Œã‚‚クリップã—ãŸã„ã‚"
+ description: "åˆã‚ã¦ãƒŽãƒ¼ãƒˆã‚’クリップã—ãŸ"
+ _noteFavorited1:
+ title: "星ãƒã¿ã‚‹ã²ã¨"
+ description: "åˆã‚ã¦ãƒŽãƒ¼ãƒˆã‚’ãŠæ°—ã«å…¥ã‚Šã«ç™»éŒ²ã—ãŸ"
+ _myNoteFavorited1:
+ title: "æ˜Ÿãƒæ¬²ã—ã„"
+ description: "ワレã®ãƒŽãƒ¼ãƒˆãŒä»–ã®ã²ã¨ã«ãŠæ°—ã«å…¥ã‚Šç™»éŒ²ã•れãŸã§"
+ _following10:
+ description: "フォローãŒ10人超ãˆãŸ"
+ _following50:
+ description: "フォローãŒ50人超ãˆãŸ"
+ _following100:
+ description: "フォローãŒ100人超ãˆãŸ"
+ _following300:
+ description: "フォローãŒ300人超ãˆãŸ"
+ _followers10:
+ description: "フォロワーãŒ10人超ãˆãŸ"
+ _followers50:
+ description: "フォロワーãŒ50人超ãˆãŸ"
+ _followers100:
+ description: "フォロワーãŒ100人超ãˆãŸ"
+ _followers300:
+ description: "フォロワーãŒ300人超ãˆãŸ"
+ _followers500:
+ title: "基地局"
+ description: "フォロワーãŒ500人超ãˆãŸ"
+ _followers1000:
+ title: "インフルエンサー"
+ description: "フォロワーãŒ1,000人超ãˆãŸ"
+ _collectAchievements30:
+ title: "実績コレクター"
+ description: "実績を30個以上ç²å¾—ã—ãŸ"
+ _viewAchievements3min:
+ title: "実績好ã"
+ description: "実績一覧を3分以上眺ã‚ç¶šã‘ãŸ"
_iLoveMisskey:
title: "Misskey好ãã‚„ã­ã‚“"
+ description: "\"I ⤠#Misskey\"を投稿ã—ãŸ"
+ flavor: "Misskeyを使ã£ã¦ãれã¦ã‚りãŒã¨ã†ãªï½žã€€by 開発ãƒãƒ¼ãƒ "
_foundTreasure:
title: "ãªã‚“ã§ã‚‚鑑定団"
+ description: "éš ã•れãŸãŠå®ã‚’発見ã—ãŸ"
_client30min:
title: "ã­ã‚“ã­"
+ description: "クライアントを起動ã—ã¦ã‹ã‚‰30分以上経éŽã—ãŸ"
_noteDeletedWithin1min:
title: "*ãŠãŠã£ã¨ï¼Š"
+ description: "投稿ã—ã¦ã‹ã‚‰1分以内ã«ãã®æŠ•ç¨¿ã‚’æ¶ˆã—ãŸ"
+ _postedAtLateNight:
+ title: "夜行性"
+ description: "深夜ã«ãƒŽãƒ¼ãƒˆã‚’投稿ã—ãŸ"
+ flavor: "ãã‚ãã‚å¯ã‚ˆã‹"
+ _postedAt0min0sec:
+ title: "時報"
+ description: "0分0ç§’ã«ãƒŽãƒ¼ãƒˆã‚’投稿ã—ãŸ"
+ flavor: "ãƒãƒƒ ãƒãƒƒ ãƒãƒƒ ピーン"
+ _selfQuote:
+ title: "自己言åŠ"
+ description: "自分ã®ãƒŽãƒ¼ãƒˆã‚’引用ã—ãŸ"
+ _htl20npm:
+ title: "æµã‚Œã‚‹TL"
+ description: "ãƒ›ãƒ¼ãƒ ã‚¿ã‚¤ãƒ ãƒ©ã‚¤ãƒ³ã®æµé€ŸãŒ20npmã‚’è¶…ã™"
+ _viewInstanceChart:
+ title: "アナリスト"
+ description: "インスタンスã®ãƒãƒ£ãƒ¼ãƒˆã‚’表示ã—ãŸ"
+ _outputHelloWorldOnScratchpad:
+ title: "Hello, world!"
+ description: "スクラッãƒãƒ‘ッド㧠hello worldを出力ã—ãŸ"
_open3windows:
title: "マド開ã‘ã™ãŽ"
+ description: "ウィンドウを3ã¤ä»¥ä¸Šé–‹ã„ãŸçŠ¶æ…‹ã«ã—ãŸ"
_driveFolderCircularReference:
title: "環状線"
+ description: "ドライブã®ãƒ•ォルダをå†å¸°çš„ãªå…¥ã‚Œå­ã«ã—よã†ã¨ã—ãŸ"
+ _reactWithoutRead:
+ title: "ã¡ã‚ƒã‚“ã¨èª­ã‚“ã ã‚“ã‹ï¼Ÿ"
+ description: "100文字以上ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’å«ã‚€ãƒŽãƒ¼ãƒˆã«æŠ•稿ã•れã¦ã‹ã‚‰3秒以内ã«ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã—ãŸ"
+ _clickedClickHere:
+ title: "ã“ã“をクリック"
+ description: "ã“ã“をクリックã—ãŸ"
+ _justPlainLucky:
+ title: "å˜ãªã‚‹ãƒ©ãƒƒã‚­ãƒ¼"
+ description: "10ç§’ã”ã¨ã«0.005ï¼…ã®ç¢ºçއã§ç²å¾—"
+ _setNameToSyuilo:
+ title: "神様コンプレックス"
+ description: "åå‰ã‚’ syuilo ã«è¨­å®šã—ãŸ"
+ _passedSinceAccountCreated1:
+ title: "一周年"
+ description: "アカウント作æˆã‹ã‚‰1年経éŽã—ãŸ"
+ _passedSinceAccountCreated2:
+ title: "二周年"
+ description: "アカウント作æˆã‹ã‚‰2年経éŽã—ãŸ"
+ _passedSinceAccountCreated3:
+ title: "三周年"
+ description: "アカウント作æˆã‹ã‚‰3年経éŽã—ãŸ"
+ _loggedInOnBirthday:
+ title: "ãƒãƒƒãƒ”ーãƒãƒ¼ã‚¹ãƒ‡ãƒ¼ï¼"
+ description: "誕生日ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ãŸ"
+ _loggedInOnNewYearsDay:
+ title: "ã‚ã‘ã¾ã—ã¦ãŠã‚ã§ã¨ã†ã”ã–ã„ã¾ã™ï¼"
+ description: "元旦ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ãŸ"
+ flavor: "今年も弊インスタンスをよã‚ã—ããŠé¡˜ã„ã—ã¾ã™"
+ _cookieClicked:
+ title: "クッキーå©ãã‚„ã¤"
+ description: "クッキーå©ã„ã¦ã‚‚ã†ãŸ"
+ flavor: "å…„ã¡ã‚ƒã‚“ソフト間é•ã£ã¨ã‚“ã§"
_role:
new: "ロールã®ä½œæˆ"
edit: "ロールã®ç·¨é›†"
@@ -997,6 +1170,7 @@ _role:
baseRole: "ベースロール"
useBaseValue: "ベースロールã®å€¤ã‚’使用"
chooseRoleToAssign: "アサインã™ã‚‹ãƒ­ãƒ¼ãƒ«ã‚’é¸æŠž"
+ descriptionOfAsBadge: "オンã«ã™ã‚‹ã¨ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã®æ¨ªã‚“ã¨ã“ã«ãƒ­ãƒ¼ãƒ«ã®ã‚¢ã‚¤ã‚³ãƒ³ãŒè¡¨ç¤ºã•れるã§ã€‚"
canEditMembersByModerator: "モデレーターã®ãƒ¡ãƒ³ãƒãƒ¼ç·¨é›†ã‚’許å¯"
descriptionOfCanEditMembersByModerator: "オンã«ã™ã‚‹ã¨ã€ç®¡ç†è€…ã«åŠ ãˆã¦ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿ãƒ¼ã‚‚ã“ã®ãƒ­ãƒ¼ãƒ«ã¸ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’アサイン/アサイン解除ã§ãるよã†ã«ãªã‚‹ã§ã€‚オフã«ã™ã‚‹ã¨ç®¡ç†è€…ã®ã¿ãŒè¡Œãˆã‚‹ã§ã€‚"
priority: "優先度"
@@ -1284,14 +1458,14 @@ _tutorial:
step8_3: "通知ã®è¨­å®šã¯ã‚ã¨ã‹ã‚‰å¤‰æ›´ã§ãã‚‹ã§"
_2fa:
alreadyRegistered: "ã‚‚ã†è¨­å®šçµ‚ã‚ã£ã¨ã‚‹ã‚。"
- registerDevice: "デãƒã‚¤ã‚¹ã‚’登録ã™ã‚‹ã§"
- registerKey: "キーを登録ã™ã‚‹ã§"
step1: "ã»ã‚“ãªã‚‰ã€{a}ã‚„{b}ã¨ã‹ã®èªè¨¼ã‚¢ãƒ—リを使ã£ã¨ã‚‹ãƒ‡ãƒã‚¤ã‚¹ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãªã€‚"
step2: "次ã«ã€ã“ã“ã«ã‚ã‚‹QRコードをアプリã§ã‚¹ã‚­ãƒ£ãƒ³ã—ã¦ãªï½žã€‚"
step2Url: "デスクトップアプリやã£ãŸã‚‰æ¬¡ã®URLを入力ã—ã¦ã‚„:"
step3: "アプリã«è¡¨ç¤ºã•れã¦ã„るトークンを入力ã—ã¦çµ‚ã‚りや。"
step4: "ã“れã‹ã‚‰ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãã‚‚ã€åŒã˜ã‚ˆã†ã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’入力ã™ã‚‹ã‚“ã‚„ã§"
securityKeyInfo: "FIDO2をサãƒãƒ¼ãƒˆã™ã‚‹ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚­ãƒ¼ã‹ç«¯æœ«ã®æŒ‡ç´‹èªè¨¼ã‚„PINを使ã£ã¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã‚ˆã†ã«è¨­å®šã§ãã‚‹ã§ã€‚"
+ removeKeyConfirm: "{name}を消ã™ã‚“?"
+ renewTOTPCancel: "ã‚„ã‚ã¨ã"
_permissions:
"read:account": "ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®æƒ…報を見るã§"
"write:account": "ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®æƒ…報を変更ã™ã‚‹ã§"
@@ -1339,7 +1513,6 @@ _antennaSources:
homeTimeline: "フォローã—ã¨ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒŽãƒ¼ãƒˆ"
users: "é¸ã‚‰ã‚“ã ä¸€äººã‹è¤‡æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒŽãƒ¼ãƒˆ"
userList: "é¸ã‚“ã ãƒªã‚¹ãƒˆã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒŽãƒ¼ãƒˆ"
- userGroup: "é¸ã‚“ã ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒŽãƒ¼ãƒˆ"
_weekday:
sunday: "日曜日"
monday: "月曜日"
@@ -1414,8 +1587,6 @@ _visibility:
followersDescription: "自分ã®ãƒ•ォロワーã®ã¿ã«å…¬é–‹ã™ã‚‹ã§"
specified: "ダイレクト"
specifiedDescription: "é¸ã‚“ã ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿ã«å…¬é–‹ã™ã‚‹ã§"
- localOnly: "ローカルã®ã¿"
- localOnlyDescription: "リモートユーザーã«ã¯éžå…¬é–‹ã«ã™ã‚‹ã§"
_postForm:
replyPlaceholder: "ã“ã®ãƒŽãƒ¼ãƒˆã«è¿”ä¿¡..."
quotePlaceholder: "ã“ã®ãƒŽãƒ¼ãƒˆã‚’引用..."
@@ -1510,7 +1681,7 @@ _pages:
viewPage: "ページを見る"
like: "ãˆãˆã‚„ã‚“"
unlike: "良ããªã„ã‚"
- my: "人気ã®ãƒšãƒ¼ã‚¸"
+ my: "自分ã®ãƒšãƒ¼ã‚¸"
liked: "ãˆãˆã¨æ€ã£ãŸãƒšãƒ¼ã‚¸"
featured: "人気"
inspector: "インスペクター"
@@ -1553,12 +1724,9 @@ _notification:
youGotReply: "{name}ã‹ã‚‰ã®ãƒªãƒ—ライ"
youGotQuote: "{name}ã«ã‚ˆã‚‹å¼•用"
youRenoted: "{name}ãŒRenoteã—ãŸã¿ãŸã„ã‚„ã§"
- youGotMessagingMessageFromUser: "{name}ã‹ã‚‰ã®ãƒãƒ£ãƒƒãƒˆãŒã‚ã‚‹ã§"
- youGotMessagingMessageFromGroup: "{name}ã®ãƒãƒ£ãƒƒãƒˆãŒã‚ã‚‹ã§"
youWereFollowed: "フォローã•れãŸã§"
youReceivedFollowRequest: "フォロー許å¯ã—ã¦ã»ã—ã„ã¿ãŸã„ã‚„ãª"
yourFollowRequestAccepted: "フォローã•ã›ã¦ã‚‚ã‚ãŸã§"
- youWereInvitedToGroup: "ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›å¾…ã•れã¨ã‚‹ã§"
pollEnded: "アンケートã®çµæžœãŒå‡ºãŸã¿ãŸã„ã‚„"
unreadAntennaNote: "アンテナ {name}"
emptyPushNotificationMessage: "ãƒ—ãƒƒã‚·ãƒ¥é€šçŸ¥ã®æ›´æ–°ã‚’ã—ã¨ã„ãŸã§"
@@ -1574,7 +1742,6 @@ _notification:
pollEnded: "アンケートãŒçµ‚了ã—ãŸã§"
receiveFollowRequest: "フォロー許å¯ã—ã¦ã»ã—ã„ã¿ãŸã„ã‚„ã§"
followRequestAccepted: "フォローãŒå—ç†ã•れãŸã§"
- groupInvited: "ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›å¾…ã•れãŸã§"
app: "連æºã‚¢ãƒ—リã‹ã‚‰ã®é€šçŸ¥ã‚„"
_actions:
followBack: "フォローãƒãƒƒã‚¯"
diff --git a/locales/kab-KAB.yml b/locales/kab-KAB.yml
index fcd490db12..18fd8f5a58 100644
--- a/locales/kab-KAB.yml
+++ b/locales/kab-KAB.yml
@@ -39,10 +39,8 @@ remove: "Kkes"
connectService: "Qqen"
userList: "Tibdarin"
securityKey: "Tasarutt n tɣellist"
-securityKeyName: "Isem n tsarutt"
signinRequired: "Ttxil jerred"
signinWith: "Tuqqna s {x}"
-tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
uiLanguage: "Tutlayt n wegrudem"
accountSettings: "IÉ£ewwaá¹›en n umiá¸an"
plugins: "Izegrar"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index 5096a5d316..1c5cf8517c 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -15,7 +15,7 @@ gotIt: "알겠어요"
cancel: "취소"
noThankYou: "나중ì—"
enterUsername: "유저명 입력"
-renotedBy: "{user}ë‹˜ì´ ë¦¬ë…¸íŠ¸"
+renotedBy: "{user}ë‹˜ì˜ ë¦¬ë…¸íŠ¸"
noNotes: "노트가 없습니다"
noNotifications: "표시할 ì•Œë¦¼ì´ ì—†ìŠµë‹ˆë‹¤"
instance: "ì¸ìŠ¤í„´ìŠ¤"
@@ -103,6 +103,8 @@ renoted: "리노트했습니다"
cantRenote: "ì´ ê²Œì‹œë¬¼ì€ ë¦¬ë…¸íŠ¸ í•  수 없습니다."
cantReRenote: "리노트를 리노트 할 수 없습니다."
quote: "ì¸ìš©"
+inChannelRenote: "ì±„ë„ ë‚´ 리노트"
+inChannelQuote: "ì±„ë„ ë‚´ ì¸ìš©"
pinnedNote: "ê³ ì •í•´ë†“ì€ ë…¸íŠ¸"
pinned: "í”„ë¡œí•„ì— ê³ ì •"
you: "당신"
@@ -391,13 +393,10 @@ about: "ì •ë³´"
aboutMisskey: "Misskeyì— ëŒ€í•˜ì—¬"
administrator: "관리ìž"
token: "토í°"
-twoStepAuthentication: "2단계 ì¸ì¦"
moderator: "모ë”ë ˆì´í„°"
moderation: "모ë”ë ˆì´ì…˜"
nUsersMentioned: "{n}ëª…ì´ ì–¸ê¸‰í•¨"
securityKey: "보안 키"
-securityKeyName: "키 ì´ë¦„"
-registerSecurityKey: "보안 키를 등ë¡"
lastUsed: "마지막 사용"
unregister: "ë“±ë¡ í•´ì œ"
passwordLessLogin: "비밀번호 ì—†ì´ ë¡œê·¸ì¸"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "모든 대화를 ì½ì€ ìƒíƒœë¡œ 표시"
help: "ë„움ë§"
inputMessageHere: "ì—¬ê¸°ì— ë©”ì‹œì§€ë¥¼ 입력하세요"
close: "닫기"
-group: "그룹"
-groups: "그룹"
-createGroup: "그룹 만들기"
-ownedGroups: "소유 그룹"
-joinedGroups: "ì°¸ì—¬ì¤‘ì¸ ê·¸ë£¹"
invites: "초대"
-groupName: "그룹명"
members: "멤버"
transfer: "ì–‘ë„"
-messagingWithUser: "유저와 대화하기"
-messagingWithGroup: "그룹ë¼ë¦¬ 대화하기"
title: "제목"
text: "í…스트"
enable: "사용"
next: "다ìŒ"
retype: "다시 입력"
noteOf: "{user}ì˜ ë…¸íŠ¸"
-inviteToGroup: "ê·¸ë£¹ì— ì´ˆëŒ€í•˜ê¸°"
quoteAttached: "ì¸ìš©í•¨"
quoteQuestion: "ì¸ìš©í•´ì„œ 작성하시겠습니까?"
noMessagesYet: "ì•„ì§ ëŒ€í™”ê°€ 없습니다"
@@ -454,17 +444,13 @@ passwordMatched: "ì¼ì¹˜í•©ë‹ˆë‹¤"
passwordNotMatched: "ì¼ì¹˜í•˜ì§€ 않습니다"
signinWith: "{x}로 로그ì¸"
signinFailed: "로그ì¸í•  수 없습니다. 사용ìžëª…ê³¼ 비밀번호를 확ì¸í•˜ì—¬ 주십시오."
-tapSecurityKey: "보안 키를 터치"
or: "혹ì€"
language: "언어"
uiLanguage: "UI 표시 언어"
-groupInvited: "ê·¸ë£¹ì— ì´ˆëŒ€ë˜ì—ˆìŠµë‹ˆë‹¤"
aboutX: "{x}ì— ëŒ€í•˜ì—¬"
emojiStyle: "ì´ëª¨ì§€ 스타ì¼"
native: "네ì´í‹°ë¸Œ"
disableDrawer: "드로어 메뉴를 사용하지 않기"
-youHaveNoGroups: "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤"
-joinOrCreateGroup: "다른 ê·¸ë£¹ì˜ ì´ˆëŒ€ë¥¼ 받거나, ì§ì ‘ 새 ê·¸ë£¹ì„ ë§Œë“¤ì–´ 보세요."
noHistory: "기ë¡ì´ 없습니다"
signinHistory: "ë¡œê·¸ì¸ ê¸°ë¡"
enableAdvancedMfm: "고급 MFMì„ í™œì„±í™”"
@@ -838,8 +824,6 @@ deleteAccountConfirm: "ê³„ì •ì´ ì‚­ì œë˜ê³  ë˜ëŒë¦´ 수 없게 ë©ë‹ˆë‹¤. ê³
incorrectPassword: "비밀번호가 올바르지 않습니다."
voteConfirm: "\"{choice}\"ì— íˆ¬í‘œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
hide: "숨기기"
-leaveGroup: "그룹 나가기"
-leaveGroupConfirm: "\"{name}\"ì—서 나갈까요?"
useDrawerReactionPickerForMobile: "모바ì¼ì—서 드로어 메뉴로 표시"
welcomeBackWithName: "환ì˜í•©ë‹ˆë‹¤, {name}님"
clickToFinishEmailVerification: "[{ok}]를 눌러 ì´ë©”ì¼ ì¸ì¦ì„ 완료하세요."
@@ -951,6 +935,10 @@ thisPostMayBeAnnoying: "ì´ ê²Œì‹œë¬¼ì€ ë‹¤ë¥¸ 유저ì—게 피해를 줄 ê°€ëŠ
thisPostMayBeAnnoyingHome: "í™ˆì— ê²Œì‹œ"
thisPostMayBeAnnoyingCancel: "그만ë‘기"
thisPostMayBeAnnoyingIgnore: "ì´ëŒ€ë¡œ 게시"
+collapseRenotes: "ì´ë¯¸ 본 리노트를 간략화하기"
+internalServerError: "내부 서버 오류"
+internalServerErrorDescription: "ë‚´ë¶€ 서버ì—서 예기치 ì•Šì€ ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+copyErrorInfo: "오류 정보 복사"
_achievements:
earnedAt: "달성 ì¼ì‹œ"
_types:
@@ -1232,7 +1220,7 @@ _role:
noteEachClipsMax: "ê° í´ë¦½ì— 추가할 수 있는 노트 수"
userListMax: "ìƒì„±í•  수 있는 유저 리스트 수"
userEachUserListsMax: "유저 리스트당 최대 ì‚¬ìš©ìž ìˆ˜"
- rateLimitFactor: "ì†ë„ 제한"
+ rateLimitFactor: "요청 ë¹ˆë„ ì œí•œ"
descriptionOfRateLimitFactor: "ìž‘ì„ìˆ˜ë¡ ì œí•œì´ ì™„í™”ë˜ê³ , í´ìˆ˜ë¡ ì œí•œì´ ê°•í™”ë©ë‹ˆë‹¤."
canHideAds: "광고 숨기기"
_condition:
@@ -1497,14 +1485,14 @@ _tutorial:
step8_3: "알림 ì„¤ì •ì€ ë‚˜ì¤‘ì—ë„ ë³€ê²½í•  수 있습니다."
_2fa:
alreadyRegistered: "ì´ë¯¸ ì„¤ì •ì´ ì™„ë£Œë˜ì—ˆìŠµë‹ˆë‹¤."
- registerDevice: "디바ì´ìФ 등ë¡"
- registerKey: "키를 등ë¡"
step1: "먼저, {a}나 {b}ë“±ì˜ ì¸ì¦ ì•±ì„ ì‚¬ìš© ì¤‘ì¸ ë””ë°”ì´ìŠ¤ì— ì„¤ì¹˜í•©ë‹ˆë‹¤."
step2: "ê·¸ 후, 표시ë˜ì–´ 있는 QR코드를 앱으로 스캔합니다."
step2Url: "ë°ìФí¬í†± 앱ì—서는 ë‹¤ìŒ URLì„ ìž…ë ¥í•˜ì„¸ìš”:"
step3: "ì•±ì— í‘œì‹œëœ í† í°ì„ 입력하시면 완료ë©ë‹ˆë‹¤."
step4: "ë‹¤ìŒ ë¡œê·¸ì¸ë¶€í„°ëŠ” 토í°ì„ 입력해야 합니다."
securityKeyInfo: "FIDO2를 ì§€ì›í•˜ëŠ” 하드웨어 보안 키 í˜¹ì€ ë””ë°”ì´ìŠ¤ì˜ ì§€ë¬¸ì¸ì‹ì´ë‚˜ 화면잠금 PINì„ ì´ìš©í•´ì„œ 로그ì¸í•˜ë„ë¡ ì„¤ì •í•  수 있습니다."
+ removeKeyConfirm: "{name} ì„(를) 삭제하시겠습니까?"
+ renewTOTPCancel: "나중ì—"
_permissions:
"read:account": "ê³„ì •ì˜ ì •ë³´ë¥¼ 봅니다"
"write:account": "ê³„ì •ì˜ ì •ë³´ë¥¼ 변경합니다"
@@ -1553,7 +1541,6 @@ _antennaSources:
homeTimeline: "íŒ”ë¡œìš°ì¤‘ì¸ ìœ ì €ì˜ ë…¸íŠ¸"
users: "지정한 한 명 í˜¹ì€ ì—¬ëŸ¬ ëª…ì˜ ìœ ì €ì˜ ë…¸íŠ¸"
userList: "지정한 ë¦¬ìŠ¤íŠ¸ì— ì†í•œ ìœ ì €ì˜ ë…¸íŠ¸"
- userGroup: "지정한 ê·¸ë£¹ì— ì†í•œ ìœ ì €ì˜ ë…¸íŠ¸"
_weekday:
sunday: "ì¼ìš”ì¼"
monday: "월요ì¼"
@@ -1628,8 +1615,6 @@ _visibility:
followersDescription: "팔로워ì—게만 공개"
specified: "다ì´ë ‰íЏ"
specifiedDescription: "지정한 유저ì—게만 공개"
- localOnly: "로컬ì—ë§Œ"
- localOnlyDescription: "리모트 유저ì—게 ë³´ì´ì§€ 않기"
_postForm:
replyPlaceholder: "ì´ ë…¸íŠ¸ì— ë‹µê¸€..."
quotePlaceholder: "ì´ ë…¸íŠ¸ë¥¼ ì¸ìš©..."
@@ -1767,12 +1752,9 @@ _notification:
youGotReply: "{name}ë‹˜ì´ ë‹µê¸€í•¨"
youGotQuote: "{name}ë‹˜ì´ ì¸ìš©í•¨"
youRenoted: "{name}ë‹˜ì´ Renote"
- youGotMessagingMessageFromUser: "{name} ë‹˜ì´ ë³´ë‚¸ ì±„íŒ…ì´ ìžˆì–´ìš”"
- youGotMessagingMessageFromGroup: "{name}ì—서 보낸 ì±„íŒ…ì´ ìžˆì–´ìš”"
youWereFollowed: "새로운 팔로워가 있습니다"
youReceivedFollowRequest: "새로운 팔로우 ìš”ì²­ì´ ìžˆìŠµë‹ˆë‹¤"
yourFollowRequestAccepted: "팔로우 ìš”ì²­ì´ ìˆ˜ë½ë˜ì—ˆìŠµë‹ˆë‹¤"
- youWereInvitedToGroup: "ê·¸ë£¹ì— ì´ˆëŒ€ë˜ì—ˆìŠµë‹ˆë‹¤"
pollEnded: "투표 결과가 발표ë˜ì—ˆìŠµë‹ˆë‹¤"
unreadAntennaNote: "안테나 {name}"
emptyPushNotificationMessage: "푸시 ì•Œë¦¼ì´ ê°±ì‹ ë˜ì—ˆìŠµë‹ˆë‹¤"
@@ -1788,7 +1770,6 @@ _notification:
pollEnded: "투표가 종료ë¨"
receiveFollowRequest: "팔로우 ìš”ì²­ì„ ë°›ì•˜ì„ ë•Œ"
followRequestAccepted: "팔로우 ìš”ì²­ì´ ìŠ¹ì¸ë˜ì—ˆì„ 때"
- groupInvited: "ê·¸ë£¹ì— ì´ˆëŒ€ë˜ì—ˆì„ 때"
app: "ì—°ë™ëœ ì•±ì„ í†µí•œ 알림"
_actions:
followBack: "팔로우"
diff --git a/locales/lo-LA.yml b/locales/lo-LA.yml
index 263a7eb18c..ce596d038f 100644
--- a/locales/lo-LA.yml
+++ b/locales/lo-LA.yml
@@ -136,7 +136,29 @@ loginFailed: "àºàº²àº™à»€àº‚ົ້າສູ່ລະບົບບà»à»ˆàºªàº³à»€
general: "ທົ່ວໄປ"
wallpaper: "ພາບພື້ນຫລັງ"
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
+searchWith: "ຊອàºàº«àº²: {q}"
+proxyAccount: "ບັນຊີພຣັອàºàºŠàºµ"
+host: "ໂຮດສ"
+selectUser: "ເລືອàºàºœàº¹à»‰à»ƒàºŠà»‰"
+recipient: "ເຖິງ"
+annotation: "ຄຳເຫັນ"
+federation: "ສະຫະພັນ"
instances: "ອີນສະà»àº•ນ"
+registeredAt: "ລົງທະບຽນຢູ່"
+storageUsage: "ບ່ອນ​ຈັດ​ເàºàº±àºšâ€‹àº‚à»à»‰â€‹àº¡àº¹àº™àº—ີ່ໃຊ້"
+charts: "ອັນດັບເພງ"
+perHour: "ຕà»à»ˆàºŠàº»à»ˆàº§à»‚ມງ"
+perDay: "ຕà»à»ˆâ€‹àº¡àº·à»‰"
+stopActivityDelivery: "ຢຸດເຊົາàºàº²àº™àºªàº»à»ˆàº‡àºàº´àº”ຈະàºà»àº²"
+blockThisInstance: "ຂັດຂວາງຕົວຢ່າງນີ້"
+operations: "àºàº²àº™àº”ຳເນີນງານ"
+software: "ຊອບà»àº§"
+version: "ສະບັບ"
+metadata: "Metadata"
+monitor: "ຈà»àºžàº²àºš"
+cpuAndMemory: "CPU à»àº¥àº° ຫນ່ວàºàº„ວາມຈà»àº²"
+network: "ເຄືອຂ່າàº"
+disk: "ດິສàºà»Œ"
instanceInfo: "ອີນສະà»àº•ນ"
statistics: "ສະຖິຕິ"
clearQueue: "ລ້າງຄິວ"
@@ -178,6 +200,7 @@ nsfw: "NSFW"
accept: "ອະນຸàºàº²àº”"
pinnedNotes: "ບັນທຶàºàº—ີ່ປັàºà»àº¸àº”ໄວ້"
userList: "ລາàºàºàº²àº™"
+smtpHost: "ໂຮດສ"
smtpUser: "ຊື່ຜູ້ໃຊ້"
smtpPass: "ລະຫັດຜ່ານ"
clearCache: "ລຶບລ້າງà»àº„ສ"
@@ -195,11 +218,14 @@ _sfx:
note: "ບັນທຶàº"
notification: "àºàº²àº™à»àºˆà»‰àº‡à»€àº•ືອນ"
chat: "à»àºŠà»‹àº”"
+_2fa:
+ renewTOTPCancel: "ບà»à»ˆâ€‹à»àº¡à»ˆàº™â€‹àº•ອນ​ນີ້"
_widgets:
profile: "ໂພຼຟາàº"
instanceInfo: "ອີນສະà»àº•ນ"
notifications: "àºàº²àº™à»àºˆà»‰àº‡à»€àº•ືອນ"
timeline: "​ເສັ້ນàºàº³â€‹àº™àº»àº”​ເວ​ລາ​"
+ federation: "ສະຫະພັນ"
_userList:
chooseList: "ເລືອàºàºšàº±àº™àºŠàºµàº¥àº²àºàºàº²àº™"
_cw:
@@ -214,6 +240,8 @@ _exportOrImport:
muteList: "ປີດສຽງ"
blockingList: "ບ໋ອàº"
userLists: "ລາàºàºàº²àº™"
+_charts:
+ federation: "ສະຫະພັນ"
_timelines:
home: "ໜ້າຫຼັàº"
_pages:
diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml
index a05d106652..3d33b5227e 100644
--- a/locales/nl-NL.yml
+++ b/locales/nl-NL.yml
@@ -376,13 +376,10 @@ about: "Over"
aboutMisskey: "Over Misskey"
administrator: "Beheerder"
token: "Token"
-twoStepAuthentication: "Tweestapsverificatie"
moderator: "Moderator"
moderation: "Moderatie"
nUsersMentioned: "Vermeld door {n} gebruikers"
securityKey: "Beveiligingssleutel"
-securityKeyName: "Sleutelnaam"
-registerSecurityKey: "Zekerheids-Sleutel registreren"
lastUsed: "Laatst gebruikt"
unregister: "Uitschrijven"
passwordLessLogin: "Inloggen zonder wachtwoord"
@@ -399,8 +396,6 @@ markAsReadAllTalkMessages: "Markeer alle berichten als gelezen"
help: "Help"
inputMessageHere: "Voer hier je bericht in"
close: "Sluiten"
-group: "Groep"
-groups: "Groepen"
invites: "Uitnodigen"
invitations: "Uitnodigen"
sound: "Geluid"
@@ -435,6 +430,8 @@ _sfx:
note: "Notities"
notification: "Meldingen"
chat: "Chat"
+_2fa:
+ renewTOTPCancel: "Nee, bedankt"
_widgets:
profile: "Profiel"
instanceInfo: "Serverinformatie"
diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml
index 0874dded9c..3003e93254 100644
--- a/locales/pl-PL.yml
+++ b/locales/pl-PL.yml
@@ -385,13 +385,10 @@ about: "Informacje"
aboutMisskey: "O Misskey"
administrator: "Admin"
token: "Token"
-twoStepAuthentication: "Uwierzytelnianie dwuskładnikowe"
moderator: "Moderator"
moderation: "Moderacja"
nUsersMentioned: "{n} wspomnianych użytkowników"
securityKey: "Klucz bezpieczeństwa"
-securityKeyName: "Nazwa klucza"
-registerSecurityKey: "Zarejestruj klucz bezpieczeństwa"
lastUsed: "Ostatnio używane"
unregister: "Cofnij rejestracjÄ™"
passwordLessLogin: "Skonfiguruj logowanie bez użycia hasła"
@@ -409,24 +406,15 @@ markAsReadAllTalkMessages: "Oznacz wszystkie wiadomości jako przeczytane"
help: "Pomoc"
inputMessageHere: "Wprowadź wiadomość tutaj"
close: "Zamknij"
-group: "Grupy"
-groups: "Grupy"
-createGroup: "Utwórz grupę"
-ownedGroups: "Posiadane grupy"
-joinedGroups: "Członkostwa w grupach"
invites: "ZaproÅ›"
-groupName: "Nazwa grupy"
members: "Członkowie"
transfer: "Transfer"
-messagingWithUser: "Rozmowy z innym użytkownikiem"
-messagingWithGroup: "Rozmowy wewnÄ…trz grupy"
title: "Tytuł"
text: "Tekst"
enable: "Włącz"
next: "Dalej"
retype: "Wprowadź ponownie"
noteOf: "Wpisy {user}"
-inviteToGroup: "ZaproÅ› do grupy"
quoteAttached: "Zacytowano"
quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
noMessagesYet: "Nie napisano jeszcze wiadomości"
@@ -448,17 +436,13 @@ passwordMatched: "Pasuje"
passwordNotMatched: "Hasła nie pasują do siebie"
signinWith: "Zaloguj siÄ™ z {x}"
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są nieprawidłowe."
-tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
or: "Lub"
language: "Język"
uiLanguage: "Język wyświetlania UI"
-groupInvited: "Zaproszony(-a) do grupy"
aboutX: "O {x}"
emojiStyle: "Styl emoji"
native: "Natywny"
disableDrawer: "Nie używaj menu w stylu szuflady"
-youHaveNoGroups: "Nie masz żadnych grup"
-joinOrCreateGroup: "Uzyskaj zaproszenie do dołączenia do grupy lub utwórz własną grupę."
noHistory: "Brak historii"
signinHistory: "Historia logowania"
doing: "Przetwarzanie..."
@@ -816,8 +800,6 @@ deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kont
incorrectPassword: "Nieprawidłowe hasło."
voteConfirm: "Potwierdzić swój głos na \"{choice}\"?"
hide: "Ukryj"
-leaveGroup: "Opuść grupę"
-leaveGroupConfirm: "Czy na pewno chcesz opuścić \"{name}\"?"
useDrawerReactionPickerForMobile: "Wyświetlaj wybornik reakcji jako szufladę na urządzeniach mobilnych"
welcomeBackWithName: "Witaj z powrotem, {name}"
clickToFinishEmailVerification: "Kliknij [{ok}], aby zakończyć weryfikację e-mail."
@@ -1112,12 +1094,12 @@ _tutorial:
step8_3: "Ustawienia powiadomień można zmienić później."
_2fa:
alreadyRegistered: "Zarejestrowałeś już urządzenie do uwierzytelniania dwuskładnikowego."
- registerDevice: "Zarejestruj nowe urzÄ…dzenie"
- registerKey: "Zarejestruj klucz bezpieczeństwa"
step1: "Najpierw, zainstaluj aplikacjÄ™ uwierzytelniajÄ…cÄ… (takÄ… jak {a} lub {b}) na swoim urzÄ…dzeniu."
step2: "Następnie, zeskanuje kod QR z ekranu."
step3: "Wprowadź token podany w aplikacji, aby ukończyć konfigurację."
step4: "Od teraz, przy każdej próbie logowania otrzymasz prośbę o token logowania."
+ removeKeyConfirm: "Usunąć kopię zapasową {name}?"
+ renewTOTPCancel: "Nie teraz"
_permissions:
"read:account": "Wyświetl informacje o swoim koncie"
"write:account": "Edytuj swoje informacje o koncie"
@@ -1328,12 +1310,9 @@ _notification:
youGotReply: "{name} odpowiedział(a) Tobie"
youGotQuote: "{name} zacytował(a) Ciebie"
youRenoted: "{name} udostępnił(a) Twój wpis"
- youGotMessagingMessageFromUser: "{name} wysłał(a) Ci wiadomość"
- youGotMessagingMessageFromGroup: "Została wysłana wiadomość do grupy {name}"
youWereFollowed: "Zaobserwował(a) Cię"
youReceivedFollowRequest: "Otrzymałeś(-aś) prośbę o możliwość obserwacji"
yourFollowRequestAccepted: "Twoja prośba o możliwość obserwacji została przyjęta"
- youWereInvitedToGroup: "Zaproszony(-a) do grupy"
pollEnded: "Wyniki ankiety stały się dostępne"
unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Powiadomienia push zostały zaktualizowane"
@@ -1347,7 +1326,6 @@ _notification:
reaction: "Reakcja"
receiveFollowRequest: "Otrzymano prośbę o możliwość obserwacji"
followRequestAccepted: "Przyjęto prośbę o możliwość obserwacji"
- groupInvited: "Zaproszono do grup"
app: "Powiadomienia z aplikacji"
_actions:
followBack: "zaobserwował cię z powrotem"
diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml
index 6ca41a395f..40b4aee7e6 100644
--- a/locales/pt-PT.yml
+++ b/locales/pt-PT.yml
@@ -382,12 +382,9 @@ about: "Informações"
aboutMisskey: "Sobre Misskey"
administrator: "Administrador"
token: "Símbolo"
-twoStepAuthentication: "Verificação em duas etapas"
moderator: "Moderador"
nUsersMentioned: "Postado por {n} pessoas"
securityKey: "Chave de segurança"
-securityKeyName: "Nome chave"
-registerSecurityKey: "Registre a chave de segurança"
lastUsed: "Último uso"
unregister: "Cancelar registro"
passwordLessLogin: "Entrar sem senha"
@@ -405,10 +402,6 @@ markAsReadAllTalkMessages: "Marcar todas as conversas como lidas"
help: "Ajuda"
inputMessageHere: "Escrever mensagem aqui"
close: "Fechar"
-group: "Grupos"
-groups: "Grupos"
-createGroup: "Criar grupo"
-ownedGroups: "Grupo próprio"
invites: "Convidar"
invitations: "Convidar"
tags: "Etiquetas"
@@ -522,12 +515,9 @@ _notification:
youGotMention: "{name} te mencionou"
youGotReply: "{name} te respondeu"
youGotQuote: "{name} te citou"
- youGotMessagingMessageFromUser: "{name} te mandou uma mensagem de bate-papo"
- youGotMessagingMessageFromGroup: "Uma mensagem foi mandada para o grupo {name}"
youWereFollowed: "Você tem um novo seguidor"
youReceivedFollowRequest: "Você recebeu um pedido de seguimento"
yourFollowRequestAccepted: "Seu pedido de seguimento foi aceito"
- youWereInvitedToGroup: "{userName} te convidou para um grupo"
pollEnded: "Os resultados da enquete agora estão disponíveis"
emptyPushNotificationMessage: "As notificações de alerta foram atualizadas"
_types:
@@ -541,7 +531,6 @@ _notification:
pollEnded: "Enquetes terminando"
receiveFollowRequest: "Recebeu pedidos de seguimento"
followRequestAccepted: "Aceitou pedidos de seguimento"
- groupInvited: "Convites de grupo"
app: "Notificações de aplicativos conectados"
_actions:
followBack: "te seguiu de volta"
diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml
index 551652ef46..c3438172ca 100644
--- a/locales/ro-RO.yml
+++ b/locales/ro-RO.yml
@@ -382,12 +382,9 @@ about: "Despre"
aboutMisskey: "Despre Misskey"
administrator: "Administrator"
token: "Token"
-twoStepAuthentication: "Autentificare în doi pași"
moderator: "Moderator"
nUsersMentioned: "Menționat de {n} utilizatori"
securityKey: "Cheie de securitate"
-securityKeyName: "Numele cheii"
-registerSecurityKey: "Înregistrează o cheie de securitate"
lastUsed: "Ultima utilizată"
unregister: "Dezînregistrează"
passwordLessLogin: "Autentificare fără parolă"
@@ -405,24 +402,15 @@ markAsReadAllTalkMessages: "Marchează toate mesajele drept citit"
help: "Ajutor"
inputMessageHere: "Introdu un mesaj aici"
close: "ÃŽnchide"
-group: "Grup"
-groups: "Grupuri"
-createGroup: "Crează un grup"
-ownedGroups: "Grupuri deținute"
-joinedGroups: "Grupuri alăturate"
invites: "Invită"
-groupName: "Numele grupului"
members: "Membri"
transfer: "Transferă"
-messagingWithUser: "Chat privat"
-messagingWithGroup: "Chat de grup"
title: "Titlu"
text: "Text"
enable: "Activează"
next: "Următorul"
retype: "Introdu din nou"
noteOf: "Notă de {user}"
-inviteToGroup: "Invită în grup"
quoteAttached: "Citat"
quoteQuestion: "Vrei să adaugi ca citat?"
noMessagesYet: "Niciun mesaj încă"
@@ -444,15 +432,11 @@ passwordMatched: "Se potrivește!"
passwordNotMatched: "Nu se potrivește"
signinWith: "Autentifică-te cu {x}"
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte."
-tapSecurityKey: "Apasă pe cheia ta de securitate."
or: "Sau"
language: "Limbă"
uiLanguage: "Limba interfeței"
-groupInvited: "Ai fost invitat într-un grup"
aboutX: "Despre {x}"
disableDrawer: "Nu folosi meniuri în stil sertar"
-youHaveNoGroups: "Nu ai niciun grup"
-joinOrCreateGroup: "Primește o invitație într-un grup sau creează unul nou."
noHistory: "Nu există istoric"
signinHistory: "Istoric autentificări"
doing: "Se procesează..."
@@ -699,7 +683,6 @@ _pages:
image: "Imagini"
_notification:
youWereFollowed: "te-a urmărit"
- youWereInvitedToGroup: "Ai fost invitat într-un grup"
_types:
follow: "Urmărești"
mention: "Mențiune"
diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml
index 1abd79c983..70839694b4 100644
--- a/locales/ru-RU.yml
+++ b/locales/ru-RU.yml
@@ -8,7 +8,7 @@ search: "ПоиÑк"
notifications: "УведомлениÑ"
username: "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
password: "Пароль"
-forgotPassword: "Пароль забыт"
+forgotPassword: "Забыли пароль?"
fetchingAsApObject: "Приём Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… Ñайтов"
ok: "Окей"
gotIt: "ЯÑно!"
@@ -103,6 +103,8 @@ renoted: "РепоÑÑ‚ Ñовершён."
cantRenote: "Это Ð½ÐµÐ»ÑŒÐ·Ñ Ñ€ÐµÐ¿Ð¾Ñтить."
cantReRenote: "Ðевозможно репоÑтить репоÑÑ‚."
quote: "Цитата"
+inChannelRenote: "В канале"
+inChannelQuote: "Заметки в канале"
pinnedNote: "Ð—Ð°ÐºÑ€ÐµÐ¿Ð»Ñ‘Ð½Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÑ‚ÐºÐ°"
pinned: "Закрепить в профиле"
you: "Ð’Ñ‹"
@@ -129,6 +131,7 @@ unblockConfirm: "Разблокировать Ñтот аккаунт?"
suspendConfirm: "Заморозить Ñтот аккаунт?"
unsuspendConfirm: "Разморозить Ñтот аккаунт?"
selectList: "Выберите ÑпиÑок"
+selectChannel: "Выберите канал"
selectAntenna: "Выберите антенну"
selectWidget: "Выберите виджет"
editWidgets: "Редактировать виджеты"
@@ -256,6 +259,8 @@ noMoreHistory: "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð°ÐºÐ¾Ð½Ñ‡Ð¸Ð»Ð°ÑÑŒ"
startMessaging: "Ðачать общение"
nUsersRead: "Прочитали {n}"
agreeTo: "Я ÑоглашаюÑÑŒ Ñ {0}"
+agreeBelow: "СоглаÑен Ñо Ñледующими"
+basicNotesBeforeCreateAccount: "ЗапиÑи, перед Ñозданием аккаунта"
tos: "ПользовательÑкое Ñоглашение"
start: "Ðачать"
home: "ГлавнаÑ"
@@ -351,6 +356,8 @@ recaptcha: "reCAPTCHA"
enableRecaptcha: "Включить reCAPTCHA"
recaptchaSiteKey: "Ключ Ñайта"
recaptchaSecretKey: "Секретный ключ"
+turnstile: "Ð¡ÐµÑ€Ð²Ð¸Ñ Turnstile"
+enableTurnstile: "Включить Turnstile"
turnstileSiteKey: "Ключ Ñайта"
turnstileSecretKey: "Секретный ключ"
avoidMultiCaptchaConfirm: "ÐеÑколько ÑпоÑобов проверки могут мешать друг другу. Подтвердите, еÑли хотите отключить другие ÑпоÑобы. Или нажмите «Отмена», чтобы оÑтавить их включёнными."
@@ -386,13 +393,10 @@ about: "ОпиÑание"
aboutMisskey: "О Misskey"
administrator: "ÐдминиÑтратор"
token: "Токен"
-twoStepAuthentication: "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
moderator: "Модератор"
moderation: "МодерациÑ"
nUsersMentioned: "УпомÑнуло пользователей: {n}"
securityKey: "Ключ безопаÑноÑти"
-securityKeyName: "Ð˜Ð¼Ñ ÐºÐ»ÑŽÑ‡Ð°"
-registerSecurityKey: "ЗарегиÑтрировать защитный ключ"
lastUsed: "ПоÑледнее иÑпользование"
unregister: "ОтпиÑатьÑÑ"
passwordLessLogin: "ÐаÑтроить вход без паролÑ"
@@ -410,24 +414,15 @@ markAsReadAllTalkMessages: "Отметить вÑе реплики как про
help: "Помощь"
inputMessageHere: "Введите Ñообщение здеÑÑŒ"
close: "Закрыть"
-group: "Группа"
-groups: "Группы"
-createGroup: "Создать группу"
-ownedGroups: "СобÑтвенные группы"
-joinedGroups: "УчаÑтие в группах"
invites: "ПриглашениÑ"
-groupName: "Ðазвание группы"
members: "УчаÑтники"
transfer: "Отдать"
-messagingWithUser: "Общение Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ пользователем"
-messagingWithGroup: "Общение в группе"
title: "Заголовок"
text: "ТекÑÑ‚"
enable: "Включить"
next: "Дальше"
retype: "Введите ещё раз"
noteOf: "Что пишет {user}"
-inviteToGroup: "ПриглаÑить в группу"
quoteAttached: "Цитата"
quoteQuestion: "Хотите добавить цитату?"
noMessagesYet: "Пока ни одного ÑообщениÑ"
@@ -449,19 +444,17 @@ passwordMatched: "Совпали"
passwordNotMatched: "Ðе Ñовпадают"
signinWith: "ИÑпользовать {x} Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°"
signinFailed: "Ðевозможно войти в ÑиÑтему. Введенное вами Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль неверны."
-tapSecurityKey: "Ðажмите на Ñвой Ñлектронный ключ"
or: "или"
language: "Язык"
uiLanguage: "Язык интерфейÑа"
-groupInvited: "Приглашение в группу"
aboutX: "ОпиÑание {x}"
emojiStyle: "Стиль Ñмодзи"
native: "СиÑтемные"
disableDrawer: "Ðе иÑпользовать выдвижные меню"
-youHaveNoGroups: "У Ð²Ð°Ñ Ð½ÐµÑ‚ ни одной группы"
-joinOrCreateGroup: "Получайте Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð² группы или Ñоздавайте Ñвои ÑобÑтвенные"
noHistory: "ИÑÑ‚Ð¾Ñ€Ð¸Ñ Ð¿Ð¾ÐºÐ° пуÑта"
signinHistory: "Журнал поÑещений"
+enableAdvancedMfm: "Включить раÑширенный MFM"
+enableAnimatedMfm: "Включить анимированную разметку MFM"
doing: "Ð’ процеÑÑе"
category: "КатегориÑ"
tags: "Метки"
@@ -831,8 +824,6 @@ deleteAccountConfirm: "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ будет безвозвра
incorrectPassword: "Пароль неверен."
voteConfirm: "Отдать Ð³Ð¾Ð»Ð¾Ñ Ð·Ð° «{choice}»?"
hide: "СпрÑтать"
-leaveGroup: "Покинуть группу"
-leaveGroupConfirm: "Покинуть группу «{name}»?"
useDrawerReactionPickerForMobile: "Ð’Ñ‹Ð´Ð²Ð¸Ð¶Ð½Ð°Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð° на мобильном уÑтройÑтве"
welcomeBackWithName: "С возвращением, {name}!"
clickToFinishEmailVerification: "ПожалуйÑта, нажмите [{ok}], чтобы завершить подтверждение адреÑа Ñлектронной почты."
@@ -855,8 +846,11 @@ oneDay: "1 день"
oneWeek: "1 неделÑ"
reflectMayTakeTime: "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ занÑть Ð²Ñ€ÐµÐ¼Ñ Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ"
failedToFetchAccountInformation: "Ðе удалоÑÑŒ получить информацию об аккаунте"
+rateLimitExceeded: "Ограничение ÑкороÑти превышено"
cropImage: "Кадрирование"
cropImageAsk: "Ðужно ли кадрировать изображение?"
+cropYes: "Обрезать"
+cropNo: "Ðе обрезать"
file: "Файлы"
recentNHours: "ПоÑледние {n} ч"
recentNDays: "ПоÑледние {n} Ñут"
@@ -883,6 +877,8 @@ refreshInterval: "Интервал перезагрузки"
label: "Метка"
type: "Тип"
speed: "СкороÑть"
+slow: "МедленнаÑ"
+fast: "БыÑтраÑ"
sensitiveMediaDetection: "Определение Ñодержимого деликатного характера"
localOnly: "Локально"
remoteOnly: "Только удалённо"
@@ -933,6 +929,16 @@ cannotPerformTemporaryDescription: "Это дейÑтвие временно нÐ
preset: "Шаблоны"
selectFromPresets: "Выбрать из шаблонов"
achievements: "ДоÑтижениÑ"
+gotInvalidResponseError: "Сервер ответил ошибкой"
+gotInvalidResponseErrorDescription: "Сервер временно не доÑтупен. Возможно проводÑÑ‚ÑÑ Ñ‚ÐµÑ…Ð½Ð¸Ñ‡ÐµÑкие работы, или Ñервер отключен."
+thisPostMayBeAnnoying: "Это Ñообщение может быть неприÑтным."
+thisPostMayBeAnnoyingHome: "Этот поÑÑ‚ может быть отправлен на главную"
+thisPostMayBeAnnoyingCancel: "Этот поÑÑ‚ не может быть отменен."
+thisPostMayBeAnnoyingIgnore: "Этот поÑÑ‚ может быть проигнорирован "
+collapseRenotes: "Свернуть репоÑты"
+internalServerError: "ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° Ñервера"
+internalServerErrorDescription: "Внутри Ñервера произошла Ð½ÐµÐ¿Ñ€ÐµÐ´Ð²Ð¸Ð´ÐµÐ½Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°."
+copyErrorInfo: "Скопировать код ошибки"
_achievements:
earnedAt: "Разблокировано в"
_types:
@@ -1189,6 +1195,9 @@ _role:
baseRole: "Шаблон роли"
useBaseValue: "ИÑпользовать значение из шаблона"
chooseRoleToAssign: "Выберите роль, которую хотите выдать"
+ iconUrl: "ÐÐ´Ñ€ÐµÑ Ð½Ð° иконку роли"
+ asBadge: "Показывать как значок"
+ descriptionOfAsBadge: "ОпиÑание значка"
canEditMembersByModerator: "Могут назначать модераторы"
descriptionOfCanEditMembersByModerator: "ЕÑли включено, на Ñту роль могут назначать пользователей как админиÑтраторы, так и модераторы. ЕÑли выключено, назначать могут только админиÑтраторы."
priority: "Приоритет"
@@ -1206,6 +1215,7 @@ _role:
pinMax: "ДоÑтупное количеÑтво закреплённых заметок"
antennaMax: "ДоÑтупное количеÑтво антенн"
wordMuteMax: "ДоÑтупное количеÑтво знаков в ÑпиÑке ÑÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñлов"
+ webhookMax: "МакÑимум web-хуков"
clipMax: "МакÑимальное количеÑтво подборок"
noteEachClipsMax: "МакÑимальное количеÑтво заметок в подборке"
userListMax: "МакÑимальное количеÑтво ÑпиÑков аккаунтов"
@@ -1227,7 +1237,12 @@ _role:
not: "Кроме тех, у кого…"
_sensitiveMediaDetection:
description: "Машинное обучение может быть иÑпользовано Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ð¾Ð±Ð½Ð°Ñ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ñ‡ÑƒÐ²Ñтвительных медиа Ð´Ð»Ñ Ð¼Ð¾Ð´ÐµÑ€Ð°Ñ†Ð¸Ð¸. Ðагрузка на Ñервер увеличиваетÑÑ Ð½ÐµÐ·Ð½Ð°Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾."
+ sensitivity: "ЧувÑтвительноÑть обнаружениÑ"
+ sensitivityDescription: "Более Ð½Ð¸Ð·ÐºÐ°Ñ Ñ‡ÑƒÐ²ÑтвительноÑть уменьшает количеÑтво ложных Ñрабатываний (false positives). Повышение чувÑтвительноÑти уменьшает утечку при обнаружении (ложноотрицательные результаты)."
setSensitiveFlagAutomatically: "УÑтановить флаг NSFW"
+ setSensitiveFlagAutomaticallyDescription: "Даже еÑли Ñтот параметр отключен, результат оценки ÑохранÑетÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ ÑиÑтемы."
+ analyzeVideos: "Ðнализировать видео?"
+ analyzeVideosDescription: "Ðнализируйте видео в дополнение к неподвижным изображениÑм. Ðагрузка на Ñервер немного увеличиваетÑÑ."
_emailUnavailable:
used: "Уже иÑпользуетÑÑ"
format: "Ðеверный формат"
@@ -1470,14 +1485,14 @@ _tutorial:
step8_3: "Эту наÑтройку вы вÑегда Ñможете поменÑть"
_2fa:
alreadyRegistered: "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑƒÐ¶Ðµ наÑтроена."
- registerDevice: "ЗарегиÑтрируйте ваше уÑтройÑтво"
- registerKey: "ЗарегиÑтрировать ключ"
step1: "Прежде вÑего, уÑтановите на уÑтройÑтво приложение Ð´Ð»Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸, например, {a} или {b}."
step2: "Далее отÑканируйте отображаемый QR-код при помощи приложениÑ."
step2Url: "ЕÑли пользуетеÑÑŒ приложением на компьютере, можете ввеÑти в него Ñту Ñтроку (URL):"
step3: "И наконец, введите код, который покажет приложение."
step4: "Теперь при каждом входе на Ñайт вам нужно будет вводить код из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñ‡Ð½Ñ‹Ð¼ образом."
securityKeyInfo: "Ð’Ñ‹ можете наÑтроить вход Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ аппаратного ключа безопаÑноÑти, поддерживающего FIDO2, или отпечатка пальца или PIN-кода на уÑтройÑтве."
+ removeKeyConfirm: "Удалить резервную копию «{name}»?"
+ renewTOTPCancel: "Ðет, ÑпаÑибо"
_permissions:
"read:account": "ПроÑматривать данные учётной запиÑи"
"write:account": "ИзменÑть данные учётной запиÑи"
@@ -1512,18 +1527,20 @@ _permissions:
"read:gallery-likes": "ПроÑмотр ÑпиÑка понравившегоÑÑ Ð² галерее"
"write:gallery-likes": "Изменение ÑпиÑка понравившегоÑÑ Ð² галерее"
_auth:
+ shareAccessTitle: "Ð Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹"
shareAccess: "Дать доÑтуп Ð´Ð»Ñ Â«{name}» к вашей учётной запиÑи?"
shareAccessAsk: "Уверены, что хотите дать приложению доÑтуп к Ñвоей учётной запиÑи?"
+ permission: "{name} Запрашивает Ñледующие разрешениÑ:"
permissionAsk: "Приложение запрашивает Ñледующие разрешениÑ:"
pleaseGoBack: "ВернитеÑÑŒ, пожалуйÑта, в приложение"
callback: "Возврат в приложение"
denied: "ДоÑтуп закрыт"
+ pleaseLogin: "Ð’Ñ‹ должны войти в ÑиÑтему, чтобы дать разрешение приложению."
_antennaSources:
all: "Ð’Ñе заметки"
homeTimeline: "Заметки тех на которых вы подпиÑаны"
users: "Заметки выбранных пользователей"
userList: "Заметки пользователей из выбранных ÑпиÑков"
- userGroup: "Заметки от пользователей из заданной группы"
_weekday:
sunday: "ВоÑкреÑенье"
monday: "Понедельник"
@@ -1598,8 +1615,6 @@ _visibility:
followersDescription: "Только вашим подпиÑчикам"
specified: "Личное"
specifiedDescription: "Тем, кого укажете"
- localOnly: "Локально"
- localOnlyDescription: "Только Ð´Ð»Ñ Ñтого Ñайта"
_postForm:
replyPlaceholder: "Ответ на заметку..."
quotePlaceholder: "ПоÑÑнение к цитате..."
@@ -1664,7 +1679,16 @@ _timelines:
social: "СоциальнаÑ"
global: "Ð’ÑеобщаÑ"
_play:
+ new: "Создать приложение "
+ edit: "Редактировать приложение"
+ created: "Приложение Ñоздано"
+ updated: "Приложение обновлено"
+ deleted: "Приложение удалено"
+ pageSetting: "ÐаÑтройки приложениÑ"
+ editThisPage: "Отредактировать Ñтраницу"
viewSource: "ПроÑмотр иÑходника"
+ my: "Мои Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ "
+ liked: "ПонравилоÑÑŒ"
featured: "ПопулÑрные"
title: "Заголовок"
script: "Скрипт"
@@ -1728,13 +1752,11 @@ _notification:
youGotReply: "{name} отвечает вам."
youGotQuote: "{name} цитирует ваÑ."
youRenoted: "{name} передаёт вашу заметку."
- youGotMessagingMessageFromUser: "{name} пишет вам."
- youGotMessagingMessageFromGroup: "Ðовое Ñообщение в группе «{name}»."
youWereFollowed: "У Ð²Ð°Ñ Ð½Ð¾Ð²Ñ‹Ð¹ подпиÑчик."
youReceivedFollowRequest: "У Ð²Ð°Ñ Ð½Ð¾Ð²Ñ‹Ð¹ Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑку."
yourFollowRequestAccepted: "Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑку одобрен."
- youWereInvitedToGroup: "Вы приглашены в группу."
pollEnded: "Подведены окончательные итоги опроÑа"
+ unreadAntennaNote: "Ðнтенна {name}"
emptyPushNotificationMessage: "Обновлены push-уведомлениÑ"
achievementEarned: "Получено доÑтижение"
_types:
@@ -1748,7 +1770,6 @@ _notification:
pollEnded: "ÐžÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€Ð¾Ñов"
receiveFollowRequest: "Получен Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑку"
followRequestAccepted: "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° подпиÑку одобрен"
- groupInvited: "Приглашение в группы"
app: "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· приложений"
_actions:
followBack: "отвечает взаимной подпиÑкой"
diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml
index 844243ffec..f55fdf9795 100644
--- a/locales/sk-SK.yml
+++ b/locales/sk-SK.yml
@@ -388,13 +388,10 @@ about: "Informácie"
aboutMisskey: "O Misskey"
administrator: "Administrátor"
token: "Token"
-twoStepAuthentication: "Dvojfaktorová autentifikácia"
moderator: "Moderátor"
moderation: "Moderovanie"
nUsersMentioned: "{n} používateľov spomenulo"
securityKey: "BezpeÄnostný kľúÄ"
-securityKeyName: "Názov kľúÄa"
-registerSecurityKey: "RegistrovaÅ¥ bezpeÄnostný kľúÄ"
lastUsed: "Naposledy použité"
unregister: "Odregistrovať"
passwordLessLogin: "Nastaviť bezheslové prihlásenie"
@@ -412,24 +409,15 @@ markAsReadAllTalkMessages: "OznaÄiÅ¥ vÅ¡etky správy ako preÄítané"
help: "Pomoc"
inputMessageHere: "Sem napíšte správu"
close: "Zavrieť"
-group: "Skupina"
-groups: "Skupiny"
-createGroup: "Vytvoriť skupinu"
-ownedGroups: "Vlastnené skupiny"
-joinedGroups: "Členstvo v skupinách"
invites: "Pozvať"
-groupName: "Názov skupiny"
members: "ÄŒlenovia"
transfer: "Presun"
-messagingWithUser: "Súkromný chat"
-messagingWithGroup: "Skupinový chat"
title: "Nadpis"
text: "Text"
enable: "Povoliť"
next: "Ďalší"
retype: "Zadajte znovu"
noteOf: "Poznámky používateľa {user}"
-inviteToGroup: "Pozvať do skupiny"
quoteAttached: "Citované"
quoteQuestion: "Pripojiť ako citát?"
noMessagesYet: "Zatiaľ žiadne správy"
@@ -451,17 +439,13 @@ passwordMatched: "Heslá sú rovnaké"
passwordNotMatched: "Heslá nie sú rovnaké"
signinWith: "Prihlásiť sa použitím {x}"
signinFailed: "Nedá sa prihlásiť. Skontrolujte prosím meno používateľa a heslo."
-tapSecurityKey: "Ťuknite na bezpeÄnostný kľúÄ"
or: "Alebo"
language: "Jazyk"
uiLanguage: "Jazyk používateľského prostredia"
-groupInvited: "Pozvať do skupiny"
aboutX: "O {x}"
emojiStyle: "Štýl emoji"
native: "Natívne"
disableDrawer: "Nepoužívať šuflíkové menu"
-youHaveNoGroups: "Nemáte žiadne skupiny"
-joinOrCreateGroup: "Požiadajte o pozvanie do existujúcej skupiny alebo vytvorte novú."
noHistory: "Žiadna história"
signinHistory: "História prihlásení"
doing: "Pracujem..."
@@ -832,8 +816,6 @@ deleteAccountConfirm: "Toto nezvrátiteľne vymaže váš úÄet. PokraÄovaÅ¥?"
incorrectPassword: "Nesprávne heslo."
voteConfirm: "Potvrdzujete svoj hlas za \"{choice}\"?"
hide: "Skryť"
-leaveGroup: "Opustiť skupiny"
-leaveGroupConfirm: "Naozaj chcete opustiť \"{name}\"?"
useDrawerReactionPickerForMobile: "Zobraziť výber reakcií ako šuflík na mobile"
welcomeBackWithName: "Vitajte späť, {name}"
clickToFinishEmailVerification: "Kliknutím na [{ok}] dokonÄíte overeniu emailu."
@@ -1174,14 +1156,14 @@ _tutorial:
step8_3: "Nastavenia notifikácií môžete neskôr zmeniť."
_2fa:
alreadyRegistered: "Už ste zaregistrovali 2-faktorové autentifikaÄné zariadenie."
- registerDevice: "Registrovať nové zariadenie"
- registerKey: "RegistrovaÅ¥ bezpeÄnostný kľúÄ"
step1: "Najprv si nainÅ¡talujte autentifikaÄnú aplikáciu (napríklad {a} alebo {b}) na svoje zariadenie."
step2: "Potom, naskenujte QR kód zobrazený na obrazovke."
step2Url: "Do aplikácie zadajte nasledujúcu URL adresu:"
step3: "Nastavenie dokonÄíte zadaním tokenu z vaÅ¡ej aplikácie."
step4: "Od teraz, vÅ¡etky ÄalÅ¡ie prihlásenia budú vyžadovaÅ¥ prihlasovací token."
securityKeyInfo: "Okrem odtlaÄku prsta alebo PIN autentifikácie si môžete nastaviÅ¥ autentifikáciu cez hardvérový bezpeÄnostný kÄ¾ÃºÄ podporujúci FIDO2 a tak eÅ¡te viac zabezpeÄiÅ¥ svoj úÄet."
+ removeKeyConfirm: "Naozaj chcete odstrániť \"{name}\"?"
+ renewTOTPCancel: "Nie, Äakujem"
_permissions:
"read:account": "VidieÅ¥ informácie o vaÅ¡om úÄte"
"write:account": "UpraviÅ¥ informácie o vaÅ¡om úÄte"
@@ -1227,7 +1209,6 @@ _antennaSources:
homeTimeline: "Poznámky od sledovaného používateľa"
users: "Poznámky od konkrétneho používateľa"
userList: "Poznámky od používateľov v zozname"
- userGroup: "Poznámky od používateľov z konkrétnej skupiny."
_weekday:
sunday: "Nedeľa"
monday: "Pondelok"
@@ -1299,8 +1280,6 @@ _visibility:
followersDescription: "Viditeľné iba tým, ktorí vás sledujú"
specified: "Priame"
specifiedDescription: "Viditeľné iba pre konkrétnych používateľov"
- localOnly: "Iba lokálne"
- localOnlyDescription: "Vzdialený používatelia nebudú vidieť"
_postForm:
replyPlaceholder: "OdpoveÄ na túto poznámku..."
quotePlaceholder: "Citovanie tejto poznámky..."
@@ -1428,12 +1407,9 @@ _notification:
youGotReply: "{name} vám odpovedal/a"
youGotQuote: "{name} vás citoval/a"
youRenoted: "{name} preposlal/a vašu poznámku"
- youGotMessagingMessageFromUser: "{name} vám poslal/a správu"
- youGotMessagingMessageFromGroup: "Prišla správa do skupiny {name}"
youWereFollowed: "Máte nového sledujúceho"
youReceivedFollowRequest: "Dostali ste žiadosť o sledovanie"
yourFollowRequestAccepted: "Vaša žiadosť o sledovanie bola prijatá"
- youWereInvitedToGroup: "Pozvať do skupiny"
pollEnded: "Výsledky hlasovania sú k dispozícii."
unreadAntennaNote: "Anténa {name}"
emptyPushNotificationMessage: "Push notifikácie aktualizované"
@@ -1448,7 +1424,6 @@ _notification:
pollEnded: "Hlasovanie skonÄilo"
receiveFollowRequest: "DoruÄené žiadosti o sledovanie"
followRequestAccepted: "Schválené žiadosti o sledovanie"
- groupInvited: "Pozvánky do skupín"
app: "Oznámenia z prepojených aplikácií"
_actions:
followBack: "Sledovať späť\n"
diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml
index 184db2e907..5e66df2076 100644
--- a/locales/sv-SE.yml
+++ b/locales/sv-SE.yml
@@ -383,12 +383,13 @@ _sfx:
notification: "Notifikationer"
chat: "Chatt"
antenna: "Antenner"
+_2fa:
+ renewTOTPCancel: "Nej tack"
_antennaSources:
all: "Alla noter"
homeTimeline: "Noter från följda användare"
users: "Noter från specifika användare"
userList: "Noter från en specificerad lista av användare"
- userGroup: "Noter från användare i en specificerad grupp"
_widgets:
profile: "Profil"
instanceInfo: "Instansinformation"
diff --git a/locales/th-TH.yml b/locales/th-TH.yml
index bea19c3706..2c721e45e1 100644
--- a/locales/th-TH.yml
+++ b/locales/th-TH.yml
@@ -103,6 +103,8 @@ renoted: "รีโน้ตเอาไว้"
cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตไว้ใหม่ได้นะ"
cantReRenote: "ไม่สามารถรีโน้ตเอาไว้ใหม่ได้นะ"
quote: "อ้างคำพูด"
+inChannelRenote: "รีโน้ตช่องà¹à¸Šà¸¥à¹à¸™à¸¥à¹€à¸—่านั้น"
+inChannelQuote: "อ้างช่องเท่านั้น"
pinnedNote: "โน้ตที่ปัà¸à¸«à¸¡à¸¸à¸”เอาไว้"
pinned: "ปัà¸à¸«à¸¡à¸¸à¸”ไปยังโปรไฟล์"
you: "ตัวเอง"
@@ -257,6 +259,8 @@ noMoreHistory: "ในนั้นไม่มีประวัติอีà¸à
startMessaging: "เริ่มà¸à¸²à¸£à¸ªà¸™à¸—นา"
nUsersRead: "อ่านโดย {n}"
agreeTo: "ฉันยอมรับที่จะ {0}"
+agreeBelow: "ฉันยอมรับถึงด้านล่าง"
+basicNotesBeforeCreateAccount: "หมายเหตุสำคัà¸"
tos: "ข้อà¸à¸³à¸«à¸™à¸”à¹à¸¥à¸°à¹€à¸‡à¸·à¹ˆà¸­à¸™à¹„ข"
start: "เริ่มต้น​ใช้งาน​"
home: "หน้าà¹à¸£à¸"
@@ -389,13 +393,10 @@ about: "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š"
aboutMisskey: "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š Misskey"
administrator: "ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸š"
token: "โทเค็น"
-twoStepAuthentication: "ยืนยันตัวตน 2 ชั้น"
moderator: "ผู้ควบคุม"
moderation: "à¸à¸²à¸£à¸à¸¥à¸±à¹ˆà¸™à¸à¸£à¸­à¸‡"
nUsersMentioned: "à¸à¸¥à¹ˆà¸²à¸§à¸–ึงโดยผู้ใช้ {n} รายนี้"
securityKey: "à¸à¸¸à¸à¹à¸ˆà¸„วามปลอดภัย"
-securityKeyName: "ชื่อคีย์"
-registerSecurityKey: "ลงทะเบียนรหัสความปลอดภัยคีย์"
lastUsed: "ใช้ล่าสุด"
unregister: "เลิà¸à¸•ิดตาม"
passwordLessLogin: "เข้าสู่ระบบà¹à¸šà¸šà¹„ม่ใช้รหัสผ่าน"
@@ -413,24 +414,15 @@ markAsReadAllTalkMessages: "ทำเครื่องหมายข้อคà
help: "ช่วยเหลือ"
inputMessageHere: "พิมพ์ข้อความที่นี่"
close: "ปิด"
-group: "à¸à¸¥à¸¸à¹ˆà¸¡"
-groups: "à¸à¸¥à¸¸à¹ˆà¸¡"
-createGroup: "สร้างà¸à¸¥à¸¸à¹ˆà¸¡"
-ownedGroups: "à¸à¸¥à¸¸à¹ˆà¸¡à¸—ี่เป็นเจ้าของ"
-joinedGroups: "เข้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡"
invites: "เชิà¸à¸Šà¸§à¸™"
-groupName: "ชื่อà¸à¸¥à¸¸à¹ˆà¸¡"
members: "สมาชิà¸"
transfer: "ถ่ายโอน"
-messagingWithUser: "à¹à¸Šà¸—ส่วนตัว"
-messagingWithGroup: "à¹à¸Šà¸—à¸à¸¥à¸¸à¹ˆà¸¡"
title: "หัวข้อ"
text: "ข้อความ"
enable: "เปิดใช้งาน"
next: "ถัด​ไป"
retype: "พิมพ์รหัสอีà¸à¸„รั้ง"
noteOf: "โน้ต โดย {ผู้ใช้งาน}"
-inviteToGroup: "ชวนเข้าà¸à¸¥à¸¸à¹ˆà¸¡"
quoteAttached: "อ้างอิง"
quoteQuestion: "นายต้องà¸à¸²à¸£à¸—ี่จะอ้างอิงหรอ?"
noMessagesYet: "ยังไม่มีข้อความนะ"
@@ -452,19 +444,17 @@ passwordMatched: "ถูà¸à¸•้อง!"
passwordNotMatched: "ไม่ถูà¸à¸•้อง"
signinWith: "ลงชื่อเข้าใช้ด้วย {x}"
signinFailed: "ไม่สามารถลงชื่อผู้เข้าใช้ได้ เนื่องจาภชื่อผู้ใช้หรือรหัสผ่านที่คุณป้อนนั้นไม่ถูà¸à¸•้องนะ"
-tapSecurityKey: "à¹à¸•ะคีย์ความปลอดภัย"
or: "หรือ"
language: "ภาษา"
uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้งาน"
-groupInvited: "คุณได้รับเชิà¸à¹ƒà¸«à¹‰à¹€à¸‚้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡"
aboutX: "เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š {x}"
emojiStyle: "สไตล์อิโมจิ"
native: "ภาษาà¹à¸¡à¹ˆ"
disableDrawer: "อย่าใช้ลิ้นชัà¸à¸ªà¹„ตล์เมนู"
-youHaveNoGroups: "คุณยังไม่มีà¸à¸¥à¸¸à¹ˆà¸¡"
-joinOrCreateGroup: "รับเชิà¸à¹€à¸‚้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡à¸«à¸£à¸·à¸­à¸ªà¸£à¹‰à¸²à¸‡à¸à¸¥à¸¸à¹ˆà¸¡à¸‚องคุณเองเลยนะ"
noHistory: "ไม่มีรายà¸à¸²à¸£"
signinHistory: "ประวัติà¸à¸²à¸£à¹€à¸‚้าสู่ระบบ"
+enableAdvancedMfm: "เปิดใช้งาน MFM ขั้นสูง"
+enableAnimatedMfm: "เปิดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™ MFM ด้วยà¹à¸­à¸™à¸´à¹€à¸¡à¸Šà¸±à¹ˆà¸™"
doing: "à¸à¸³à¸¥à¸±à¸‡à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥......"
category: "หมวดหมู่"
tags: "à¹à¸—็à¸"
@@ -834,8 +824,6 @@ deleteAccountConfirm: "à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸™à¸µà¹‰à¸ˆà¸°à¸¥à¸š
incorrectPassword: "รหัสผ่านไม่ถูà¸à¸•้อง"
voteConfirm: "ยืนยันà¸à¸²à¸£à¹‚หวต \"{choice}\" มั้ย?"
hide: "ซ่อน"
-leaveGroup: "ออà¸à¸ˆà¸²à¸à¸à¸¥à¸¸à¹ˆà¸¡"
-leaveGroupConfirm: "คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸­à¸§à¹ˆà¸²à¸•้องà¸à¸²à¸£à¸­à¸­à¸à¸ˆà¸²à¸ \"{name}\""
useDrawerReactionPickerForMobile: "à¹à¸ªà¸”งผล ตัวเลือà¸à¸›à¸à¸´à¸à¸´à¸£à¸´à¸¢à¸²à¹€à¸›à¹‡à¸™à¸¥à¸´à¹‰à¸™à¸Šà¸±à¸à¸šà¸™à¸¡à¸·à¸­à¸–ือ"
welcomeBackWithName: "ยินดีต้อนรับà¸à¸²à¸£à¸à¸¥à¸±à¸šà¸¡à¸²à¸™à¸°à¸„่ะ, {name}"
clickToFinishEmailVerification: "à¸à¸£à¸¸à¸“าคลิภ[{ok}] เพื่อดำเนินà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸­à¸µà¹€à¸¡à¸¥à¹ƒà¸«à¹‰à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์นะ"
@@ -861,6 +849,8 @@ failedToFetchAccountInformation: "ไม่สามารถเรียà¸à¸”à
rateLimitExceeded: "เà¸à¸´à¸™à¸‚ีดจำà¸à¸±à¸”อัตรา"
cropImage: "ครอบตัดรูปภาพ"
cropImageAsk: "คุณต้องà¸à¸²à¸£à¸„รอบตัดรูปภาพนี้อย่างงั้นหรือ?"
+cropYes: "ครอบตัด"
+cropNo: "ใช้ตามที่เป็นอยู่"
file: "ไฟล์"
recentNHours: "ล่าสุด {n} ชั่วโมงที่à¹à¸¥à¹‰à¸§"
recentNDays: "ล่าสุด {n} วันที่à¹à¸¥à¹‰à¸§"
@@ -941,6 +931,14 @@ selectFromPresets: "เลือà¸à¸ˆà¸²à¸à¸à¸²à¸£à¸žà¸£à¸µà¹€à¸‹à¹‡à¸•"
achievements: "ความสำเร็จ"
gotInvalidResponseError: "à¸à¸²à¸£à¸•อบสนองเซิร์ฟเวอร์ไม่ถูà¸à¸•้อง"
gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะà¸à¸³à¸¥à¸±à¸‡à¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸›à¸£à¸±à¸šà¸›à¸£à¸¸à¸‡ à¸à¸£à¸¸à¸“าลองใหม่อีà¸à¸„รั้งในภายหลังนะคะ"
+thisPostMayBeAnnoying: "โน้ตนี้อาจจะเป็นà¸à¸²à¸£à¸£à¸šà¸à¸§à¸™à¸œà¸¹à¹‰à¸­à¸·à¹ˆà¸™à¸™à¸°à¸„ะ"
+thisPostMayBeAnnoyingHome: "โพสต์ไปยังบ้านไทม์ไลน์"
+thisPostMayBeAnnoyingCancel: "เลิà¸"
+thisPostMayBeAnnoyingIgnore: "โพสต์ยังไงà¸à¹‡à¹à¸¥à¹‰à¸§à¹à¸•่"
+collapseRenotes: "ยุบ renotes ที่คุณได้เห็นà¹à¸¥à¹‰à¸§"
+internalServerError: "เซิร์ฟเวอร์ภายในเà¸à¸´à¸”ข้อผิดพลาด"
+internalServerErrorDescription: "เซิร์ฟเวอร์รันค้นพบข้อผิดพลาดที่ไม่คาดคิด"
+copyErrorInfo: "คัดลอà¸à¸£à¸²à¸¢à¸¥à¸°à¹€à¸­à¸µà¸¢à¸”ข้อผิดพลาด"
_achievements:
earnedAt: "ได้รับเมื่อ"
_types:
@@ -1487,14 +1485,14 @@ _tutorial:
step8_3: "คุณสามารถเปลี่ยนà¸à¸²à¸£à¸•ั้งค่านี้ในภายหลังได้ตลอดเวลานะ"
_2fa:
alreadyRegistered: "คุณได้ลงทะเบียนอุปà¸à¸£à¸“์ยืนยันตัวตนà¹à¸šà¸š 2 ชั้นà¹à¸¥à¹‰à¸§"
- registerDevice: "ลงทะเบียนอุปà¸à¸£à¸“์ใหม่"
- registerKey: "ลงทะเบียนรหัสความปลอดภัย"
step1: "ขั้นตอนà¹à¸£à¸ ติดตั้งà¹à¸­à¸›à¸¢à¸·à¸™à¸¢à¸±à¸™à¸•ัวตน (เช่น {a} หรือ {b}) บนอุปà¸à¸£à¸“์ของคุณ"
step2: "จาà¸à¸™à¸±à¹‰à¸™à¸ªà¹à¸à¸™à¸£à¸«à¸±à¸ª QR ที่à¹à¸ªà¸”งบนหน้าจอนี้"
step2Url: "คุณยังสามารถป้อนบน URL นี้หาà¸à¸„ุณใช้โปรà¹à¸à¸£à¸¡à¹€à¸”สà¸à¹Œà¸—็อป:"
step3: "ป้อนโทเค็นที่à¹à¸­à¸›à¸‚องคุณให้มาเพื่อเสร็จสิ้นà¸à¸²à¸£à¸•ั้งค่า"
step4: "นับจาà¸à¸™à¸µà¹‰à¹€à¸›à¹‡à¸™à¸•้นไปà¸à¸²à¸£à¸žà¸¢à¸²à¸¢à¸²à¸¡à¹€à¸‚้าสู่ระบบในอนาคตนั้น อาจจะต้องขอโทเค็นในà¸à¸²à¸£à¹€à¸‚้าสู่ระบบดังà¸à¸¥à¹ˆà¸²à¸§"
securityKeyInfo: "นอà¸à¸ˆà¸²à¸à¸™à¸µà¹‰à¸à¸²à¸£à¸•รวจสอบความถูà¸à¸•้องด้วยลายนิ้วมือหรือ PIN à¹à¸¥à¹‰à¸§ คุณยังสามารถตั้งค่าà¸à¸²à¸£à¸•รวจสอบสิทธิ์ผ่านคีย์ความปลอดภัยของฮาร์ดà¹à¸§à¸£à¹Œà¸—ี่รองรับ FIDO2 เพื่อเพิ่มความปลอดภัยให้à¸à¸±à¸šà¸šà¸±à¸à¸Šà¸µà¸‚องคุณ"
+ removeKeyConfirm: "ลบข้อมูลสำรอง {name} มั้ย?"
+ renewTOTPCancel: "ไม่เป็นไร"
_permissions:
"read:account": "ดูข้อมูลบัà¸à¸Šà¸µà¸‚องคุณ"
"write:account": "à¹à¸à¹‰à¹„ขข้อมูลบัà¸à¸Šà¸µà¸‚องคุณ"
@@ -1543,7 +1541,6 @@ _antennaSources:
homeTimeline: "โน้ตจาà¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸—ี่ติดตาม"
users: "โน้ตจาà¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸—ี่เฉพาะเจาะจง"
userList: "โน้ตจาà¸à¸£à¸²à¸¢à¸Šà¸·à¹ˆà¸­à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¸—ี่ระบุ"
- userGroup: "โน้ตจาà¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰à¹ƒà¸™à¸à¸¥à¸¸à¹ˆà¸¡à¸—ี่ระบุ"
_weekday:
sunday: "วันอาทิตย์"
monday: "วันจันทร์"
@@ -1618,8 +1615,6 @@ _visibility:
followersDescription: "ทำให้ผู้ติดตามนั้นมองเห็นà¹à¸„่คุณเท่านั้น"
specified: "ไดเร็ค"
specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น"
- localOnly: "เฉพาะท้องถิ่น"
- localOnlyDescription: "ผู้ใช้ระยะไà¸à¸¥à¸™à¸±à¹‰à¸™à¹„ม่สามารถมองเห็นได้"
_postForm:
replyPlaceholder: "ตอบà¸à¸¥à¸±à¸šà¹‚น้ตนี้..."
quotePlaceholder: "อ้างโน้ตนี้..."
@@ -1757,12 +1752,9 @@ _notification:
youGotReply: "{name} ตอบà¸à¸¥à¸±à¸šà¸–ึงคุณ"
youGotQuote: "{name} อ้างถึงคุณ"
youRenoted: "รีโน้ตจาภ{name}"
- youGotMessagingMessageFromUser: "{name} ได้ส่งข้อความà¹à¸Šà¸—ถึงคุณ"
- youGotMessagingMessageFromGroup: "ข้อความà¹à¸Šà¸—ถูà¸à¸ªà¹ˆà¸‡à¹„ปยัง {name} à¸à¸¥à¸¸à¹ˆà¸¡"
youWereFollowed: "ได้ติดตามคุณ"
youReceivedFollowRequest: "คุณมีคำขอติดตามใหม่น่ะ"
yourFollowRequestAccepted: "คำขอติดตามของคุณได้รับà¸à¸²à¸£à¸¢à¸­à¸¡à¸£à¸±à¸šà¹à¸¥à¹‰à¸§à¸™à¹ˆà¸°"
- youWereInvitedToGroup: "{userName} ได้เชิà¸à¸„ุณเข้าà¸à¸¥à¸¸à¹ˆà¸¡"
pollEnded: "โพลสำรวจความคิดเห็นผลลัพธ์มีพร้อมใช้งาน"
unreadAntennaNote: "เสาอาà¸à¸²à¸¨ {name}"
emptyPushNotificationMessage: "à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนà¹à¸šà¸šà¸žà¸¸à¸Šà¹„ด้รับà¸à¸²à¸£à¸­à¸±à¸žà¹€à¸”ทà¹à¸¥à¹‰à¸§"
@@ -1778,7 +1770,6 @@ _notification:
pollEnded: "โพลนี้สิ้นสุดลงà¹à¸¥à¹‰à¸§"
receiveFollowRequest: "ได้รับคำขอติดตาม\n"
followRequestAccepted: "ยอมรับคำขอติดตาม"
- groupInvited: "ได้รับคำเชิà¸à¹€à¸‚้าà¸à¸¥à¸¸à¹ˆà¸¡"
app: "à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนจาà¸à¹à¸­à¸›à¸—ี่มีลิงà¸à¹Œ"
_actions:
followBack: "ติดตามà¸à¸¥à¸±à¸šà¸”้วย"
diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml
index 27882e50f6..79ec11f421 100644
--- a/locales/uk-UA.yml
+++ b/locales/uk-UA.yml
@@ -387,13 +387,10 @@ about: "ІнформаціÑ"
aboutMisskey: "Про Misskey"
administrator: "Ðдмін"
token: "Токен"
-twoStepAuthentication: "Двохфакторна аутентифікаціÑ"
moderator: "Модератор"
moderation: "МодераціÑ"
nUsersMentioned: "Згадали: {n}"
securityKey: "Ключ захиÑту"
-securityKeyName: "Ðазва ключа"
-registerSecurityKey: "ЗареєÑтрувати ключ захиÑту"
lastUsed: "ВоÑтаннє викориÑтано"
unregister: "СкаÑувати реєÑтрацію"
passwordLessLogin: "Ðалаштувати вхід без паролÑ"
@@ -411,24 +408,15 @@ markAsReadAllTalkMessages: "Позначити вÑÑ– Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ
help: "Допомога"
inputMessageHere: "Введіть Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚ÑƒÑ‚"
close: "Закрити"
-group: "Група"
-groups: "Групи"
-createGroup: "Створити групу"
-ownedGroups: "ВлаÑні групи"
-joinedGroups: "ЧленÑтво в групах"
invites: "ЗапроÑити"
-groupName: "Ðазва групи"
members: "УчаÑники"
transfer: "Передача"
-messagingWithUser: "Чат з кориÑтувачами"
-messagingWithGroup: "Чат з групою"
title: "Тема"
text: "ТекÑÑ‚"
enable: "Увімкнути"
next: "Далі"
retype: "Введіть ще раз"
noteOf: "Ðотатка {user}"
-inviteToGroup: "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ групи"
quoteAttached: "Цитата"
quoteQuestion: "Ви хочете додати цитату?"
noMessagesYet: "Ще немає повідомлень"
@@ -450,15 +438,11 @@ passwordMatched: "Ð’Ñе вірно"
passwordNotMatched: "Паролі не Ñпівпадають"
signinWith: "Увійти за допомогою {x}"
signinFailed: "Ðе вдалоÑÑ ÑƒÐ²Ñ–Ð¹Ñ‚Ð¸. Введені Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або пароль неправильнi."
-tapSecurityKey: "ТоркнітьÑÑ ÐºÐ»ÑŽÑ‡Ð° безпеки"
or: "або"
language: "Мова"
uiLanguage: "Мова інтерфейÑу"
-groupInvited: "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ групи"
aboutX: "Про {x}"
disableDrawer: "Ðе викориÑтовувати виÑувні меню"
-youHaveNoGroups: "Ðемає груп"
-joinOrCreateGroup: "Отримуйте Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ груп або Ñтворюйте Ñвої влаÑні групи."
noHistory: "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ"
signinHistory: "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð²Ñ…Ð¾Ð´Ñ–Ð²"
doing: "ВиконуєтьÑÑ"
@@ -825,8 +809,6 @@ deleteAccountConfirm: "Це незворотно видалить ваш акаÑ
incorrectPassword: "Ðеправильний пароль."
voteConfirm: "Підтверджуєте Ñвій Ð³Ð¾Ð»Ð¾Ñ Ð·Ð° \"{choice}\"?"
hide: "Сховати"
-leaveGroup: "Залишити групу"
-leaveGroupConfirm: "Залишити \"{name}\"?"
welcomeBackWithName: "З поверненнÑм, {name}!"
clickToFinishEmailVerification: "ÐатиÑніть [{ok}], щоб завершити перевірку email."
overridedDeviceKind: "Тип приÑтрою"
@@ -1113,6 +1095,8 @@ _achievements:
_loggedInOnNewYearsDay:
title: "З Ðовим роком!"
description: "Увійшли в перший день року"
+ _cookieClicked:
+ flavor: "Чекайте, це вірний Ñайт?"
_brainDiver:
title: "Brain Diver"
description: "Відправити поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° \"Brain Diver\""
@@ -1347,13 +1331,12 @@ _tutorial:
step8_3: "Ви завжди можете змінити цей параметр пізніше."
_2fa:
alreadyRegistered: "Двофакторна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð²Ð¶Ðµ налаштована."
- registerDevice: "ЗареєÑтрувати новий приÑтрій"
- registerKey: "ЗареєÑтрувати новий ключ безпеки"
step1: "Спершу вÑтановіть на Ñвій приÑтрій програму автентифікації (наприклад {a} або {b})."
step2: "Потім відÑкануйте QR-код, Ñкий відображаєтьÑÑ Ð½Ð° цьому екрані."
step2Url: "Ви також можете ввеÑти цю URL-адреÑу, Ñкщо викориÑтовуєте програму Ð´Ð»Ñ ÐŸÐš:"
step3: "Щоб завершити налаштуваннÑ, введіть токен, наданий вашою програмою."
step4: "Відтепер будь-Ñкі майбутні Ñпроби входу вимагатимуть такого токена."
+ renewTOTPCancel: "Ðе зараз"
_permissions:
"read:account": "ПереглÑдати дані профілю"
"write:account": "Змінити дані акаунту"
@@ -1462,8 +1445,6 @@ _visibility:
followersDescription: "Тільки Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñників"
specified: "ОÑобиÑто"
specifiedDescription: "Лише Ð´Ð»Ñ Ð¿ÐµÐ²Ð½Ð¸Ñ… кориÑтувачів"
- localOnly: "Локально"
- localOnlyDescription: "Приховано Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¸Ñ… кориÑтувачів"
_postForm:
replyPlaceholder: "Відповідь на цю нотатку..."
quotePlaceholder: "Прокоментуйте цю нотатку..."
@@ -1588,12 +1569,9 @@ _notification:
youGotReply: "{name} відповідає"
youGotQuote: "{name} цитує ваÑ"
youRenoted: "{name} поширює"
- youGotMessagingMessageFromUser: "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ {name}"
- youGotMessagingMessageFromGroup: "Ðове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² групі {name}"
youWereFollowed: "Ðовий підпиÑник"
youReceivedFollowRequest: "Ви отримали запит на підпиÑку"
yourFollowRequestAccepted: "Запит на підпиÑку прийнÑто"
- youWereInvitedToGroup: "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ групи"
achievementEarned: "ДоÑÑÐ³Ð½ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¾"
_types:
all: "Ð’Ñе"
@@ -1605,7 +1583,6 @@ _notification:
reaction: "Реакції"
receiveFollowRequest: "Запити на підпиÑку"
followRequestAccepted: "ПрийнÑті підпиÑки"
- groupInvited: "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ груп"
app: "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ додатків"
_actions:
reply: "ВідповіÑти"
diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml
index 594052dfce..44aed8bc37 100644
--- a/locales/vi-VN.yml
+++ b/locales/vi-VN.yml
@@ -383,13 +383,10 @@ about: "Giới thiệu"
aboutMisskey: "Vá» Misskey"
administrator: "Quản trị viên"
token: "Token"
-twoStepAuthentication: "Xác minh 2 bước"
moderator: "Kiểm duyệt viên"
moderation: "Kiểm duyệt"
nUsersMentioned: "Dùng bởi {n} ngưá»i"
securityKey: "Khóa bảo mật"
-securityKeyName: "Tên khoá"
-registerSecurityKey: "Äăng ký khóa bảo mật"
lastUsed: "Dùng lần cuối"
unregister: "Hủy đăng ký"
passwordLessLogin: "Äăng nhập không mật khẩu"
@@ -407,24 +404,15 @@ markAsReadAllTalkMessages: "Äánh dấu tất cả các tin nhắn là đã Ä‘á
help: "Trợ giúp"
inputMessageHere: "Nhập nội dung tin nhắn"
close: "Äóng"
-group: "Nhóm"
-groups: "Các nhóm"
-createGroup: "Tạo nhóm"
-ownedGroups: "Nhóm tôi quản lý"
-joinedGroups: "Nhóm tôi tham gia"
invites: "Má»i"
-groupName: "Tên nhóm"
members: "Thành viên"
transfer: "Chuyển giao"
-messagingWithUser: "Nhắn riêng"
-messagingWithGroup: "Chat nhóm"
title: "Tá»±a Ä‘á»"
text: "Ná»™i dung"
enable: "Bật"
next: "Kế tiếp"
retype: "Nhập lại"
noteOf: "Tút của {user}"
-inviteToGroup: "Má»i vào nhóm"
quoteAttached: "Trích dẫn"
quoteQuestion: "Trích dẫn lại?"
noMessagesYet: "Chưa có tin nhắn"
@@ -446,15 +434,11 @@ passwordMatched: "Trùng khớp"
passwordNotMatched: "Không trùng khớp"
signinWith: "Äăng nhập bằng {x}"
signinFailed: "Không thể đăng nhập. Vui lòng kiểm tra tên ngưá»i dùng và mật khẩu cá»§a bạn."
-tapSecurityKey: "Nhấn mã bảo mật của bạn"
or: "Hoặc"
language: "Ngôn ngữ"
uiLanguage: "Ngôn ngữ giao diện"
-groupInvited: "Bạn đã được má»i tham gia nhóm"
aboutX: "Giới thiệu {x}"
disableDrawer: "Không dùng menu thanh bên"
-youHaveNoGroups: "Không có nhóm nào"
-joinOrCreateGroup: "Tham gia hoặc tạo một nhóm mới."
noHistory: "Không có dữ liệu"
signinHistory: "Lịch sử đăng nhập"
doing: "Äang xá»­ lý..."
@@ -825,8 +809,6 @@ deleteAccountConfirm: "Äiá»u này sẽ khiến tài khoản bị xóa vÄ©nh vi
incorrectPassword: "Sai mật khẩu."
voteConfirm: "Xác nhận bình chá»n \"{choice}\"?"
hide: "Ẩn"
-leaveGroup: "Rá»i khá»i nhóm"
-leaveGroupConfirm: "Bạn có chắc muốn rá»i khá»i nhóm \"{name}\"?"
useDrawerReactionPickerForMobile: "Hiện bá»™ chá»n biểu cảm dạng xổ ra trên Ä‘iện thoại"
welcomeBackWithName: "Chào mừng trở lại, {name}"
clickToFinishEmailVerification: "Vui lòng nhấn [{ok}] để hoàn tất việc đăng ký."
@@ -1150,14 +1132,13 @@ _tutorial:
step7_3: "Bây giá», chúc may mắn và vui vẻ vá»›i Misskey! 🚀"
_2fa:
alreadyRegistered: "Bạn đã đăng ký thiết bị xác minh 2 bước."
- registerDevice: "Äăng ký má»™t thiết bị"
- registerKey: "Äăng ký má»™t mã bảo vệ"
step1: "Trước tiên, hãy cài đặt một ứng dụng xác minh (chẳng hạn như {a} hoặc {b}) trên thiết bị của bạn."
step2: "Sau đó, quét mã QR hiển thị trên màn hình này."
step2Url: "Bạn cũng có thể nhập URL này nếu sử dụng một chương trình máy tính:"
step3: "Nhập mã token do ứng dụng của bạn cung cấp để hoàn tất thiết lập."
step4: "Kể từ bây giá», những lần đăng nhập trong tương lai sẽ yêu cầu mã token đăng nhập đó."
securityKeyInfo: "Bên cạnh xác minh bằng vân tay hoặc mã PIN, bạn cũng có thể thiết lập xác minh thông qua khóa bảo mật phần cứng hỗ trợ FIDO2 để bảo mật hơn nữa cho tài khoản của mình."
+ removeKeyConfirm: "Xóa bản sao lưu {name}?"
_permissions:
"read:account": "Xem thông tin tài khoản của bạn"
"write:account": "Sửa thông tin tài khoản của bạn"
@@ -1203,7 +1184,6 @@ _antennaSources:
homeTimeline: "Tút từ những ngưá»i đã theo dõi"
users: "Tút từ những ngưá»i cụ thể"
userList: "Tút từ danh sách ngưá»i dùng cụ thể"
- userGroup: "Tút từ ngưá»i dùng trong má»™t nhóm cụ thể"
_weekday:
sunday: "Chủ Nhật"
monday: "Thứ Hai"
@@ -1275,8 +1255,6 @@ _visibility:
followersDescription: "Dành riêng cho ngưá»i theo dõi"
specified: "Nhắn riêng"
specifiedDescription: "Chỉ ngưá»i được nhắc đến má»›i thấy"
- localOnly: "Chỉ trên máy chủ"
- localOnlyDescription: "Không hiển thị vá»›i ngưá»i ở máy chá»§ khác"
_postForm:
replyPlaceholder: "Trả lá»i tút này"
quotePlaceholder: "Trích dẫn tút này"
@@ -1404,12 +1382,9 @@ _notification:
youGotReply: "{name} trả lá»i bạn"
youGotQuote: "{name} trích dẫn tút của bạn"
youRenoted: "{name} đăng lại tút của bạn"
- youGotMessagingMessageFromUser: "{name} nhắn tin cho bạn"
- youGotMessagingMessageFromGroup: "Một tin nhắn trong nhóm {name}"
youWereFollowed: "đã theo dõi bạn"
youReceivedFollowRequest: "Bạn vừa có một yêu cầu theo dõi"
yourFollowRequestAccepted: "Yêu cầu theo dõi của bạn đã được chấp nhận"
- youWereInvitedToGroup: "Bạn đã được má»i tham gia nhóm"
pollEnded: "Cuá»™c bình chá»n đã kết thúc"
emptyPushNotificationMessage: "Äã cập nhật thông báo đẩy"
_types:
@@ -1423,7 +1398,6 @@ _notification:
pollEnded: "Bình chá»n kết thúc"
receiveFollowRequest: "Yêu cầu theo dõi"
followRequestAccepted: "Yêu cầu theo dõi được chấp nhận"
- groupInvited: "Má»i vào nhóm"
app: "Từ app liên kết"
_actions:
followBack: "đã theo dõi lại bạn"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 71ca55d9e5..7ba8956394 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -103,6 +103,8 @@ renoted: "已转å‘。"
cantRenote: "该帖无法转å‘。"
cantReRenote: "è½¬å‘æ— æ³•è¢«å†æ¬¡è½¬å‘。"
quote: "引用"
+inChannelRenote: "在频é“内转å‘"
+inChannelQuote: "在频é“内引用"
pinnedNote: "已置顶的帖å­"
pinned: "置顶"
you: "您"
@@ -391,13 +393,10 @@ about: "关于"
aboutMisskey: "关于 Misskey"
administrator: "管ç†å‘˜"
token: "Token (令牌)"
-twoStepAuthentication: "两步验è¯"
moderator: "监察员"
moderation: "管ç†"
nUsersMentioned: "{n} 被æåˆ°"
securityKey: "安全密钥"
-securityKeyName: "密钥åç§°"
-registerSecurityKey: "注册硬件安全密钥"
lastUsed: "最åŽä½¿ç”¨ï¼š"
unregister: "删除账户"
passwordLessLogin: "无密ç ç™»å½•"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "将所有èŠå¤©æ ‡è®°ä¸ºå·²è¯»"
help: "帮助"
inputMessageHere: "在此键入信æ¯"
close: "关闭"
-group: "群组"
-groups: "群组"
-createGroup: "创建群组"
-ownedGroups: "拥有的群组"
-joinedGroups: "已加入的群组"
invites: "邀请"
-groupName: "群组å"
members: "æˆå‘˜"
transfer: "转让"
-messagingWithUser: "与用户èŠå¤©"
-messagingWithGroup: "与群组èŠå¤©"
title: "标题"
text: "文本"
enable: "å¯ç”¨"
next: "下一个"
retype: "釿–°è¾“å…¥"
noteOf: "{user}的帖å­"
-inviteToGroup: "群组邀请"
quoteAttached: "已引用"
quoteQuestion: "是å¦å¼•用此链接内容?"
noMessagesYet: "现在没有新的èŠå¤©"
@@ -454,17 +444,13 @@ passwordMatched: "密ç ä¸€è‡´"
passwordNotMatched: "密ç ä¸ä¸€è‡´"
signinWith: "以{x}登录"
signinFailed: "无法登录,请检查您的用户åå’Œå¯†ç æ˜¯å¦æ­£ç¡®ã€‚"
-tapSecurityKey: "轻触硬件安全密钥"
or: "或者"
language: "语言"
uiLanguage: "显示语言"
-groupInvited: "您有新的群组邀请"
aboutX: "关于 {x}"
emojiStyle: "emoji 的样å¼"
native: "原生"
disableDrawer: "䏿˜¾ç¤ºæŠ½å±‰èœå•"
-youHaveNoGroups: "没有群组"
-joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
noHistory: "没有历å²è®°å½•"
signinHistory: "登录历å²"
enableAdvancedMfm: "å¯ç”¨æ‰©å±•MFM"
@@ -683,7 +669,7 @@ driveFilesCount: "网盘的文件数"
driveUsage: "网盘的空间用é‡"
noCrawle: "è¦æ±‚æœç´¢å¼•擎ä¸ç´¢å¼•该用户"
noCrawleDescription: "è¦æ±‚æœç´¢å¼•擎ä¸è¦æ”¶å½•(索引)您的用户页é¢ï¼Œå¸–å­ï¼Œé¡µé¢ç­‰ã€‚"
-lockedAccountInfo: "å³ä½¿é€šè¿‡äº†å…³æ³¨è¯·æ±‚,åªè¦æ‚¨ä¸å°†å¸–å­å¯è§èŒƒå›´è®¾ç½®æˆâ€œå…³æ³¨è€…â€ï¼Œä»»ä½•人都å¯ä»¥çœ‹åˆ°æ‚¨çš„帖å­ã€‚"
+lockedAccountInfo: "å³ä½¿å¯ç”¨è¯¥åŠŸèƒ½ï¼Œåªè¦æ‚¨ä¸å°†å¸–å­å¯è§èŒƒå›´è®¾ç½®ä¸ºâ€œä»…关注者â€ï¼Œä»»ä½•人都还是å¯ä»¥çœ‹åˆ°æ‚¨çš„帖å­ã€‚"
alwaysMarkSensitive: "é»˜è®¤å°†åª’ä½“æ–‡ä»¶æ ‡è®°ä¸ºæ•æ„Ÿå†…容"
loadRawImages: "添加附件图åƒçš„缩略图时使用原始图åƒè´¨é‡"
disableShowingAnimatedImages: "䏿’­æ”¾åŠ¨ç”»"
@@ -838,8 +824,6 @@ deleteAccountConfirm: "å°†è¦åˆ é™¤è´¦æˆ·ã€‚是å¦ç¡®è®¤ï¼Ÿ"
incorrectPassword: "密ç é”™è¯¯"
voteConfirm: "确定投给“{choice}†?"
hide: "éšè—"
-leaveGroup: "离开群组"
-leaveGroupConfirm: "确定离开「{name}ã€ï¼Ÿ"
useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示"
welcomeBackWithName: "欢迎回æ¥ï¼Œ{name}"
clickToFinishEmailVerification: "点击 [{ok}] 完æˆç”µå­é‚®ä»¶åœ°å€è®¤è¯ã€‚"
@@ -951,6 +935,10 @@ thisPostMayBeAnnoying: "这个帖å­å¯èƒ½ä¼šè®©å…¶ä»–人感到困扰。"
thisPostMayBeAnnoyingHome: "å‘到首页"
thisPostMayBeAnnoyingCancel: "å–æ¶ˆ"
thisPostMayBeAnnoyingIgnore: "就这样å‘布"
+collapseRenotes: "çœç•¥æ˜¾ç¤ºå·²ç»çœ‹è¿‡çš„转å‘内容"
+internalServerError: "内部æœåŠ¡å™¨é”™è¯¯"
+internalServerErrorDescription: "内部æœåС噍å‘生了预期外的错误"
+copyErrorInfo: "å¤åˆ¶é”™è¯¯ä¿¡æ¯"
_achievements:
earnedAt: "è¾¾æˆæ—¶é—´"
_types:
@@ -1497,14 +1485,14 @@ _tutorial:
step8_3: "您也å¯ä»¥ç¨åŽå†æ›´æ”¹é€šçŸ¥è®¾ç½®ã€‚"
_2fa:
alreadyRegistered: "此设备已被注册"
- registerDevice: "注册设备"
- registerKey: "注册密钥"
step1: "首先,在您的设备上安装验è¯åº”用,例如{a}或{b}。"
step2: "ç„¶åŽï¼Œæ‰«æå±å¹•上显示的二维ç ã€‚"
step2Url: "在桌é¢åº”用程åºä¸­è¾“入以下URL:"
step3: "输入您的应用æä¾›çš„动æ€å£ä»¤ä»¥å®Œæˆè®¾ç½®ã€‚"
step4: "从现在开始,任何登录æ“ä½œéƒ½å°†è¦æ±‚您æä¾›åЍæ€å£ä»¤ã€‚"
securityKeyInfo: "您å¯ä»¥è®¾ç½®ä½¿ç”¨æ”¯æŒFIDO2的硬件安全密钥ã€è®¾å¤‡ä¸Šçš„æŒ‡çº¹æˆ–PINæ¥ä¿æŠ¤æ‚¨çš„登录过程。"
+ removeKeyConfirm: "您确定è¦åˆ é™¤ {name} å—?"
+ renewTOTPCancel: "ä¸ç”¨ï¼Œè°¢è°¢"
_permissions:
"read:account": "查看账户信æ¯"
"write:account": "æ›´æ”¹å¸æˆ·ä¿¡æ¯"
@@ -1553,7 +1541,6 @@ _antennaSources:
homeTimeline: "已关注用户的帖å­"
users: "æ¥è‡ªæŒ‡å®šç”¨æˆ·çš„帖å­"
userList: "æ¥è‡ªæŒ‡å®šåˆ—表中的帖å­"
- userGroup: "æ¥è‡ªæŒ‡å®šç¾¤ç»„中用户的帖å­"
_weekday:
sunday: "星期日"
monday: "星期一"
@@ -1628,8 +1615,6 @@ _visibility:
followersDescription: "ä»…å‘é€è‡³å…³æ³¨è€…"
specified: "指定用户"
specifiedDescription: "ä»…å‘é€è‡³æŒ‡å®šç”¨æˆ·"
- localOnly: "仅陿œ¬åœ°"
- localOnlyDescription: "对远程用户ä¸å¯è§"
_postForm:
replyPlaceholder: "回å¤è¿™ä¸ªå¸–å­..."
quotePlaceholder: "引用这个帖å­..."
@@ -1767,12 +1752,9 @@ _notification:
youGotReply: "æ¥è‡ª{name}的回å¤"
youGotQuote: "æ¥è‡ª{name}的引用"
youRenoted: "æ¥è‡ª{name}的转å‘"
- youGotMessagingMessageFromUser: "æ¥è‡ª{name}çš„èŠå¤©"
- youGotMessagingMessageFromGroup: "æ¥è‡ª{name}的群èŠ"
youWereFollowed: "关注了你。"
youReceivedFollowRequest: "您有新的关注请求"
yourFollowRequestAccepted: "您的关注请求已通过"
- youWereInvitedToGroup: "您有新的群组邀请"
pollEnded: "é—®å·è°ƒæŸ¥ç»“果已生æˆã€‚"
unreadAntennaNote: "天线 {name}"
emptyPushNotificationMessage: "推é€é€šçŸ¥å·²æ›´æ–°"
@@ -1788,7 +1770,6 @@ _notification:
pollEnded: "é—®å·è°ƒæŸ¥ç»“æŸ"
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "关注请求已通过"
- groupInvited: "加入群组邀请"
app: "å…³è”应用的通知"
_actions:
followBack: "回关"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index f99ca91e63..1dd2ae4cec 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -103,13 +103,15 @@ renoted: "轉傳æˆåŠŸ"
cantRenote: "無法轉發此貼文。"
cantReRenote: "無法轉傳之å‰å·²ç¶“轉傳éŽçš„內容。"
quote: "引用"
+inChannelRenote: "在頻é“內轉發"
+inChannelQuote: "在頻é“內引用"
pinnedNote: "已置頂的貼文"
pinned: "置頂"
you: "您"
clickToShow: "按一下以顯示"
sensitive: "æ•æ„Ÿå…§å®¹"
add: "新增"
-reaction: "情感"
+reaction: "忇‰"
reactions: "情感"
reactionSetting: "åœ¨é¸æ“‡å™¨ä¸­é¡¯ç¤ºå應"
reactionSettingDescription2: "æ‹–å‹•ä»¥é‡æ–°åˆ—åºï¼Œé»žæ“Šä»¥åˆªé™¤ï¼ŒæŒ‰ä¸‹ + 添加。"
@@ -391,13 +393,10 @@ about: "關於"
aboutMisskey: "關於 Misskey"
administrator: "管ç†å“¡"
token: "權æ–"
-twoStepAuthentication: "兩階段驗證"
moderator: "審查員"
moderation: "審查"
nUsersMentioned: "æåˆ°äº†{n}"
securityKey: "安全金鑰"
-securityKeyName: "金鑰å稱"
-registerSecurityKey: "註冊安全金鑰"
lastUsed: "上次使用"
unregister: "註銷帳號"
passwordLessLogin: "設置無密碼登入"
@@ -415,24 +414,15 @@ markAsReadAllTalkMessages: "標記所有訊æ¯ç‚ºå·²è®€"
help: "幫助"
inputMessageHere: "在此輸入訊æ¯"
close: "關閉"
-group: "群組"
-groups: "群組"
-createGroup: "創建群組"
-ownedGroups: "æ“æœ‰çš„群組"
-joinedGroups: "群組æˆå“¡"
invites: "邀請"
-groupName: "群組å稱"
members: "æˆå“¡"
transfer: "轉讓"
-messagingWithUser: "與其他使用者èŠå¤©"
-messagingWithGroup: "發é€è¨Šæ¯è‡³ç¾¤çµ„"
title: "標題"
text: "文字"
enable: "啟用"
next: "下一步"
-retype: "釿–°è¼¸å…¥"
+retype: "冿¬¡è¼¸å…¥"
noteOf: "{user}的貼文"
-inviteToGroup: "邀請至群組"
quoteAttached: "引用"
quoteQuestion: "是å¦è¦å¼•用?"
noMessagesYet: "沒有訊æ¯"
@@ -454,17 +444,13 @@ passwordMatched: "密碼一致"
passwordNotMatched: "密碼ä¸ä¸€è‡´"
signinWith: "以{x}登錄"
signinFailed: "登入失敗。 請檢查使用者å稱和密碼。"
-tapSecurityKey: "點擊安全密鑰"
or: "或者"
language: "語言"
uiLanguage: "介é¢èªžè¨€"
-groupInvited: "您有新的群組邀請"
aboutX: "關於{x}"
emojiStyle: "表情符號的風格"
native: "原生"
disableDrawer: "ä¸é¡¯ç¤ºä¸‹æ‹‰å¼é¸å–®"
-youHaveNoGroups: "找ä¸åˆ°ç¾¤çµ„"
-joinOrCreateGroup: "è«‹åŠ å…¥ç¾æœ‰ç¾¤çµ„,或創建新群組。"
noHistory: "沒有歷å²ç´€éŒ„"
signinHistory: "登入歷å²"
enableAdvancedMfm: "啟用高級MFM"
@@ -673,8 +659,8 @@ repliedCount: "回覆數é‡"
renotedCount: "轉發次數"
followingCount: "正在跟隨的用戶數é‡"
followersCount: "跟隨者數é‡"
-sentReactionsCount: "æƒ…æ„Ÿç™¼é€æ¬¡æ•¸"
-receivedReactionsCount: "情感收到次數"
+sentReactionsCount: "忇‰ç™¼é€æ¬¡æ•¸"
+receivedReactionsCount: "æ”¶åˆ°åæ‡‰æ¬¡æ•¸"
pollVotesCount: "已統計的投票數"
pollVotedCount: "已投票數"
yes: "確定"
@@ -838,8 +824,6 @@ deleteAccountConfirm: "å°‡è¦åˆªé™¤å¸³æˆ¶ã€‚是å¦ç¢ºå®šï¼Ÿ"
incorrectPassword: "密碼錯誤。"
voteConfirm: "確定投給「{choice}ã€ï¼Ÿ"
hide: "éš±è—"
-leaveGroup: "離開群組"
-leaveGroupConfirm: "確定離開「{name}ã€ï¼Ÿ"
useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示"
welcomeBackWithName: "歡迎回來,{name}"
clickToFinishEmailVerification: "點擊 [{ok}] 完æˆé›»å­éƒµä»¶åœ°å€èªè­‰ã€‚"
@@ -952,6 +936,9 @@ thisPostMayBeAnnoyingHome: "發布到首é "
thisPostMayBeAnnoyingCancel: "退出"
thisPostMayBeAnnoyingIgnore: "直接發布貼文"
collapseRenotes: "çœç•¥é¡¯ç¤ºå·²çœ‹éŽçš„轉發貼文"
+internalServerError: "內部伺æœå™¨éŒ¯èª¤"
+internalServerErrorDescription: "內部伺æœå™¨ç™¼ç”Ÿäº†éžé æœŸçš„錯誤。"
+copyErrorInfo: "複製錯誤資訊"
_achievements:
earnedAt: "ç²å¾—日期"
_types:
@@ -1488,7 +1475,7 @@ _tutorial:
step5_3: "想è¦è¿½éš¨å…¶ä»–人,åªè¦é»žæ“Šä»–們的大頭貼並按「追隨ã€å³å¯ã€‚"
step5_4: "如果使用者的åå­—æ—æœ‰éŽ–é ­çš„åœ–ç¤ºï¼Œä»£è¡¨ä»–å€‘éœ€è¦æ‰‹å‹•核准你的追隨請求。"
step6_1: "ç¾åœ¨ä½ å¯ä»¥åœ¨æ™‚間軸上看到其他用戶的貼文。"
- step6_2: "你也å¯ä»¥å°åˆ¥äººçš„貼文作出「情感ã€ï¼Œä½œå‡ºç°¡å–®çš„回覆。"
+ step6_2: "你也å¯ä»¥å°åˆ¥äººçš„è²¼æ–‡ä½œå‡ºã€Œåæ‡‰ã€ï¼Œä½œå‡ºç°¡å–®çš„回覆。"
step6_3: "在他人的貼文按下\"+\"圖標,å³å¯é¸æ“‡å–œå¥½çš„表情符號進行回應。"
step7_1: "以上為Misskey的基本æ“作說明,教學在此告一段è½ã€‚辛苦了。"
step7_2: "歡迎到{help}來瞭解更多Misskey相關介紹。"
@@ -1498,14 +1485,14 @@ _tutorial:
step8_3: "通知的設定å¯ä»¥åœ¨ä¹‹å¾Œè®Šæ›´ã€‚"
_2fa:
alreadyRegistered: "此設備已經被註冊éŽäº†"
- registerDevice: "註冊è£ç½®"
- registerKey: "註冊éµ"
step1: "首先,在您的設備上安è£äºŒæ­¥é©—證程å¼ï¼Œä¾‹å¦‚{a}或{b}。"
step2: "然後,掃æèž¢å¹•上的QR code。"
step2Url: "在桌é¢ç‰ˆæ‡‰ç”¨ä¸­ï¼Œè«‹è¼¸å…¥ä»¥ä¸‹çš„URL:"
step3: "輸入您的Appæä¾›çš„æ¬Šæ–以完æˆè¨­å®šã€‚"
step4: "從ç¾åœ¨é–‹å§‹ï¼Œä»»ä½•登入æ“ä½œéƒ½å°‡è¦æ±‚您æä¾›æ¬Šæ–。"
securityKeyInfo: "您å¯ä»¥è¨­å®šä½¿ç”¨æ”¯æ´FIDO2的硬體安全鎖ã€çµ‚端設備的指纹èªè­‰æˆ–者PIN碼來登入。"
+ removeKeyConfirm: "è¦åˆªé™¤{name}嗎?"
+ renewTOTPCancel: "ç¾åœ¨ä¸è¦"
_permissions:
"read:account": "查看我的帳戶資訊"
"write:account": "更改我的帳戶資訊"
@@ -1524,8 +1511,8 @@ _permissions:
"write:notes": "撰寫或刪除貼文"
"read:notifications": "查看通知"
"write:notifications": "編輯通知"
- "read:reactions": "查看情感"
- "write:reactions": "編輯情感"
+ "read:reactions": "æŸ¥çœ‹åæ‡‰"
+ "write:reactions": "ç·¨è¼¯åæ‡‰"
"write:votes": "投票"
"read:pages": "顯示é é¢"
"write:pages": "編輯é é¢"
@@ -1554,7 +1541,6 @@ _antennaSources:
homeTimeline: "來自已追隨使用者的貼文"
users: "來自特定使用者的貼文"
userList: "來自特定清單中的貼文"
- userGroup: "來自特定群組的貼文"
_weekday:
sunday: "週日"
monday: "週一"
@@ -1629,8 +1615,6 @@ _visibility:
followersDescription: "僅發é€è‡³é—œæ³¨è€…"
specified: "指定使用者"
specifiedDescription: "僅發é€è‡³æŒ‡å®šä½¿ç”¨è€…"
- localOnly: "åƒ…é™æœ¬åœ°"
- localOnlyDescription: "å°é ç«¯ä½¿ç”¨è€…éš±è—"
_postForm:
replyPlaceholder: "回覆此貼文..."
quotePlaceholder: "引用此貼文..."
@@ -1768,12 +1752,9 @@ _notification:
youGotReply: "{name}回覆了您"
youGotQuote: "{name}引用了您"
youRenoted: "{name} 轉發了你的貼文"
- youGotMessagingMessageFromUser: "{name}發é€çµ¦æ‚¨çš„訊æ¯"
- youGotMessagingMessageFromGroup: "{name}發é€çµ¦æ‚¨çš„訊æ¯"
youWereFollowed: "您有新的追隨者"
youReceivedFollowRequest: "您有新的追隨請求"
yourFollowRequestAccepted: "您的追隨請求已通éŽ"
- youWereInvitedToGroup: "您有新的群組邀請"
pollEnded: "å•å·èª¿æŸ¥å·²ç”¢ç”Ÿçµæžœ"
unreadAntennaNote: "天線 {name}"
emptyPushNotificationMessage: "推é€é€šçŸ¥å·²æ›´æ–°"
@@ -1789,7 +1770,6 @@ _notification:
pollEnded: "å•å·èª¿æŸ¥çµæŸ"
receiveFollowRequest: "已收到追隨請求"
followRequestAccepted: "追隨請求已接å—"
- groupInvited: "加入社群邀請"
app: "應用程å¼é€šçŸ¥"
_actions:
followBack: "回關"
diff --git a/package.json b/package.json
index 5a6b807d66..8d5334433b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "misskey",
- "version": "13.6.1",
+ "version": "13.7.5",
"codename": "nasubi",
"repository": {
"type": "git",
@@ -16,10 +16,11 @@
"scripts": {
"build-pre": "node ./scripts/build-pre.js",
"build": "pnpm build-pre && pnpm -r build && pnpm gulp",
- "start": "cd packages/backend && node ./built/boot/index.js",
+ "start": "pnpm check:connect && cd packages/backend && node ./built/boot/index.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/index.js",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
+ "check:connect": "cd packages/backend && pnpm check:connect",
"migrateandstart": "pnpm migrate && pnpm start",
"gulp": "pnpm exec gulp build",
"watch": "pnpm dev",
@@ -54,12 +55,12 @@
"devDependencies": {
"@types/gulp": "4.0.10",
"@types/gulp-rename": "2.0.1",
- "@typescript-eslint/eslint-plugin": "5.51.0",
- "@typescript-eslint/parser": "5.51.0",
+ "@typescript-eslint/eslint-plugin": "5.52.0",
+ "@typescript-eslint/parser": "5.52.0",
"cross-env": "7.0.3",
- "cypress": "12.5.1",
- "eslint": "8.33.0",
- "start-server-and-test": "1.15.3"
+ "cypress": "12.6.0",
+ "eslint": "8.34.0",
+ "start-server-and-test": "1.15.4"
},
"optionalDependencies": {
"@tensorflow/tfjs-core": "4.2.0"
diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc
index 55a88456ef..08d4222d01 100644
--- a/packages/backend/.swcrc
+++ b/packages/backend/.swcrc
@@ -1,25 +1,23 @@
{
- "$schema": "https://json.schemastore.org/swcrc",
- "jsc": {
- "parser": {
- "syntax": "typescript",
- "dynamicImport": true,
- "decorators": true
- },
- "transform": {
- "legacyDecorator": true,
- "decoratorMetadata": true
- },
+ "$schema": "https://json.schemastore.org/swcrc",
+ "jsc": {
+ "parser": {
+ "syntax": "typescript",
+ "dynamicImport": true,
+ "decorators": true
+ },
+ "transform": {
+ "legacyDecorator": true,
+ "decoratorMetadata": true
+ },
"experimental": {
"keepImportAssertions": true
},
- "baseUrl": ".",
+ "baseUrl": "src",
"paths": {
- "@/*": [
- "./src/*"
- ]
+ "@/*": ["*"]
},
"target": "es2021"
- },
- "minify": false
+ },
+ "minify": false
}
diff --git a/packages/backend/assets/apple-touch-icon.png b/packages/backend/assets/apple-touch-icon.png
index 947c513bbb..06ad3f1bb4 100644
--- a/packages/backend/assets/apple-touch-icon.png
+++ b/packages/backend/assets/apple-touch-icon.png
Binary files differ
diff --git a/packages/backend/assets/icons/192.png b/packages/backend/assets/icons/192.png
index 606b46d87c..15fd1e3731 100644
--- a/packages/backend/assets/icons/192.png
+++ b/packages/backend/assets/icons/192.png
Binary files differ
diff --git a/packages/backend/assets/icons/512.png b/packages/backend/assets/icons/512.png
index ba51546427..f2169ec9b0 100644
--- a/packages/backend/assets/icons/512.png
+++ b/packages/backend/assets/icons/512.png
Binary files differ
diff --git a/packages/backend/check_connect.js b/packages/backend/check_connect.js
new file mode 100644
index 0000000000..8bf134a105
--- /dev/null
+++ b/packages/backend/check_connect.js
@@ -0,0 +1,10 @@
+import {loadConfig} from './built/config.js';
+import {createRedisConnection} from "./built/redis.js";
+
+const config = loadConfig();
+const redis = createRedisConnection(config);
+
+redis.on('connect', () => redis.disconnect());
+redis.on('error', (e) => {
+ throw e;
+});
diff --git a/packages/backend/migration/1676434944993-drop-group.js b/packages/backend/migration/1676434944993-drop-group.js
index bdf3c1034e..c856046eb9 100644
--- a/packages/backend/migration/1676434944993-drop-group.js
+++ b/packages/backend/migration/1676434944993-drop-group.js
@@ -10,19 +10,11 @@ export class dropGroup1676434944993 {
await queryRunner.query(`CREATE TYPE "public"."antenna_src_enum" AS ENUM('home', 'all', 'users', 'list')`);
await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "public"."antenna_src_enum" USING "src"::"text"::"public"."antenna_src_enum"`);
await queryRunner.query(`DROP TYPE "public"."antenna_src_enum_old"`);
- await queryRunner.query(`ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`);
- await queryRunner.query(`CREATE TYPE "public"."notification_type_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app')`);
- await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum" USING "type"::"text"::"public"."notification_type_enum"`);
- await queryRunner.query(`DROP TYPE "public"."notification_type_enum_old"`);
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "emailNotificationTypes" SET DEFAULT '["follow","receiveFollowRequest"]'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "emailNotificationTypes" SET DEFAULT '["follow", "receiveFollowRequest", "groupInvited"]'`);
- await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'achievementEarned', 'app')`);
- await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum_old" USING "type"::"text"::"public"."notification_type_enum_old"`);
- await queryRunner.query(`DROP TYPE "public"."notification_type_enum"`);
- await queryRunner.query(`ALTER TYPE "public"."notification_type_enum_old" RENAME TO "notification_type_enum"`);
await queryRunner.query(`CREATE TYPE "public"."antenna_src_enum_old" AS ENUM('home', 'all', 'users', 'list', 'group')`);
await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "public"."antenna_src_enum_old" USING "src"::"text"::"public"."antenna_src_enum_old"`);
await queryRunner.query(`DROP TYPE "public"."antenna_src_enum"`);
diff --git a/packages/backend/migration/1676438468213-ad3.js b/packages/backend/migration/1676438468213-ad3.js
index bf1f384adc..18f56e8d36 100644
--- a/packages/backend/migration/1676438468213-ad3.js
+++ b/packages/backend/migration/1676438468213-ad3.js
@@ -4,6 +4,6 @@ export class ad1676438468213 {
await queryRunner.query(`ALTER TABLE "ad" ADD "startsAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`);
}
async down(queryRunner) {
- await queryRunner.query(`ALTER TABLE "role" DROP COLUMN "startsAt"`);
+ await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "startsAt"`);
}
}
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 52b0d74ad0..4d1d37efff 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -7,48 +7,62 @@
"start": "node ./built/index.js",
"start:test": "NODE_ENV=test node ./built/index.js",
"migrate": "pnpm typeorm migration:run -d ormconfig.js",
- "build:swc": "swc src -d built -D",
+ "check:connect": "node ./check_connect.js",
+ "build": "swc src -d built -D",
"watch:swc": "swc src -d built -D -w",
- "build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
+ "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs",
"typecheck": "tsc --noEmit",
"eslint": "eslint --quiet \"src/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint",
- "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --runInBand",
- "jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --runInBand",
+ "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --runInBand --detectOpenHandles",
+ "jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --runInBand --detectOpenHandles",
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
"test": "pnpm jest",
"test-and-coverage": "pnpm jest-and-coverage"
},
"optionalDependencies": {
+ "@swc/core-android-arm64": "^1.3.11",
+ "@swc/core-darwin-arm64": "^1.3.36",
+ "@swc/core-darwin-x64": "^1.3.36",
+ "@swc/core-linux-arm-gnueabihf": "^1.3.36",
+ "@swc/core-linux-arm64-gnu": "^1.3.36",
+ "@swc/core-linux-arm64-musl": "^1.3.36",
+ "@swc/core-linux-x64-gnu": "^1.3.36",
+ "@swc/core-linux-x64-musl": "^1.3.36",
+ "@swc/core-win32-arm64-msvc": "^1.3.36",
+ "@swc/core-win32-ia32-msvc": "^1.3.36",
+ "@swc/core-win32-x64-msvc": "^1.3.36",
"@tensorflow/tfjs": "4.2.0",
"@tensorflow/tfjs-node": "4.2.0"
},
"dependencies": {
- "@bull-board/api": "4.11.1",
- "@bull-board/fastify": "4.11.1",
- "@bull-board/ui": "4.11.1",
+ "@bull-board/api": "4.12.1",
+ "@bull-board/fastify": "4.12.1",
+ "@bull-board/ui": "4.12.1",
"@discordapp/twemoji": "14.0.2",
"@fastify/accepts": "4.1.0",
"@fastify/cookie": "8.3.0",
"@fastify/cors": "8.2.0",
"@fastify/http-proxy": "8.4.0",
- "@fastify/multipart": "7.4.0",
- "@fastify/static": "6.8.0",
+ "@fastify/multipart": "7.4.1",
+ "@fastify/static": "6.9.0",
"@fastify/view": "7.4.1",
- "@nestjs/common": "9.3.7",
- "@nestjs/core": "9.3.7",
- "@nestjs/testing": "9.3.7",
+ "@nestjs/common": "9.3.9",
+ "@nestjs/core": "9.3.9",
+ "@nestjs/testing": "9.3.9",
"@peertube/http-signature": "1.7.0",
"@sinonjs/fake-timers": "10.0.2",
+ "@swc/cli": "0.1.62",
+ "@swc/core": "1.3.36",
"accepts": "1.3.8",
"ajv": "8.12.0",
"archiver": "5.3.1",
"autwh": "0.1.0",
- "aws-sdk": "2.1295.0",
+ "aws-sdk": "2.1318.0",
"bcryptjs": "2.4.3",
- "blurhash": "2.0.4",
- "bull": "4.10.3",
+ "blurhash": "2.0.5",
+ "bull": "4.10.4",
"cacheable-lookup": "6.1.0",
"cbor": "8.1.0",
"chalk": "5.2.0",
@@ -60,12 +74,13 @@
"date-fns": "2.29.3",
"deep-email-validator": "0.1.21",
"escape-regexp": "0.0.1",
- "fastify": "4.12.0",
+ "fastify": "4.13.0",
"feed": "4.2.2",
- "file-type": "18.2.0",
+ "file-type": "18.2.1",
"fluent-ffmpeg": "2.1.2",
"form-data": "4.0.0",
"got": "12.5.3",
+ "happy-dom": "^8.7.0",
"hpagent": "1.2.0",
"ioredis": "4.28.5",
"ip-cidr": "3.1.0",
@@ -85,6 +100,7 @@
"nsfwjs": "2.4.2",
"oauth": "0.10.0",
"os-utils": "0.0.14",
+ "otpauth": "^9.0.2",
"parse5": "7.1.2",
"pg": "8.9.0",
"private-ip": "3.0.0",
@@ -104,15 +120,14 @@
"rss-parser": "3.12.0",
"rxjs": "7.8.0",
"s-age": "1.1.2",
- "sanitize-html": "2.9.0",
+ "sanitize-html": "2.10.0",
"seedrandom": "3.0.5",
"semver": "7.3.8",
"sharp": "0.31.3",
- "speakeasy": "2.0.0",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"summaly": "github:misskey-dev/summaly",
- "systeminformation": "5.17.8",
+ "systeminformation": "5.17.9",
"tinycolor2": "1.6.0",
"tmp": "0.2.1",
"tsc-alias": "1.8.2",
@@ -126,14 +141,12 @@
"vary": "1.1.2",
"web-push": "3.5.0",
"websocket": "1.0.34",
- "ws": "8.12.0",
+ "ws": "8.12.1",
"xev": "3.0.2"
},
"devDependencies": {
- "@jest/globals": "29.4.2",
+ "@jest/globals": "29.4.3",
"@redocly/openapi-core": "1.0.0-beta.123",
- "@swc/cli": "0.1.61",
- "@swc/core": "1.3.34",
"@swc/jest": "0.2.24",
"@types/accepts": "1.3.5",
"@types/archiver": "5.3.1",
@@ -151,7 +164,7 @@
"@types/jsonld": "1.5.8",
"@types/jsrsasign": "10.5.5",
"@types/mime-types": "2.1.1",
- "@types/node": "18.13.0",
+ "@types/node": "18.14.0",
"@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.7",
"@types/oauth": "0.9.1",
@@ -167,7 +180,6 @@
"@types/semver": "7.3.13",
"@types/sharp": "0.31.1",
"@types/sinonjs__fake-timers": "8.1.2",
- "@types/speakeasy": "2.0.7",
"@types/tinycolor2": "1.4.3",
"@types/tmp": "0.2.3",
"@types/unzipper": "0.10.5",
@@ -176,13 +188,13 @@
"@types/web-push": "3.3.2",
"@types/websocket": "1.0.5",
"@types/ws": "8.5.4",
- "@typescript-eslint/eslint-plugin": "5.51.0",
- "@typescript-eslint/parser": "5.51.0",
+ "@typescript-eslint/eslint-plugin": "5.52.0",
+ "@typescript-eslint/parser": "5.52.0",
"cross-env": "7.0.3",
- "eslint": "8.33.0",
+ "eslint": "8.34.0",
"eslint-plugin-import": "2.27.5",
"execa": "6.1.0",
- "jest": "29.4.2",
- "jest-mock": "29.4.2"
+ "jest": "29.4.3",
+ "jest-mock": "29.4.3"
}
-}
+} \ No newline at end of file
diff --git a/packages/backend/src/@types/redis-lock.d.ts b/packages/backend/src/@types/redis-lock.d.ts
new file mode 100644
index 0000000000..9242656a98
--- /dev/null
+++ b/packages/backend/src/@types/redis-lock.d.ts
@@ -0,0 +1,8 @@
+declare module 'redis-lock' {
+ import type Redis from 'ioredis';
+
+ type Lock = (lockName: string, timeout?: number, taskToPerform?: () => Promise<void>) => void;
+ function redisLock(client: Redis.Redis, retryDelay: number): Lock;
+
+ export = redisLock;
+}
diff --git a/packages/backend/src/core/AppLockService.ts b/packages/backend/src/core/AppLockService.ts
index 5f3072a415..ee179b7f01 100644
--- a/packages/backend/src/core/AppLockService.ts
+++ b/packages/backend/src/core/AppLockService.ts
@@ -12,7 +12,7 @@ const retryDelay = 100;
@Injectable()
export class AppLockService {
- private lock: (key: string, timeout?: number) => Promise<() => void>;
+ private lock: (key: string, timeout?: number, _?: (() => Promise<void>) | undefined) => Promise<() => void>;
constructor(
@Inject(DI.redis)
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index 8d961452c7..9b2d5dc0ff 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -1,7 +1,7 @@
import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common';
import * as parse5 from 'parse5';
-import { JSDOM } from 'jsdom';
+import { Window } from 'happy-dom';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { intersperse } from '@/misc/prelude/array.js';
@@ -235,7 +235,7 @@ export class MfmService {
return null;
}
- const { window } = new JSDOM('');
+ const { window } = new Window();
const doc = window.document;
@@ -300,7 +300,7 @@ export class MfmService {
hashtag: (node) => {
const a = doc.createElement('a');
- a.href = `${this.config.url}/tags/${node.props.hashtag}`;
+ a.setAttribute('href', `${this.config.url}/tags/${node.props.hashtag}`);
a.textContent = `#${node.props.hashtag}`;
a.setAttribute('rel', 'tag');
return a;
@@ -326,7 +326,7 @@ export class MfmService {
link: (node) => {
const a = doc.createElement('a');
- a.href = node.props.url;
+ a.setAttribute('href', node.props.url);
appendChildren(node.children, a);
return a;
},
@@ -335,7 +335,7 @@ export class MfmService {
const a = doc.createElement('a');
const { username, host, acct } = node.props;
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
- a.href = remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`;
+ a.setAttribute('href', remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`);
a.className = 'u-url mention';
a.textContent = acct;
return a;
@@ -360,14 +360,14 @@ export class MfmService {
url: (node) => {
const a = doc.createElement('a');
- a.href = node.props.url;
+ a.setAttribute('href', node.props.url);
a.textContent = node.props.url;
return a;
},
search: (node) => {
const a = doc.createElement('a');
- a.href = `https://www.google.com/search?q=${node.props.query}`;
+ a.setAttribute('href', `https://www.google.com/search?q=${node.props.query}`);
a.textContent = node.props.content;
return a;
},
diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts
index 75bf4b0e01..2cad1bc07e 100644
--- a/packages/backend/src/core/PushNotificationService.ts
+++ b/packages/backend/src/core/PushNotificationService.ts
@@ -9,7 +9,7 @@ import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js';
// Defined also packages/sw/types.ts#L13
-type pushNotificationsTypes = {
+type PushNotificationsTypes = {
'notification': Packed<'Notification'>;
'unreadAntennaNote': {
antenna: { id: string, name: string };
@@ -22,8 +22,8 @@ type pushNotificationsTypes = {
};
// Reduce length because push message servers have character limits
-function truncateBody<T extends keyof pushNotificationsTypes>(type: T, body: pushNotificationsTypes[T]): pushNotificationsTypes[T] {
- if (body === undefined) return body;
+function truncateBody<T extends keyof PushNotificationsTypes>(type: T, body: PushNotificationsTypes[T]): PushNotificationsTypes[T] {
+ if (typeof body !== 'object') return body;
return {
...body,
@@ -56,7 +56,7 @@ export class PushNotificationService {
}
@bindThis
- public async pushNotification<T extends keyof pushNotificationsTypes>(userId: string, type: T, body: pushNotificationsTypes[T]) {
+ public async pushNotification<T extends keyof PushNotificationsTypes>(userId: string, type: T, body: PushNotificationsTypes[T]) {
const meta = await this.metaService.fetch();
if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return;
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 9bd80b6066..6d9569bce2 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -450,9 +450,11 @@ export class ApInboxService {
return `skip: delete actor ${actor.uri} !== ${uri}`;
}
- const user = await this.usersRepository.findOneByOrFail({ id: actor.id });
- if (user.isDeleted) {
- this.logger.info('skip: already deleted');
+ const user = await this.usersRepository.findOneBy({ id: actor.id });
+ if (user == null) {
+ return 'skip: actor not found';
+ } else if (user.isDeleted) {
+ return 'skip: already deleted';
}
const job = await this.queueService.createDeleteAccountJob(actor);
diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts
index bfd53dfabf..71fbc29476 100644
--- a/packages/backend/src/core/activitypub/ApRequestService.ts
+++ b/packages/backend/src/core/activitypub/ApRequestService.ts
@@ -28,31 +28,15 @@ type PrivateKey = {
keyId: string;
};
-@Injectable()
-export class ApRequestService {
- private logger: Logger;
-
- constructor(
- @Inject(DI.config)
- private config: Config,
-
- private userKeypairStoreService: UserKeypairStoreService,
- private httpRequestService: HttpRequestService,
- private loggerService: LoggerService,
- ) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- this.logger = this.loggerService?.getLogger('ap-request'); // ãªãœã‹ TypeError: Cannot read properties of undefined (reading 'getLogger') ã¨è¨€ã‚れる
- }
-
- @bindThis
- private createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record<string, string> }): Signed {
+export class ApRequestCreator {
+ static createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url);
const digestHeader = `SHA-256=${crypto.createHash('sha256').update(args.body).digest('base64')}`;
const request: Request = {
url: u.href,
method: 'POST',
- headers: this.objectAssignWithLcKey({
+ headers: this.#objectAssignWithLcKey({
'Date': new Date().toUTCString(),
'Host': u.host,
'Content-Type': 'application/activity+json',
@@ -60,7 +44,7 @@ export class ApRequestService {
}, args.additionalHeaders),
};
- const result = this.signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
+ const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'digest']);
return {
request,
@@ -70,21 +54,20 @@ export class ApRequestService {
};
}
- @bindThis
- private createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
+ static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url);
const request: Request = {
url: u.href,
method: 'GET',
- headers: this.objectAssignWithLcKey({
+ headers: this.#objectAssignWithLcKey({
'Accept': 'application/activity+json, application/ld+json',
'Date': new Date().toUTCString(),
'Host': new URL(args.url).host,
}, args.additionalHeaders),
};
- const result = this.signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
+ const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
return {
request,
@@ -94,13 +77,12 @@ export class ApRequestService {
};
}
- @bindThis
- private signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]): Signed {
- const signingString = this.genSigningString(request, includeHeaders);
+ static #signToRequest(request: Request, key: PrivateKey, includeHeaders: string[]): Signed {
+ const signingString = this.#genSigningString(request, includeHeaders);
const signature = crypto.sign('sha256', Buffer.from(signingString), key.privateKeyPem).toString('base64');
const signatureHeader = `keyId="${key.keyId}",algorithm="rsa-sha256",headers="${includeHeaders.join(' ')}",signature="${signature}"`;
- request.headers = this.objectAssignWithLcKey(request.headers, {
+ request.headers = this.#objectAssignWithLcKey(request.headers, {
Signature: signatureHeader,
});
// node-fetch will generate this for us. if we keep 'Host', it won't change with redirects!
@@ -114,9 +96,8 @@ export class ApRequestService {
};
}
- @bindThis
- private genSigningString(request: Request, includeHeaders: string[]): string {
- request.headers = this.lcObjectKey(request.headers);
+ static #genSigningString(request: Request, includeHeaders: string[]): string {
+ request.headers = this.#lcObjectKey(request.headers);
const results: string[] = [];
@@ -131,16 +112,31 @@ export class ApRequestService {
return results.join('\n');
}
- @bindThis
- private lcObjectKey(src: Record<string, string>): Record<string, string> {
+ static #lcObjectKey(src: Record<string, string>): Record<string, string> {
const dst: Record<string, string> = {};
for (const key of Object.keys(src).filter(x => x !== '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key];
return dst;
}
- @bindThis
- private objectAssignWithLcKey(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
- return Object.assign(this.lcObjectKey(a), this.lcObjectKey(b));
+ static #objectAssignWithLcKey(a: Record<string, string>, b: Record<string, string>): Record<string, string> {
+ return Object.assign(this.#lcObjectKey(a), this.#lcObjectKey(b));
+ }
+}
+
+@Injectable()
+export class ApRequestService {
+ private logger: Logger;
+
+ constructor(
+ @Inject(DI.config)
+ private config: Config,
+
+ private userKeypairStoreService: UserKeypairStoreService,
+ private httpRequestService: HttpRequestService,
+ private loggerService: LoggerService,
+ ) {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ this.logger = this.loggerService?.getLogger('ap-request'); // ãªãœã‹ TypeError: Cannot read properties of undefined (reading 'getLogger') ã¨è¨€ã‚れる
}
@bindThis
@@ -149,7 +145,7 @@ export class ApRequestService {
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id);
- const req = this.createSignedPost({
+ const req = ApRequestCreator.createSignedPost({
key: {
privateKeyPem: keypair.privateKey,
keyId: `${this.config.url}/users/${user.id}#main-key`,
@@ -176,7 +172,7 @@ export class ApRequestService {
public async signedGet(url: string, user: { id: User['id'] }) {
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id);
- const req = this.createSignedGet({
+ const req = ApRequestCreator.createSignedGet({
key: {
privateKeyPem: keypair.privateKey,
keyId: `${this.config.url}/users/${user.id}#main-key`,
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 268bf99119..7f2ca9c05e 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -1,8 +1,8 @@
-export type obj = { [x: string]: any };
+export type Obj = { [x: string]: any };
export type ApObject = IObject | string | (IObject | string)[];
export interface IObject {
- '@context'?: string | string[] | obj | obj[];
+ '@context'?: string | string[] | Obj | Obj[];
type: string | string[];
id?: string;
name?: string | null;
diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts
index 34ff52ede8..33c76c6937 100644
--- a/packages/backend/src/core/entities/NotificationEntityService.ts
+++ b/packages/backend/src/core/entities/NotificationEntityService.ts
@@ -94,13 +94,6 @@ export class NotificationEntityService implements OnModuleInit {
}),
reaction: notification.reaction,
} : {}),
- ...(notification.type === 'pollVote' ? { // TODO: ãã®ã†ã¡æ¶ˆã™
- note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, {
- detail: true,
- _hint_: options._hintForEachNotes_,
- }),
- choice: notification.choice,
- } : {}),
...(notification.type === 'pollEnded' ? {
note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, {
detail: true,
diff --git a/packages/backend/src/core/entities/RoleEntityService.ts b/packages/backend/src/core/entities/RoleEntityService.ts
index f2ba642375..80ef5ac1fa 100644
--- a/packages/backend/src/core/entities/RoleEntityService.ts
+++ b/packages/backend/src/core/entities/RoleEntityService.ts
@@ -25,14 +25,7 @@ export class RoleEntityService {
public async pack(
src: Role['id'] | Role,
me?: { id: User['id'] } | null | undefined,
- options?: {
- detail?: boolean;
- },
) {
- const opts = Object.assign({
- detail: true,
- }, options);
-
const role = typeof src === 'object' ? src : await this.rolesRepository.findOneByOrFail({ id: src });
const assigns = await this.roleAssignmentsRepository.findBy({
@@ -65,9 +58,6 @@ export class RoleEntityService {
canEditMembersByModerator: role.canEditMembersByModerator,
policies: policies,
usersCount: assigns.length,
- ...(opts.detail ? {
- users: this.userEntityService.packMany(assigns.map(x => x.userId), me),
- } : {}),
});
}
@@ -75,11 +65,8 @@ export class RoleEntityService {
public packMany(
roles: any[],
me: { id: User['id'] },
- options?: {
- detail?: boolean;
- },
) {
- return Promise.all(roles.map(x => this.pack(x, me, options)));
+ return Promise.all(roles.map(x => this.pack(x, me)));
}
}
diff --git a/packages/backend/src/models/entities/Notification.ts b/packages/backend/src/models/entities/Notification.ts
index 105f0d0407..51117efba5 100644
--- a/packages/backend/src/models/entities/Notification.ts
+++ b/packages/backend/src/models/entities/Notification.ts
@@ -1,5 +1,5 @@
import { Entity, Index, JoinColumn, ManyToOne, Column, PrimaryColumn } from 'typeorm';
-import { notificationTypes } from '@/types.js';
+import { notificationTypes, obsoleteNotificationTypes } from '@/types.js';
import { id } from '../id.js';
import { User } from './User.js';
import { Note } from './Note.js';
@@ -58,7 +58,6 @@ export class Notification {
* renote - 投稿ãŒRenoteã•れãŸ
* quote - 投稿ãŒå¼•用Renoteã•れãŸ
* reaction - 投稿ã«ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã•れãŸ
- * pollVote - 投稿ã®ã‚¢ãƒ³ã‚±ãƒ¼ãƒˆã«æŠ•票ã•れ㟠(廃止)
* pollEnded - 自分ã®ã‚¢ãƒ³ã‚±ãƒ¼ãƒˆã‚‚ã—ãã¯è‡ªåˆ†ãŒæŠ•票ã—ãŸã‚¢ãƒ³ã‚±ãƒ¼ãƒˆãŒçµ‚了ã—ãŸ
* receiveFollowRequest - フォローリクエストã•れãŸ
* followRequestAccepted - 自分ã®é€ã£ãŸãƒ•ã‚©ãƒ­ãƒ¼ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒæ‰¿èªã•れãŸ
@@ -67,7 +66,10 @@ export class Notification {
*/
@Index()
@Column('enum', {
- enum: notificationTypes,
+ enum: [
+ ...notificationTypes,
+ ...obsoleteNotificationTypes,
+ ],
comment: 'The type of the Notification.',
})
public type: typeof notificationTypes[number];
diff --git a/packages/backend/src/models/entities/UserProfile.ts b/packages/backend/src/models/entities/UserProfile.ts
index 3d35b4cb5a..60c1c55de5 100644
--- a/packages/backend/src/models/entities/UserProfile.ts
+++ b/packages/backend/src/models/entities/UserProfile.ts
@@ -1,5 +1,5 @@
import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
-import { ffVisibility, notificationTypes } from '@/types.js';
+import { obsoleteNotificationTypes, ffVisibility, notificationTypes } from '@/types.js';
import { id } from '../id.js';
import { User } from './User.js';
import { Page } from './Page.js';
@@ -205,7 +205,7 @@ export class UserProfile {
enum: [
...notificationTypes,
// マイグレーションã§å‰Šé™¤ãŒå›°é›£ãªã®ã§å¤ã„enumã¯æ®‹ã—ã¦ãŠã
- 'groupInvited',
+ ...obsoleteNotificationTypes,
],
array: true,
default: [],
diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts
index cc27b36966..347fa59d36 100644
--- a/packages/backend/src/server/api/ApiCallService.ts
+++ b/packages/backend/src/server/api/ApiCallService.ts
@@ -108,9 +108,9 @@ export class ApiCallService implements OnApplicationShutdown {
const [path] = await createTemp();
await pump(multipartData.file, fs.createWriteStream(path));
- const fields = {} as Record<string, string | undefined>;
+ const fields = {} as Record<string, unknown>;
for (const [k, v] of Object.entries(multipartData.fields)) {
- fields[k] = v.value;
+ fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined;
}
const token = fields['i'];
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 30101a2c60..d3e2219bd5 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -66,6 +66,7 @@ import * as ep___admin_roles_update from './endpoints/admin/roles/update.js';
import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js';
import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js';
import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js';
+import * as ep___admin_roles_users from './endpoints/admin/roles/users.js';
import * as ep___announcements from './endpoints/announcements.js';
import * as ep___antennas_create from './endpoints/antennas/create.js';
import * as ep___antennas_delete from './endpoints/antennas/delete.js';
@@ -170,6 +171,7 @@ import * as ep___i_2fa_keyDone from './endpoints/i/2fa/key-done.js';
import * as ep___i_2fa_passwordLess from './endpoints/i/2fa/password-less.js';
import * as ep___i_2fa_registerKey from './endpoints/i/2fa/register-key.js';
import * as ep___i_2fa_register from './endpoints/i/2fa/register.js';
+import * as ep___i_2fa_updateKey from './endpoints/i/2fa/update-key.js';
import * as ep___i_2fa_removeKey from './endpoints/i/2fa/remove-key.js';
import * as ep___i_2fa_unregister from './endpoints/i/2fa/unregister.js';
import * as ep___i_apps from './endpoints/i/apps.js';
@@ -276,6 +278,9 @@ import * as ep___flash_myLikes from './endpoints/flash/my-likes.js';
import * as ep___ping from './endpoints/ping.js';
import * as ep___pinnedUsers from './endpoints/pinned-users.js';
import * as ep___promo_read from './endpoints/promo/read.js';
+import * as ep___roles_list from './endpoints/roles/list.js';
+import * as ep___roles_show from './endpoints/roles/show.js';
+import * as ep___roles_users from './endpoints/roles/users.js';
import * as ep___requestResetPassword from './endpoints/request-reset-password.js';
import * as ep___resetDb from './endpoints/reset-db.js';
import * as ep___resetPassword from './endpoints/reset-password.js';
@@ -382,6 +387,7 @@ const $admin_roles_update: Provider = { provide: 'ep:admin/roles/update', useCla
const $admin_roles_assign: Provider = { provide: 'ep:admin/roles/assign', useClass: ep___admin_roles_assign.default };
const $admin_roles_unassign: Provider = { provide: 'ep:admin/roles/unassign', useClass: ep___admin_roles_unassign.default };
const $admin_roles_updateDefaultPolicies: Provider = { provide: 'ep:admin/roles/update-default-policies', useClass: ep___admin_roles_updateDefaultPolicies.default };
+const $admin_roles_users: Provider = { provide: 'ep:admin/roles/users', useClass: ep___admin_roles_users.default };
const $announcements: Provider = { provide: 'ep:announcements', useClass: ep___announcements.default };
const $antennas_create: Provider = { provide: 'ep:antennas/create', useClass: ep___antennas_create.default };
const $antennas_delete: Provider = { provide: 'ep:antennas/delete', useClass: ep___antennas_delete.default };
@@ -486,6 +492,7 @@ const $i_2fa_keyDone: Provider = { provide: 'ep:i/2fa/key-done', useClass: ep___
const $i_2fa_passwordLess: Provider = { provide: 'ep:i/2fa/password-less', useClass: ep___i_2fa_passwordLess.default };
const $i_2fa_registerKey: Provider = { provide: 'ep:i/2fa/register-key', useClass: ep___i_2fa_registerKey.default };
const $i_2fa_register: Provider = { provide: 'ep:i/2fa/register', useClass: ep___i_2fa_register.default };
+const $i_2fa_updateKey: Provider = { provide: 'ep:i/2fa/update-key', useClass: ep___i_2fa_updateKey.default };
const $i_2fa_removeKey: Provider = { provide: 'ep:i/2fa/remove-key', useClass: ep___i_2fa_removeKey.default };
const $i_2fa_unregister: Provider = { provide: 'ep:i/2fa/unregister', useClass: ep___i_2fa_unregister.default };
const $i_apps: Provider = { provide: 'ep:i/apps', useClass: ep___i_apps.default };
@@ -592,6 +599,9 @@ const $flash_myLikes: Provider = { provide: 'ep:flash/my-likes', useClass: ep___
const $ping: Provider = { provide: 'ep:ping', useClass: ep___ping.default };
const $pinnedUsers: Provider = { provide: 'ep:pinned-users', useClass: ep___pinnedUsers.default };
const $promo_read: Provider = { provide: 'ep:promo/read', useClass: ep___promo_read.default };
+const $roles_list: Provider = { provide: 'ep:roles/list', useClass: ep___roles_list.default };
+const $roles_show: Provider = { provide: 'ep:roles/show', useClass: ep___roles_show.default };
+const $roles_users: Provider = { provide: 'ep:roles/users', useClass: ep___roles_users.default };
const $requestResetPassword: Provider = { provide: 'ep:request-reset-password', useClass: ep___requestResetPassword.default };
const $resetDb: Provider = { provide: 'ep:reset-db', useClass: ep___resetDb.default };
const $resetPassword: Provider = { provide: 'ep:reset-password', useClass: ep___resetPassword.default };
@@ -702,6 +712,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$admin_roles_assign,
$admin_roles_unassign,
$admin_roles_updateDefaultPolicies,
+ $admin_roles_users,
$announcements,
$antennas_create,
$antennas_delete,
@@ -806,6 +817,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$i_2fa_passwordLess,
$i_2fa_registerKey,
$i_2fa_register,
+ $i_2fa_updateKey,
$i_2fa_removeKey,
$i_2fa_unregister,
$i_apps,
@@ -912,6 +924,9 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$ping,
$pinnedUsers,
$promo_read,
+ $roles_list,
+ $roles_show,
+ $roles_users,
$requestResetPassword,
$resetDb,
$resetPassword,
@@ -1016,6 +1031,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$admin_roles_assign,
$admin_roles_unassign,
$admin_roles_updateDefaultPolicies,
+ $admin_roles_users,
$announcements,
$antennas_create,
$antennas_delete,
@@ -1120,6 +1136,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$i_2fa_passwordLess,
$i_2fa_registerKey,
$i_2fa_register,
+ $i_2fa_updateKey,
$i_2fa_removeKey,
$i_2fa_unregister,
$i_apps,
@@ -1226,6 +1243,9 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$ping,
$pinnedUsers,
$promo_read,
+ $roles_list,
+ $roles_show,
+ $roles_users,
$requestResetPassword,
$resetDb,
$resetPassword,
diff --git a/packages/backend/src/server/api/GetterService.ts b/packages/backend/src/server/api/GetterService.ts
index c7f9916f97..c94884a78c 100644
--- a/packages/backend/src/server/api/GetterService.ts
+++ b/packages/backend/src/server/api/GetterService.ts
@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { NotesRepository, UsersRepository } from '@/models/index.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
-import type { User } from '@/models/entities/User.js';
+import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
import type { Note } from '@/models/entities/Note.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js';
@@ -45,7 +45,7 @@ export class GetterService {
throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.');
}
- return user;
+ return user as LocalUser | RemoteUser;
}
/**
diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts
index f1164b9957..bd3d8a28da 100644
--- a/packages/backend/src/server/api/SigninApiService.ts
+++ b/packages/backend/src/server/api/SigninApiService.ts
@@ -1,7 +1,7 @@
import { randomBytes } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common';
import bcrypt from 'bcryptjs';
-import * as speakeasy from 'speakeasy';
+import * as OTPAuth from 'otpauth';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { UserSecurityKeysRepository, SigninsRepository, UserProfilesRepository, AttestationChallengesRepository, UsersRepository } from '@/models/index.js';
@@ -155,19 +155,19 @@ export class SigninApiService {
});
}
- const verified = (speakeasy as any).totp.verify({
- secret: profile.twoFactorSecret,
- encoding: 'base32',
- token: token,
- window: 2,
+ const delta = OTPAuth.TOTP.validate({
+ secret: OTPAuth.Secret.fromBase32(profile.twoFactorSecret!),
+ digits: 6,
+ token,
+ window: 1,
});
- if (verified) {
- return this.signinService.signin(request, reply, user);
- } else {
+ if (delta === null) {
return await fail(403, {
id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f',
});
+ } else {
+ return this.signinService.signin(request, reply, user);
}
} else if (body.credentialId && body.clientDataJSON && body.authenticatorData && body.signature) {
if (!same && !profile.usePasswordLessLogin) {
diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts
index 115526d997..ed283eb834 100644
--- a/packages/backend/src/server/api/endpoint-base.ts
+++ b/packages/backend/src/server/api/endpoint-base.ts
@@ -20,14 +20,14 @@ type File = {
};
// TODO: paramsã®åž‹ã‚’T['params']ã®ã‚¹ã‚­ãƒ¼ãƒžå®šç¾©ã‹ã‚‰æŽ¨è«–ã™ã‚‹
-type executor<T extends IEndpointMeta, Ps extends Schema> =
+type Executor<T extends IEndpointMeta, Ps extends Schema> =
(params: SchemaType<Ps>, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record<string, string> | null) =>
Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
export abstract class Endpoint<T extends IEndpointMeta, Ps extends Schema> {
public exec: (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => Promise<any>;
- constructor(meta: T, paramDef: Ps, cb: executor<T, Ps>) {
+ constructor(meta: T, paramDef: Ps, cb: Executor<T, Ps>) {
const validate = ajv.compile(paramDef);
this.exec = (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record<string, string> | null) => {
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index d05005b078..4d5ed9fb62 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -66,6 +66,7 @@ import * as ep___admin_roles_update from './endpoints/admin/roles/update.js';
import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js';
import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js';
import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js';
+import * as ep___admin_roles_users from './endpoints/admin/roles/users.js';
import * as ep___announcements from './endpoints/announcements.js';
import * as ep___antennas_create from './endpoints/antennas/create.js';
import * as ep___antennas_delete from './endpoints/antennas/delete.js';
@@ -170,6 +171,7 @@ import * as ep___i_2fa_keyDone from './endpoints/i/2fa/key-done.js';
import * as ep___i_2fa_passwordLess from './endpoints/i/2fa/password-less.js';
import * as ep___i_2fa_registerKey from './endpoints/i/2fa/register-key.js';
import * as ep___i_2fa_register from './endpoints/i/2fa/register.js';
+import * as ep___i_2fa_updateKey from './endpoints/i/2fa/update-key.js';
import * as ep___i_2fa_removeKey from './endpoints/i/2fa/remove-key.js';
import * as ep___i_2fa_unregister from './endpoints/i/2fa/unregister.js';
import * as ep___i_apps from './endpoints/i/apps.js';
@@ -276,6 +278,9 @@ import * as ep___flash_myLikes from './endpoints/flash/my-likes.js';
import * as ep___ping from './endpoints/ping.js';
import * as ep___pinnedUsers from './endpoints/pinned-users.js';
import * as ep___promo_read from './endpoints/promo/read.js';
+import * as ep___roles_list from './endpoints/roles/list.js';
+import * as ep___roles_show from './endpoints/roles/show.js';
+import * as ep___roles_users from './endpoints/roles/users.js';
import * as ep___requestResetPassword from './endpoints/request-reset-password.js';
import * as ep___resetDb from './endpoints/reset-db.js';
import * as ep___resetPassword from './endpoints/reset-password.js';
@@ -380,6 +385,7 @@ const eps = [
['admin/roles/assign', ep___admin_roles_assign],
['admin/roles/unassign', ep___admin_roles_unassign],
['admin/roles/update-default-policies', ep___admin_roles_updateDefaultPolicies],
+ ['admin/roles/users', ep___admin_roles_users],
['announcements', ep___announcements],
['antennas/create', ep___antennas_create],
['antennas/delete', ep___antennas_delete],
@@ -484,6 +490,7 @@ const eps = [
['i/2fa/password-less', ep___i_2fa_passwordLess],
['i/2fa/register-key', ep___i_2fa_registerKey],
['i/2fa/register', ep___i_2fa_register],
+ ['i/2fa/update-key', ep___i_2fa_updateKey],
['i/2fa/remove-key', ep___i_2fa_removeKey],
['i/2fa/unregister', ep___i_2fa_unregister],
['i/apps', ep___i_apps],
@@ -590,6 +597,9 @@ const eps = [
['ping', ep___ping],
['pinned-users', ep___pinnedUsers],
['promo/read', ep___promo_read],
+ ['roles/list', ep___roles_list],
+ ['roles/show', ep___roles_show],
+ ['roles/users', ep___roles_users],
['request-reset-password', ep___requestResetPassword],
['reset-db', ep___resetDb],
['reset-password', ep___resetPassword],
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index 6376cb153c..85b566aabe 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -1,5 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
-import type { DriveFilesRepository } from '@/models/index.js';
+import type { DriveFilesRepository, UsersRepository } from '@/models/index.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
@@ -161,6 +161,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository,
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+
private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
@@ -178,7 +181,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new ApiError(meta.errors.noSuchFile);
}
- const isModerator = await this.roleService.isModerator(me);
+ const owner = file.userId ? await this.usersRepository.findOneByOrFail({
+ id: file.userId,
+ }) : null;
+
+ const iAmModerator = await this.roleService.isModerator(me);
+ const ownerIsModerator = owner ? await this.roleService.isModerator(owner) : false;
return {
id: file.id,
@@ -207,8 +215,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
name: file.name,
md5: file.md5,
createdAt: file.createdAt.toISOString(),
- requestIp: isModerator ? file.requestIp : null,
- requestHeaders: isModerator ? file.requestHeaders : null,
+ requestIp: iAmModerator ? file.requestIp : null,
+ requestHeaders: iAmModerator && !ownerIsModerator ? file.requestHeaders : null,
};
});
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/list.ts b/packages/backend/src/server/api/endpoints/admin/roles/list.ts
index ac56de56b9..edaf638ea9 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/list.ts
@@ -32,7 +32,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const roles = await this.rolesRepository.find({
order: { lastUsedAt: 'DESC' },
});
- return await this.roleEntityService.packMany(roles, me, { detail: false });
+ return await this.roleEntityService.packMany(roles, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/show.ts b/packages/backend/src/server/api/endpoints/admin/roles/show.ts
index c83f96191d..01028a086f 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/show.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/show.ts
@@ -39,12 +39,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private roleEntityService: RoleEntityService,
) {
- super(meta, paramDef, async (ps) => {
+ super(meta, paramDef, async (ps, me) => {
const role = await this.rolesRepository.findOneBy({ id: ps.roleId });
if (role == null) {
throw new ApiError(meta.errors.noSuchRole);
}
- return await this.roleEntityService.pack(role);
+ return await this.roleEntityService.pack(role, me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
new file mode 100644
index 0000000000..bb016a8425
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
@@ -0,0 +1,71 @@
+import { Inject, Injectable } from '@nestjs/common';
+import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { QueryService } from '@/core/QueryService.js';
+import { DI } from '@/di-symbols.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { ApiError } from '../../../error.js';
+
+export const meta = {
+ tags: ['admin', 'role', 'users'],
+
+ requireCredential: false,
+ requireAdmin: true,
+
+ errors: {
+ noSuchRole: {
+ message: 'No such role.',
+ code: 'NO_SUCH_ROLE',
+ id: '224eff5e-2488-4b18-b3e7-f50d94421648',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ roleId: { type: 'string', format: 'misskey:id' },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+ },
+ required: ['roleId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.rolesRepository)
+ private rolesRepository: RolesRepository,
+
+ @Inject(DI.roleAssignmentsRepository)
+ private roleAssignmentsRepository: RoleAssignmentsRepository,
+
+ private queryService: QueryService,
+ private userEntityService: UserEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const role = await this.rolesRepository.findOneBy({
+ id: ps.roleId,
+ });
+
+ if (role == null) {
+ throw new ApiError(meta.errors.noSuchRole);
+ }
+
+ const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId)
+ .andWhere('assign.roleId = :roleId', { roleId: role.id })
+ .innerJoinAndSelect('assign.user', 'user');
+
+ const assigns = await query
+ .take(ps.limit)
+ .getMany();
+
+ return await Promise.all(assigns.map(async assign => ({
+ id: assign.id,
+ user: await this.userEntityService.pack(assign.user!, me, { detail: true }),
+ })));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts
index 823af6d8be..9d19efbbcf 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts
@@ -59,12 +59,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new Error('cannot show info of admin');
}
- if (!await this.roleService.isAdministrator(_me)) {
- return {
- isSuspended: user.isSuspended,
- };
- }
-
const signins = await this.signinsRepository.findBy({ userId: user.id });
const roles = await this.roleService.getUserRoles(user.id);
@@ -89,7 +83,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
moderationNote: profile.moderationNote,
signins,
policies: await this.roleService.getUserPolicies(user.id),
- roles: await this.roleEntityService.packMany(roles, me, { detail: false }),
+ roles: await this.roleEntityService.packMany(roles, me),
};
});
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
index ec9ac1ef90..6c31075e05 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
@@ -1,7 +1,10 @@
-import * as speakeasy from 'speakeasy';
+import * as OTPAuth from 'otpauth';
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { UserProfilesRepository } from '@/models/index.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
export const meta = {
@@ -22,8 +25,14 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.config)
+ private config: Config,
+
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private userEntityService: UserEntityService,
+ private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
const token = ps.token.replace(/\s/g, '');
@@ -34,13 +43,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new Error('二段階èªè¨¼ã®è¨­å®šãŒé–‹å§‹ã•れã¦ã„ã¾ã›ã‚“');
}
- const verified = (speakeasy as any).totp.verify({
- secret: profile.twoFactorTempSecret,
- encoding: 'base32',
- token: token,
+ const delta = OTPAuth.TOTP.validate({
+ secret: OTPAuth.Secret.fromBase32(profile.twoFactorTempSecret),
+ digits: 6,
+ token,
+ window: 1,
});
- if (!verified) {
+ if (delta === null) {
throw new Error('not verified');
}
@@ -48,6 +58,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
twoFactorSecret: profile.twoFactorTempSecret,
twoFactorEnabled: true,
});
+
+ // Publish meUpdated event
+ this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, {
+ detail: true,
+ includeSecrets: true,
+ }));
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
index 6e0849f2b2..ad33398da6 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
@@ -25,7 +25,7 @@ export const paramDef = {
attestationObject: { type: 'string' },
password: { type: 'string' },
challengeId: { type: 'string' },
- name: { type: 'string' },
+ name: { type: 'string', minLength: 1, maxLength: 30 },
},
required: ['clientDataJSON', 'attestationObject', 'password', 'challengeId', 'name'],
} as const;
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
index 0655a86350..0ee9f556a8 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
@@ -1,12 +1,23 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { UserProfilesRepository } from '@/models/index.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
+import { ApiError } from '../../../error.js';
export const meta = {
requireCredential: true,
secure: true,
+
+ errors: {
+ noKey: {
+ message: 'No security key.',
+ code: 'NO_SECURITY_KEY',
+ id: 'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512',
+ },
+ },
} as const;
export const paramDef = {
@@ -23,11 +34,45 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ @Inject(DI.userSecurityKeysRepository)
+ private userSecurityKeysRepository: UserSecurityKeysRepository,
+
+ private userEntityService: UserEntityService,
+ private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
+ if (ps.value === true) {
+ // セキュリティキーãŒãªã‘れã°ãƒ‘スワードレスを有効ã«ã¯ã§ããªã„
+ const keyCount = await this.userSecurityKeysRepository.count({
+ where: {
+ userId: me.id,
+ },
+ select: {
+ id: true,
+ name: true,
+ lastUsed: true,
+ },
+ });
+
+ if (keyCount === 0) {
+ await this.userProfilesRepository.update(me.id, {
+ usePasswordLessLogin: false,
+ });
+
+ throw new ApiError(meta.errors.noKey);
+ }
+ }
+
await this.userProfilesRepository.update(me.id, {
usePasswordLessLogin: ps.value,
});
+
+ // Publish meUpdated event
+ this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, {
+ detail: true,
+ includeSecrets: true,
+ }));
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
index a539c5c221..eb4d7f9c14 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
@@ -1,5 +1,5 @@
import bcrypt from 'bcryptjs';
-import * as speakeasy from 'speakeasy';
+import * as OTPAuth from 'otpauth';
import * as QRCode from 'qrcode';
import { Inject, Injectable } from '@nestjs/common';
import type { UserProfilesRepository } from '@/models/index.js';
@@ -42,25 +42,24 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
// Generate user's secret key
- const secret = speakeasy.generateSecret({
- length: 32,
- });
+ const secret = new OTPAuth.Secret();
await this.userProfilesRepository.update(me.id, {
twoFactorTempSecret: secret.base32,
});
// Get the data URL of the authenticator URL
- const url = speakeasy.otpauthURL({
- secret: secret.base32,
- encoding: 'base32',
+ const totp = new OTPAuth.TOTP({
+ secret,
+ digits: 6,
label: me.username,
issuer: this.config.host,
});
- const dataUrl = await QRCode.toDataURL(url);
+ const url = totp.toString();
+ const qr = await QRCode.toDataURL(url);
return {
- qr: dataUrl,
+ qr,
url,
secret: secret.base32,
label: me.username,
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
index 0f2b0fd7ee..4b726aed80 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
@@ -50,6 +50,24 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
id: ps.credentialId,
});
+ // 使ã‚れã¦ã„るキーãŒãªããªã£ãŸã‚‰ãƒ‘スワードレスログインをやã‚ã‚‹
+ const keyCount = await this.userSecurityKeysRepository.count({
+ where: {
+ userId: me.id,
+ },
+ select: {
+ id: true,
+ name: true,
+ lastUsed: true,
+ },
+ });
+
+ if (keyCount === 0) {
+ await this.userProfilesRepository.update(me.id, {
+ usePasswordLessLogin: false,
+ });
+ }
+
// Publish meUpdated event
this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, {
detail: true,
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
index 4c5b151f78..e0e7ba6658 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
@@ -1,7 +1,9 @@
import bcrypt from 'bcryptjs';
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { UserProfilesRepository } from '@/models/index.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
export const meta = {
@@ -24,6 +26,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private userEntityService: UserEntityService,
+ private globalEventService: GlobalEventService,
) {
super(meta, paramDef, async (ps, me) => {
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
@@ -38,7 +43,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.userProfilesRepository.update(me.id, {
twoFactorSecret: null,
twoFactorEnabled: false,
+ usePasswordLessLogin: false,
});
+
+ // Publish meUpdated event
+ this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, {
+ detail: true,
+ includeSecrets: true,
+ }));
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts
new file mode 100644
index 0000000000..d98f60fa5f
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts
@@ -0,0 +1,78 @@
+import bcrypt from 'bcryptjs';
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/index.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { DI } from '@/di-symbols.js';
+import { ApiError } from '../../../error.js';
+
+export const meta = {
+ requireCredential: true,
+
+ secure: true,
+
+ errors: {
+ noSuchKey: {
+ message: 'No such key.',
+ code: 'NO_SUCH_KEY',
+ id: 'f9c5467f-d492-4d3c-9a8g-a70dacc86512',
+ },
+
+ accessDenied: {
+ message: 'You do not have edit privilege of the channel.',
+ code: 'ACCESS_DENIED',
+ id: '1fb7cb09-d46a-4fff-b8df-057708cce513',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ name: { type: 'string', minLength: 1, maxLength: 30 },
+ credentialId: { type: 'string' },
+ },
+ required: ['name', 'credentialId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.userSecurityKeysRepository)
+ private userSecurityKeysRepository: UserSecurityKeysRepository,
+
+ @Inject(DI.userProfilesRepository)
+ private userProfilesRepository: UserProfilesRepository,
+
+ private userEntityService: UserEntityService,
+ private globalEventService: GlobalEventService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const key = await this.userSecurityKeysRepository.findOneBy({
+ id: ps.credentialId,
+ });
+
+ if (key == null) {
+ throw new ApiError(meta.errors.noSuchKey);
+ }
+
+ if (key.userId !== me.id) {
+ throw new ApiError(meta.errors.accessDenied);
+ }
+
+ await this.userSecurityKeysRepository.update(key.id, {
+ name: ps.name,
+ });
+
+ // Publish meUpdated event
+ this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, {
+ detail: true,
+ includeSecrets: true,
+ }));
+
+ return {};
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts
index 706e0d2089..e3897d38bd 100644
--- a/packages/backend/src/server/api/endpoints/i/notifications.ts
+++ b/packages/backend/src/server/api/endpoints/i/notifications.ts
@@ -1,7 +1,7 @@
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
import type { UsersRepository, FollowingsRepository, MutingsRepository, UserProfilesRepository, NotificationsRepository } from '@/models/index.js';
-import { notificationTypes } from '@/types.js';
+import { obsoleteNotificationTypes, notificationTypes } from '@/types.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import { NoteReadService } from '@/core/NoteReadService.js';
@@ -41,11 +41,12 @@ export const paramDef = {
following: { type: 'boolean', default: false },
unreadOnly: { type: 'boolean', default: false },
markAsRead: { type: 'boolean', default: true },
+ // 後方互æ›ã®ãŸã‚ã€å»ƒæ­¢ã•れãŸé€šçŸ¥ã‚¿ã‚¤ãƒ—ã‚‚å—ã‘付ã‘ã‚‹
includeTypes: { type: 'array', items: {
- type: 'string', enum: notificationTypes,
+ type: 'string', enum: [...notificationTypes, ...obsoleteNotificationTypes],
} },
excludeTypes: { type: 'array', items: {
- type: 'string', enum: notificationTypes,
+ type: 'string', enum: [...notificationTypes, ...obsoleteNotificationTypes],
} },
},
required: [],
@@ -84,6 +85,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (notificationTypes.every(type => ps.excludeTypes?.includes(type))) {
return [];
}
+
+ const includeTypes = ps.includeTypes && ps.includeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][];
+ const excludeTypes = ps.excludeTypes && ps.excludeTypes.filter(type => !(obsoleteNotificationTypes).includes(type as any)) as typeof notificationTypes[number][];
+
const followingQuery = this.followingsRepository.createQueryBuilder('following')
.select('following.followeeId')
.where('following.followerId = :followerId', { followerId: me.id });
@@ -143,10 +148,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
query.setParameters(followingQuery.getParameters());
}
- if (ps.includeTypes && ps.includeTypes.length > 0) {
- query.andWhere('notification.type IN (:...includeTypes)', { includeTypes: ps.includeTypes });
- } else if (ps.excludeTypes && ps.excludeTypes.length > 0) {
- query.andWhere('notification.type NOT IN (:...excludeTypes)', { excludeTypes: ps.excludeTypes });
+ if (includeTypes && includeTypes.length > 0) {
+ query.andWhere('notification.type IN (:...includeTypes)', { includeTypes });
+ } else if (excludeTypes && excludeTypes.length > 0) {
+ query.andWhere('notification.type NOT IN (:...excludeTypes)', { excludeTypes });
}
if (ps.unreadOnly) {
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 593444968e..f4c5a84a4f 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -79,6 +79,12 @@ export const meta = {
code: 'YOU_HAVE_BEEN_BLOCKED',
id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3',
},
+
+ noSuchFile: {
+ message: 'Some files are not found.',
+ code: 'NO_SUCH_FILE',
+ id: 'b6992544-63e7-67f0-fa7f-32444b1b5306',
+ },
},
} as const;
@@ -207,6 +213,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.orderBy('array_position(ARRAY[:...fileIds], "id"::text)')
.setParameters({ fileIds })
.getMany();
+
+ if (files.length !== fileIds.length) {
+ throw new ApiError(meta.errors.noSuchFile);
+ }
}
let renote: Note | null = null;
diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts
index 8eff8fdb22..cf939f6631 100644
--- a/packages/backend/src/server/api/endpoints/notes/featured.ts
+++ b/packages/backend/src/server/api/endpoints/notes/featured.ts
@@ -28,6 +28,7 @@ export const paramDef = {
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
offset: { type: 'integer', default: 0 },
+ channelId: { type: 'string', nullable: true, format: 'misskey:id' },
},
required: [],
} as const;
@@ -63,12 +64,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
+ if (ps.channelId) query.andWhere('note.channelId = :channelId', { channelId: ps.channelId });
+
if (me) this.queryService.generateMutedUserQuery(query, me);
if (me) this.queryService.generateBlockedUserQuery(query, me);
let notes = await query
.orderBy('note.score', 'DESC')
- .take(ps.limit)
+ .take(50)
.getMany();
notes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
diff --git a/packages/backend/src/server/api/endpoints/roles/list.ts b/packages/backend/src/server/api/endpoints/roles/list.ts
new file mode 100644
index 0000000000..d61c6b8dc6
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/roles/list.ts
@@ -0,0 +1,37 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import type { RolesRepository } from '@/models/index.js';
+import { DI } from '@/di-symbols.js';
+import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
+
+export const meta = {
+ tags: ['role'],
+
+ requireCredential: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ },
+ required: [
+ ],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.rolesRepository)
+ private rolesRepository: RolesRepository,
+
+ private roleEntityService: RoleEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const roles = await this.rolesRepository.findBy({
+ isPublic: true,
+ });
+ return await this.roleEntityService.packMany(roles, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/roles/show.ts b/packages/backend/src/server/api/endpoints/roles/show.ts
new file mode 100644
index 0000000000..cc755dcc76
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/roles/show.ts
@@ -0,0 +1,52 @@
+import { Inject, Injectable } from '@nestjs/common';
+import type { RolesRepository } from '@/models/index.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DI } from '@/di-symbols.js';
+import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
+import { ApiError } from '../../error.js';
+
+export const meta = {
+ tags: ['role', 'users'],
+
+ requireCredential: false,
+
+ errors: {
+ noSuchRole: {
+ message: 'No such role.',
+ code: 'NO_SUCH_ROLE',
+ id: 'de5502bf-009a-4639-86c1-fec349e46dcb',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ roleId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['roleId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.rolesRepository)
+ private rolesRepository: RolesRepository,
+
+ private roleEntityService: RoleEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const role = await this.rolesRepository.findOneBy({
+ id: ps.roleId,
+ isPublic: true,
+ });
+
+ if (role == null) {
+ throw new ApiError(meta.errors.noSuchRole);
+ }
+
+ return await this.roleEntityService.pack(role, me);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/roles/users.ts b/packages/backend/src/server/api/endpoints/roles/users.ts
new file mode 100644
index 0000000000..6e221b6c67
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/roles/users.ts
@@ -0,0 +1,71 @@
+import { Inject, Injectable } from '@nestjs/common';
+import type { RoleAssignmentsRepository, RolesRepository } from '@/models/index.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { QueryService } from '@/core/QueryService.js';
+import { DI } from '@/di-symbols.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { ApiError } from '../../error.js';
+
+export const meta = {
+ tags: ['role', 'users'],
+
+ requireCredential: false,
+
+ errors: {
+ noSuchRole: {
+ message: 'No such role.',
+ code: 'NO_SUCH_ROLE',
+ id: '30aaaee3-4792-48dc-ab0d-cf501a575ac5',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ roleId: { type: 'string', format: 'misskey:id' },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+ },
+ required: ['roleId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.rolesRepository)
+ private rolesRepository: RolesRepository,
+
+ @Inject(DI.roleAssignmentsRepository)
+ private roleAssignmentsRepository: RoleAssignmentsRepository,
+
+ private queryService: QueryService,
+ private userEntityService: UserEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const role = await this.rolesRepository.findOneBy({
+ id: ps.roleId,
+ isPublic: true,
+ });
+
+ if (role == null) {
+ throw new ApiError(meta.errors.noSuchRole);
+ }
+
+ const query = this.queryService.makePaginationQuery(this.roleAssignmentsRepository.createQueryBuilder('assign'), ps.sinceId, ps.untilId)
+ .andWhere('assign.roleId = :roleId', { roleId: role.id })
+ .innerJoinAndSelect('assign.user', 'user');
+
+ const assigns = await query
+ .take(ps.limit)
+ .getMany();
+
+ return await Promise.all(assigns.map(async assign => ({
+ id: assign.id,
+ user: await this.userEntityService.pack(assign.user!, me, { detail: true }),
+ })));
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
index 8b22f913d2..1cefcf2707 100644
--- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
@@ -1,6 +1,7 @@
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
+import type { Config } from '@/config.js';
import type { User } from '@/models/entities/User.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
@@ -36,13 +37,13 @@ export const paramDef = {
properties: {
username: { type: 'string', nullable: true },
},
- required: ['username']
+ required: ['username'],
},
{
properties: {
host: { type: 'string', nullable: true },
},
- required: ['host']
+ required: ['host'],
},
],
} as const;
@@ -53,6 +54,9 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> {
constructor(
+ @Inject(DI.config)
+ private config: Config,
+
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@@ -62,79 +66,76 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private userEntityService: UserEntityService,
) {
super(meta, paramDef, async (ps, me) => {
- const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30æ—¥
-
- if (ps.host) {
- const q = this.usersRepository.createQueryBuilder('user')
- .where('user.isSuspended = FALSE')
- .andWhere('user.host LIKE :host', { host: sqlLikeEscape(ps.host.toLowerCase()) + '%' });
-
+ const setUsernameAndHostQuery = (query = this.usersRepository.createQueryBuilder('user')) => {
if (ps.username) {
- q.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' });
+ query.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' });
}
- q.andWhere('user.updatedAt IS NOT NULL');
- q.orderBy('user.updatedAt', 'DESC');
+ if (ps.host) {
+ if (ps.host === this.config.hostname || ps.host === '.') {
+ query.andWhere('user.host IS NULL');
+ } else {
+ query.andWhere('user.host LIKE :host', {
+ host: sqlLikeEscape(ps.host.toLowerCase()) + '%',
+ });
+ }
+ }
- const users = await q.take(ps.limit).getMany();
+ return query;
+ };
- return await this.userEntityService.packMany(users, me, { detail: ps.detail });
- } else if (ps.username) {
- let users: User[] = [];
+ const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30æ—¥
- if (me) {
- const followingQuery = this.followingsRepository.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: me.id });
+ let users: User[] = [];
- const query = this.usersRepository.createQueryBuilder('user')
- .where(`user.id IN (${ followingQuery.getQuery() })`)
- .andWhere('user.id != :meId', { meId: me.id })
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' })
- .andWhere(new Brackets(qb => { qb
- .where('user.updatedAt IS NULL')
- .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
- }));
+ if (me) {
+ const followingQuery = this.followingsRepository.createQueryBuilder('following')
+ .select('following.followeeId')
+ .where('following.followerId = :followerId', { followerId: me.id });
- query.setParameters(followingQuery.getParameters());
+ const query = setUsernameAndHostQuery()
+ .andWhere(`user.id IN (${ followingQuery.getQuery() })`)
+ .andWhere('user.id != :meId', { meId: me.id })
+ .andWhere('user.isSuspended = FALSE')
+ .andWhere(new Brackets(qb => { qb
+ .where('user.updatedAt IS NULL')
+ .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
+ }));
- users = await query
- .orderBy('user.usernameLower', 'ASC')
- .take(ps.limit)
- .getMany();
+ query.setParameters(followingQuery.getParameters());
- if (users.length < ps.limit) {
- const otherQuery = await this.usersRepository.createQueryBuilder('user')
- .where(`user.id NOT IN (${ followingQuery.getQuery() })`)
- .andWhere('user.id != :meId', { meId: me.id })
- .andWhere('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' })
- .andWhere('user.updatedAt IS NOT NULL');
+ users = await query
+ .orderBy('user.usernameLower', 'ASC')
+ .take(ps.limit)
+ .getMany();
- otherQuery.setParameters(followingQuery.getParameters());
+ if (users.length < ps.limit) {
+ const otherQuery = setUsernameAndHostQuery()
+ .andWhere(`user.id NOT IN (${ followingQuery.getQuery() })`)
+ .andWhere('user.isSuspended = FALSE')
+ .andWhere('user.updatedAt IS NOT NULL');
- const otherUsers = await otherQuery
- .orderBy('user.updatedAt', 'DESC')
- .take(ps.limit - users.length)
- .getMany();
+ otherQuery.setParameters(followingQuery.getParameters());
- users = users.concat(otherUsers);
- }
- } else {
- users = await this.usersRepository.createQueryBuilder('user')
- .where('user.isSuspended = FALSE')
- .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' })
- .andWhere('user.updatedAt IS NOT NULL')
+ const otherUsers = await otherQuery
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit - users.length)
.getMany();
+
+ users = users.concat(otherUsers);
}
+ } else {
+ const query = setUsernameAndHostQuery()
+ .andWhere('user.isSuspended = FALSE')
+ .andWhere('user.updatedAt IS NOT NULL');
- return await this.userEntityService.packMany(users, me, { detail: !!ps.detail });
+ users = await query
+ .orderBy('user.updatedAt', 'DESC')
+ .take(ps.limit - users.length)
+ .getMany();
}
- return [];
+ return await this.userEntityService.packMany(users, me, { detail: !!ps.detail });
});
}
}
diff --git a/packages/backend/src/server/web/manifest.json b/packages/backend/src/server/web/manifest.json
index 48030a2980..41171d62a1 100644
--- a/packages/backend/src/server/web/manifest.json
+++ b/packages/backend/src/server/web/manifest.json
@@ -9,16 +9,26 @@
{
"src": "/static-assets/icons/192.png",
"sizes": "192x192",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
},
{
"src": "/static-assets/icons/512.png",
"sizes": "512x512",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/static-assets/splash.png",
+ "sizes": "300x300",
+ "type": "image/png",
+ "purpose": "any"
}
],
"share_target": {
"action": "/share/",
+ "method": "GET",
+ "enctype": "application/x-www-form-urlencoded",
"params": {
"title": "title",
"text": "text",
diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts
index 8ac65a021c..7c6a1e5199 100644
--- a/packages/backend/src/types.ts
+++ b/packages/backend/src/types.ts
@@ -1,4 +1,5 @@
-export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] as const;
+export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] as const;
+export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const;
export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const;
diff --git a/packages/backend/test/tests/mfm.ts b/packages/backend/test/tests/mfm.ts
deleted file mode 100644
index 884f39d7fb..0000000000
--- a/packages/backend/test/tests/mfm.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import * as assert from 'assert';
-import * as mfm from 'mfm-js';
-
-import { toHtml } from '../../src/mfm/to-html.js';
-import { fromHtml } from '../../src/mfm/from-html.js';
-
-describe('toHtml', () => {
- test('br', () => {
- const input = 'foo\nbar\nbaz';
- const output = '<p><span>foo<br>bar<br>baz</span></p>';
- assert.equal(toHtml(mfm.parse(input)), output);
- });
-
- test('br alt', () => {
- const input = 'foo\r\nbar\rbaz';
- const output = '<p><span>foo<br>bar<br>baz</span></p>';
- assert.equal(toHtml(mfm.parse(input)), output);
- });
-});
-
-describe('fromHtml', () => {
- test('p', () => {
- assert.deepStrictEqual(fromHtml('<p>a</p><p>b</p>'), 'a\n\nb');
- });
-
- test('block element', () => {
- assert.deepStrictEqual(fromHtml('<div>a</div><div>b</div>'), 'a\nb');
- });
-
- test('inline element', () => {
- assert.deepStrictEqual(fromHtml('<ul><li>a</li><li>b</li></ul>'), 'a\nb');
- });
-
- test('block code', () => {
- assert.deepStrictEqual(fromHtml('<pre><code>a\nb</code></pre>'), '```\na\nb\n```');
- });
-
- test('inline code', () => {
- assert.deepStrictEqual(fromHtml('<code>a</code>'), '`a`');
- });
-
- test('quote', () => {
- assert.deepStrictEqual(fromHtml('<blockquote>a\nb</blockquote>'), '> a\n> b');
- });
-
- test('br', () => {
- assert.deepStrictEqual(fromHtml('<p>abc<br><br/>d</p>'), 'abc\n\nd');
- });
-
- test('link with different text', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/b">c</a> d</p>'), 'a [c](https://example.com/b) d');
- });
-
- test('link with different text, but not encoded', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/ä">c</a> d</p>'), 'a [c](<https://example.com/ä>) d');
- });
-
- test('link with same text', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/b">https://example.com/b</a> d</p>'), 'a https://example.com/b d');
- });
-
- test('link with same text, but not encoded', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/ä">https://example.com/ä</a> d</p>'), 'a <https://example.com/ä> d');
- });
-
- test('link with no url', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="b">c</a> d</p>'), 'a [c](b) d');
- });
-
- test('link without href', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a>c</a> d</p>'), 'a c d');
- });
-
- test('link without text', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/b"></a> d</p>'), 'a https://example.com/b d');
- });
-
- test('link without both', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a></a> d</p>'), 'a d');
- });
-
- test('mention', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/@user" class="u-url mention">@user</a> d</p>'), 'a @user@example.com d');
- });
-
- test('hashtag', () => {
- assert.deepStrictEqual(fromHtml('<p>a <a href="https://example.com/tags/a">#a</a> d</p>', ['#a']), 'a #a d');
- });
-});
diff --git a/packages/backend/test/tests/reaction-lib.ts b/packages/backend/test/tests/reaction-lib.ts
deleted file mode 100644
index 2e767f7697..0000000000
--- a/packages/backend/test/tests/reaction-lib.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-import * as assert from 'assert';
-
-import { toDbReaction } from '../src/misc/reaction-lib.js';
-
-describe('toDbReaction', async () => {
- test('æ—¢å­˜ã®æ–‡å­—列リアクションã¯ãã®ã¾ã¾', async () => {
- assert.strictEqual(await toDbReaction('like'), 'like');
- });
-
- test('Unicodeプリンã¯å¯¿å¸åŒ–ä¸èƒ½ã¨ã™ã‚‹ãŸã‚文字列化ã—ãªã„', async () => {
- assert.strictEqual(await toDbReaction('ðŸ®'), 'ðŸ®');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ like', async () => {
- assert.strictEqual(await toDbReaction('ðŸ‘'), 'like');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ love', async () => {
- assert.strictEqual(await toDbReaction('â¤ï¸'), 'love');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ love 異体字セレクタãªã—', async () => {
- assert.strictEqual(await toDbReaction('â¤'), 'love');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ laugh', async () => {
- assert.strictEqual(await toDbReaction('😆'), 'laugh');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ hmm', async () => {
- assert.strictEqual(await toDbReaction('🤔'), 'hmm');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ surprise', async () => {
- assert.strictEqual(await toDbReaction('😮'), 'surprise');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ congrats', async () => {
- assert.strictEqual(await toDbReaction('🎉'), 'congrats');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ angry', async () => {
- assert.strictEqual(await toDbReaction('💢'), 'angry');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ confused', async () => {
- assert.strictEqual(await toDbReaction('😥'), 'confused');
- });
-
- test('ãƒ—ãƒªãƒ³ä»¥å¤–ã®æ—¢å­˜ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯æ–‡å­—列化ã™ã‚‹ rip', async () => {
- assert.strictEqual(await toDbReaction('😇'), 'rip');
- });
-
- test('ãれ以外ã¯Unicodeã®ã¾ã¾', async () => {
- assert.strictEqual(await toDbReaction('ðŸ…'), 'ðŸ…');
- });
-
- test('異体字セレクタ除去', async () => {
- assert.strictEqual(await toDbReaction('㊗ï¸'), '㊗');
- });
-
- test('異体字セレクタ除去 å¿…è¦ãªã—', async () => {
- assert.strictEqual(await toDbReaction('㊗'), '㊗');
- });
-
- test('fallback - undefined', async () => {
- assert.strictEqual(await toDbReaction(undefined), 'like');
- });
-
- test('fallback - null', async () => {
- assert.strictEqual(await toDbReaction(null), 'like');
- });
-
- test('fallback - empty', async () => {
- assert.strictEqual(await toDbReaction(''), 'like');
- });
-
- test('fallback - unknown', async () => {
- assert.strictEqual(await toDbReaction('unknown'), 'like');
- });
-});
-*/
diff --git a/packages/backend/test/tsconfig.json b/packages/backend/test/tsconfig.json
index 5d91d0923a..da82ddc4a1 100644
--- a/packages/backend/test/tsconfig.json
+++ b/packages/backend/test/tsconfig.json
@@ -37,6 +37,7 @@
},
"compileOnSave": false,
"include": [
- "./**/*.ts"
+ "./**/*.ts",
+ "../src/@types/**/*.ts",
]
}
diff --git a/packages/backend/test/unit/MfmService.ts b/packages/backend/test/unit/MfmService.ts
new file mode 100644
index 0000000000..5496738778
--- /dev/null
+++ b/packages/backend/test/unit/MfmService.ts
@@ -0,0 +1,102 @@
+import * as assert from 'assert';
+import * as mfm from 'mfm-js';
+import { Test } from '@nestjs/testing';
+
+import { CoreModule } from '@/core/CoreModule.js';
+import { MfmService } from '@/core/MfmService.js';
+import { GlobalModule } from '@/GlobalModule.js';
+
+describe('MfmService', () => {
+ let mfmService: MfmService;
+
+ beforeAll(async () => {
+ const app = await Test.createTestingModule({
+ imports: [GlobalModule, CoreModule],
+ }).compile();
+ mfmService = app.get<MfmService>(MfmService);
+ });
+
+ describe('toHtml', () => {
+ test('br', () => {
+ const input = 'foo\nbar\nbaz';
+ const output = '<p><span>foo<br>bar<br>baz</span></p>';
+ assert.equal(mfmService.toHtml(mfm.parse(input)), output);
+ });
+
+ test('br alt', () => {
+ const input = 'foo\r\nbar\rbaz';
+ const output = '<p><span>foo<br>bar<br>baz</span></p>';
+ assert.equal(mfmService.toHtml(mfm.parse(input)), output);
+ });
+ });
+
+ describe('fromHtml', () => {
+ test('p', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a</p><p>b</p>'), 'a\n\nb');
+ });
+
+ test('block element', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<div>a</div><div>b</div>'), 'a\nb');
+ });
+
+ test('inline element', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<ul><li>a</li><li>b</li></ul>'), 'a\nb');
+ });
+
+ test('block code', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<pre><code>a\nb</code></pre>'), '```\na\nb\n```');
+ });
+
+ test('inline code', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<code>a</code>'), '`a`');
+ });
+
+ test('quote', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<blockquote>a\nb</blockquote>'), '> a\n> b');
+ });
+
+ test('br', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>abc<br><br/>d</p>'), 'abc\n\nd');
+ });
+
+ test('link with different text', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/b">c</a> d</p>'), 'a [c](https://example.com/b) d');
+ });
+
+ test('link with different text, but not encoded', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/ä">c</a> d</p>'), 'a [c](<https://example.com/ä>) d');
+ });
+
+ test('link with same text', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/b">https://example.com/b</a> d</p>'), 'a https://example.com/b d');
+ });
+
+ test('link with same text, but not encoded', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/ä">https://example.com/ä</a> d</p>'), 'a <https://example.com/ä> d');
+ });
+
+ test('link with no url', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="b">c</a> d</p>'), 'a [c](b) d');
+ });
+
+ test('link without href', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a>c</a> d</p>'), 'a c d');
+ });
+
+ test('link without text', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/b"></a> d</p>'), 'a https://example.com/b d');
+ });
+
+ test('link without both', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a></a> d</p>'), 'a d');
+ });
+
+ test('mention', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/@user" class="u-url mention">@user</a> d</p>'), 'a @user@example.com d');
+ });
+
+ test('hashtag', () => {
+ assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/tags/a">#a</a> d</p>', ['#a']), 'a #a d');
+ });
+ });
+});
diff --git a/packages/backend/test/unit/ReactionService.ts b/packages/backend/test/unit/ReactionService.ts
new file mode 100644
index 0000000000..6a20a1e08e
--- /dev/null
+++ b/packages/backend/test/unit/ReactionService.ts
@@ -0,0 +1,92 @@
+import * as assert from 'assert';
+import { Test } from '@nestjs/testing';
+
+import { CoreModule } from '@/core/CoreModule.js';
+import { ReactionService } from '@/core/ReactionService.js';
+import { GlobalModule } from '@/GlobalModule.js';
+
+describe('ReactionService', () => {
+ let reactionService: ReactionService;
+
+ beforeAll(async () => {
+ const app = await Test.createTestingModule({
+ imports: [GlobalModule, CoreModule],
+ }).compile();
+ reactionService = app.get<ReactionService>(ReactionService);
+ });
+
+ describe('toDbReaction', () => {
+ test('絵文字リアクションã¯ãã®ã¾ã¾', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('ðŸ‘'), 'ðŸ‘');
+ assert.strictEqual(await reactionService.toDbReaction('ðŸ…'), 'ðŸ…');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ pudding', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('pudding'), 'ðŸ®');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ like', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('like'), 'ðŸ‘');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ love', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('love'), 'â¤');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ laugh', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('laugh'), '😆');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ hmm', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('hmm'), '🤔');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ surprise', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('surprise'), '😮');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ congrats', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('congrats'), '🎉');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ angry', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('angry'), '💢');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ confused', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('confused'), '😥');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ rip', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('rip'), '😇');
+ });
+
+ test('既存ã®ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯çµµæ–‡å­—化ã™ã‚‹ star', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('star'), 'â­');
+ });
+
+ test('異体字セレクタ除去', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('㊗ï¸'), '㊗');
+ });
+
+ test('異体字セレクタ除去 å¿…è¦ãªã—', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('㊗'), '㊗');
+ });
+
+ test('fallback - undefined', async () => {
+ assert.strictEqual(await reactionService.toDbReaction(undefined), 'ðŸ‘');
+ });
+
+ test('fallback - null', async () => {
+ assert.strictEqual(await reactionService.toDbReaction(null), 'ðŸ‘');
+ });
+
+ test('fallback - empty', async () => {
+ assert.strictEqual(await reactionService.toDbReaction(''), 'ðŸ‘');
+ });
+
+ test('fallback - unknown', async () => {
+ assert.strictEqual(await reactionService.toDbReaction('unknown'), 'ðŸ‘');
+ });
+ });
+});
diff --git a/packages/backend/test/tests/ap-request.ts b/packages/backend/test/unit/ap-request.ts
index 8c586861ad..98f352e1c6 100644
--- a/packages/backend/test/tests/ap-request.ts
+++ b/packages/backend/test/unit/ap-request.ts
@@ -1,7 +1,8 @@
import * as assert from 'assert';
import httpSignature from '@peertube/http-signature';
-import { genRsaKeyPair } from '../../src/misc/gen-key-pair.js';
-import { createSignedPost, createSignedGet } from '../../src/activitypub/ap-request.js';
+
+import { genRsaKeyPair } from '@/misc/gen-key-pair.js';
+import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js';
export const buildParsedSignature = (signingString: string, signature: string, algorithm: string) => {
return {
@@ -9,7 +10,7 @@ export const buildParsedSignature = (signingString: string, signature: string, a
params: {
keyId: 'KeyID', // dummy, not used for verify
algorithm: algorithm,
- headers: [ '(request-target)', 'date', 'host', 'digest' ], // dummy, not used for verify
+ headers: ['(request-target)', 'date', 'host', 'digest'], // dummy, not used for verify
signature: signature,
},
signingString: signingString,
@@ -29,7 +30,7 @@ describe('ap-request', () => {
'User-Agent': 'UA',
};
- const req = createSignedPost({ key, url, body, additionalHeaders: headers });
+ const req = ApRequestCreator.createSignedPost({ key, url, body, additionalHeaders: headers });
const parsed = buildParsedSignature(req.signingString, req.signature, 'rsa-sha256');
@@ -45,7 +46,7 @@ describe('ap-request', () => {
'User-Agent': 'UA',
};
- const req = createSignedGet({ key, url, additionalHeaders: headers });
+ const req = ApRequestCreator.createSignedGet({ key, url, additionalHeaders: headers });
const parsed = buildParsedSignature(req.signingString, req.signature, 'rsa-sha256');
diff --git a/packages/backend/test/unit/chart.ts b/packages/backend/test/unit/chart.ts
index 1e9a51bc88..5ac4cc18a2 100644
--- a/packages/backend/test/unit/chart.ts
+++ b/packages/backend/test/unit/chart.ts
@@ -19,7 +19,7 @@ import Logger from '@/logger.js';
describe('Chart', () => {
const config = loadConfig();
const appLockService = {
- getChartInsertLock: jest.fn().mockImplementation(() => Promise.resolve(() => {})),
+ getChartInsertLock: () => () => Promise.resolve(() => {}),
} as unknown as jest.Mocked<AppLockService>;
let db: DataSource | undefined;
diff --git a/packages/backend/test/tests/extract-mentions.ts b/packages/backend/test/unit/extract-mentions.ts
index e81d04c2db..66d32be1c5 100644
--- a/packages/backend/test/tests/extract-mentions.ts
+++ b/packages/backend/test/unit/extract-mentions.ts
@@ -1,11 +1,11 @@
import * as assert from 'assert';
import { parse } from 'mfm-js';
-import { extractMentions } from '../../src/misc/extract-mentions.js';
+import { extractMentions } from '@/misc/extract-mentions.js';
describe('Extract mentions', () => {
test('simple', () => {
- const ast = parse('@foo @bar @baz')!;
+ const ast = parse('@foo @bar @baz');
const mentions = extractMentions(ast);
assert.deepStrictEqual(mentions, [{
username: 'foo',
@@ -23,7 +23,7 @@ describe('Extract mentions', () => {
});
test('nested', () => {
- const ast = parse('@foo **@bar** @baz')!;
+ const ast = parse('@foo **@bar** @baz');
const mentions = extractMentions(ast);
assert.deepStrictEqual(mentions, [{
username: 'foo',
diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json
index 544b529e94..6f335a2442 100644
--- a/packages/backend/tsconfig.json
+++ b/packages/backend/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"allowJs": true,
- "noEmitOnError": false,
+ "noEmitOnError": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedParameters": false,
diff --git a/packages/frontend/.eslintrc.js b/packages/frontend/.eslintrc.js
index 6c3bfb5a6e..e8e0e57d2a 100644
--- a/packages/frontend/.eslintrc.js
+++ b/packages/frontend/.eslintrc.js
@@ -55,6 +55,7 @@ module.exports = {
'vue/multi-word-component-names': 'warn',
'vue/require-v-for-key': 'warn',
'vue/no-unused-components': 'warn',
+ 'vue/no-unused-vars': 'warn',
'vue/valid-v-for': 'warn',
'vue/return-in-computed-property': 'warn',
'vue/no-setup-props-destructure': 'warn',
diff --git a/packages/frontend/assets/about-icon.png b/packages/frontend/assets/about-icon.png
index afc1f0c728..15fd1e3731 100644
--- a/packages/frontend/assets/about-icon.png
+++ b/packages/frontend/assets/about-icon.png
Binary files differ
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index 61c0135ba3..24f8d9b6a6 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -19,11 +19,11 @@
"@vue/compiler-sfc": "3.2.47",
"autobind-decorator": "2.4.0",
"autosize": "5.0.2",
- "blurhash": "2.0.4",
+ "blurhash": "2.0.5",
"broadcast-channel": "4.20.2",
- "browser-image-resizer": "git+https://github.com/misskey-dev/browser-image-resizer#v2.2.1-misskey.3",
+ "browser-image-resizer": "github:misskey-dev/browser-image-resizer#v2.2.1-misskey.3",
"canvas-confetti": "1.6.0",
- "chart.js": "4.2.0",
+ "chart.js": "4.2.1",
"chartjs-adapter-date-fns": "3.0.0",
"chartjs-chart-matrix": "2.0.1",
"chartjs-plugin-gradient": "0.6.1",
@@ -38,7 +38,7 @@
"insert-text-at-cursor": "0.3.0",
"is-file-animated": "1.0.2",
"json5": "2.2.3",
- "matter-js": "0.18.0",
+ "matter-js": "0.19.0",
"mfm-js": "0.23.3",
"misskey-js": "0.0.15",
"photoswipe": "5.3.5",
@@ -46,13 +46,12 @@
"punycode": "2.3.0",
"querystring": "0.2.1",
"rndstr": "1.0.0",
- "rollup": "3.14.0",
+ "rollup": "3.17.2",
"s-age": "1.1.2",
- "sanitize-html": "2.9.0",
- "sass": "1.58.0",
+ "sanitize-html": "2.10.0",
+ "sass": "1.58.3",
"seedrandom": "3.0.5",
"strict-event-emitter-types": "2.0.0",
- "stringz": "2.1.0",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.149.0",
@@ -64,9 +63,9 @@
"typescript": "4.9.5",
"uuid": "9.0.0",
"vanilla-tilt": "1.8.0",
- "vue-plyr": "7.0.0",
- "vite": "4.1.1",
+ "vite": "4.1.2",
"vue": "3.2.47",
+ "vue-plyr": "7.0.0",
"vue-prism-editor": "2.0.0-alpha.2",
"vuedraggable": "next"
},
@@ -76,7 +75,7 @@
"@types/gulp": "4.0.10",
"@types/gulp-rename": "2.0.1",
"@types/matter-js": "0.18.2",
- "@types/node": "18.13.0",
+ "@types/node": "18.14.0",
"@types/punycode": "2.1.0",
"@types/sanitize-html": "2.8.0",
"@types/seedrandom": "3.0.4",
@@ -85,16 +84,16 @@
"@types/uuid": "9.0.0",
"@types/websocket": "1.0.5",
"@types/ws": "8.5.4",
- "@typescript-eslint/eslint-plugin": "5.51.0",
- "@typescript-eslint/parser": "5.51.0",
+ "@typescript-eslint/eslint-plugin": "5.52.0",
+ "@typescript-eslint/parser": "5.52.0",
"@vue/runtime-core": "3.2.47",
"cross-env": "7.0.3",
- "cypress": "12.5.1",
- "eslint": "8.33.0",
+ "cypress": "12.6.0",
+ "eslint": "8.34.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-vue": "9.9.0",
- "start-server-and-test": "1.15.3",
+ "start-server-and-test": "1.15.4",
"vue-eslint-parser": "9.1.0",
- "vue-tsc": "1.0.24"
+ "vue-tsc": "1.1.4"
}
-}
+} \ No newline at end of file
diff --git a/packages/frontend/src/components/MkAbuseReportWindow.vue b/packages/frontend/src/components/MkAbuseReportWindow.vue
index a76a1e0f54..9f2bf99338 100644
--- a/packages/frontend/src/components/MkAbuseReportWindow.vue
+++ b/packages/frontend/src/components/MkAbuseReportWindow.vue
@@ -43,7 +43,7 @@ const emit = defineEmits<{
}>();
const uiWindow = shallowRef<InstanceType<typeof MkWindow>>();
-const comment = ref(props.initialComment || '');
+const comment = ref(props.initialComment ?? '');
function send() {
os.apiWithDialog('users/report-abuse', {
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index 7e5432434f..663c57623d 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -209,7 +209,7 @@ function exec() {
}
} else if (props.type === 'hashtag') {
if (!props.q || props.q === '') {
- hashtags.value = JSON.parse(miLocalStorage.getItem('hashtags') || '[]');
+ hashtags.value = JSON.parse(miLocalStorage.getItem('hashtags') ?? '[]');
fetching.value = false;
} else {
const cacheKey = `autocomplete:hashtag:${props.q}`;
diff --git a/packages/frontend/src/components/MkCaptcha.vue b/packages/frontend/src/components/MkCaptcha.vue
index 8db2e54e88..c72cc2ab1b 100644
--- a/packages/frontend/src/components/MkCaptcha.vue
+++ b/packages/frontend/src/components/MkCaptcha.vue
@@ -69,7 +69,7 @@ const captcha = computed<Captcha>(() => window[variable.value] || {} as unknown
if (loaded) {
available.value = true;
} else {
- (document.getElementById(scriptId.value) || document.head.appendChild(Object.assign(document.createElement('script'), {
+ (document.getElementById(scriptId.value) ?? document.head.appendChild(Object.assign(document.createElement('script'), {
async: true,
id: scriptId.value,
src: src.value,
diff --git a/packages/frontend/src/components/MkClickerGame.vue b/packages/frontend/src/components/MkClickerGame.vue
index 2283e652db..da6439fd2c 100644
--- a/packages/frontend/src/components/MkClickerGame.vue
+++ b/packages/frontend/src/components/MkClickerGame.vue
@@ -22,9 +22,6 @@ import * as game from '@/scripts/clicker-game';
import number from '@/filters/number';
import { claimAchievement } from '@/scripts/achievements';
-defineProps<{
-}>();
-
const saveData = game.saveData;
const cookies = computed(() => saveData.value?.cookies);
let cps = $ref(0);
diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue
index f0ea984c4e..21cccaabde 100644
--- a/packages/frontend/src/components/MkContextMenu.vue
+++ b/packages/frontend/src/components/MkContextMenu.vue
@@ -32,6 +32,8 @@ let rootEl = $shallowRef<HTMLDivElement>();
let zIndex = $ref<number>(os.claimZIndex('high'));
+const SCROLLBAR_THICKNESS = 16;
+
onMounted(() => {
let left = props.ev.pageX + 1; // é–“é•ã£ã¦å³ãƒ€ãƒ–ルクリックã—ãŸå ´åˆã«æ„図ã›ãšã‚¢ã‚¤ãƒ†ãƒ ãŒã‚¯ãƒªãƒƒã‚¯ã•れるã®ã‚’防ããŸã‚ + 1
let top = props.ev.pageY + 1; // é–“é•ã£ã¦å³ãƒ€ãƒ–ルクリックã—ãŸå ´åˆã«æ„図ã›ãšã‚¢ã‚¤ãƒ†ãƒ ãŒã‚¯ãƒªãƒƒã‚¯ã•れるã®ã‚’防ããŸã‚ + 1
@@ -39,12 +41,12 @@ onMounted(() => {
const width = rootEl.offsetWidth;
const height = rootEl.offsetHeight;
- if (left + width - window.pageXOffset > window.innerWidth) {
- left = window.innerWidth - width + window.pageXOffset;
+ if (left + width - window.pageXOffset >= (window.innerWidth - SCROLLBAR_THICKNESS)) {
+ left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset;
}
- if (top + height - window.pageYOffset > window.innerHeight) {
- top = window.innerHeight - height + window.pageYOffset;
+ if (top + height - window.pageYOffset >= (window.innerHeight - SCROLLBAR_THICKNESS)) {
+ top = (window.innerHeight - SCROLLBAR_THICKNESS) - height + window.pageYOffset;
}
if (top < 0) {
diff --git a/packages/frontend/src/components/MkCwButton.vue b/packages/frontend/src/components/MkCwButton.vue
index e0885f5550..7d5579040a 100644
--- a/packages/frontend/src/components/MkCwButton.vue
+++ b/packages/frontend/src/components/MkCwButton.vue
@@ -7,7 +7,6 @@
<script lang="ts" setup>
import { computed } from 'vue';
-import { length } from 'stringz';
import * as misskey from 'misskey-js';
import { concat } from '@/scripts/array';
import { i18n } from '@/i18n';
@@ -23,7 +22,7 @@ const emit = defineEmits<{
const label = computed(() => {
return concat([
- props.note.text ? [i18n.t('_cw.chars', { count: length(props.note.text) })] : [],
+ props.note.text ? [i18n.t('_cw.chars', { count: props.note.text.length })] : [],
props.note.files && props.note.files.length !== 0 ? [i18n.t('_cw.files', { count: props.note.files.length })] : [],
props.note.poll != null ? [i18n.ts.poll] : [],
] as string[][]).join(' / ');
diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue
index 9690353432..863ea702cd 100644
--- a/packages/frontend/src/components/MkDialog.vue
+++ b/packages/frontend/src/components/MkDialog.vue
@@ -14,8 +14,12 @@
</div>
<header v-if="title" :class="$style.title"><Mfm :text="title"/></header>
<div v-if="text" :class="$style.text"><Mfm :text="text"/></div>
- <MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" @keydown="onInputKeydown">
+ <MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
<template v-if="input.type === 'password'" #prefix><i class="ti ti-lock"></i></template>
+ <template #caption>
+ <span v-if="okButtonDisabled && disabledReason === 'charactersExceeded'" v-text="i18n.t('_dialog.charactersExceeded', { current: (inputValue as string).length, max: input.maxLength ?? 'NaN' })" />
+ <span v-else-if="okButtonDisabled && disabledReason === 'charactersBelow'" v-text="i18n.t('_dialog.charactersBelow', { current: (inputValue as string).length, min: input.minLength ?? 'NaN' })" />
+ </template>
</MkInput>
<MkSelect v-if="select" v-model="selectedValue" autofocus>
<template v-if="select.items">
@@ -28,7 +32,7 @@
</template>
</MkSelect>
<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons">
- <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="showOkButton" inline primary :autofocus="!input && !select" :disabled="okButtonDisabled" @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">
@@ -47,9 +51,12 @@ import MkSelect from '@/components/MkSelect.vue';
import { i18n } from '@/i18n';
type Input = {
- type: HTMLInputElement['type'];
+ type: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time' | 'search' | 'datetime-local';
placeholder?: string | null;
- default: any | null;
+ autocomplete?: string;
+ default: string | number | null;
+ minLength?: number;
+ maxLength?: number;
};
type Select = {
@@ -98,8 +105,28 @@ const emit = defineEmits<{
const modal = shallowRef<InstanceType<typeof MkModal>>();
-const inputValue = ref(props.input?.default || null);
-const selectedValue = ref(props.select?.default || null);
+const inputValue = ref<string | number | null>(props.input?.default ?? null);
+const selectedValue = ref(props.select?.default ?? null);
+
+let disabledReason = $ref<null | 'charactersExceeded' | 'charactersBelow'>(null);
+const okButtonDisabled = $computed<boolean>(() => {
+ if (props.input) {
+ if (props.input.minLength) {
+ if ((inputValue.value || inputValue.value === '') && (inputValue.value as string).length < props.input.minLength) {
+ disabledReason = 'charactersBelow';
+ return true;
+ }
+ }
+ if (props.input.maxLength) {
+ if (inputValue.value && (inputValue.value as string).length > props.input.maxLength) {
+ disabledReason = 'charactersExceeded';
+ return true;
+ }
+ }
+ }
+
+ return false;
+});
function done(canceled: boolean, result?) {
emit('done', { canceled, result });
diff --git a/packages/frontend/src/components/MkFolder.vue b/packages/frontend/src/components/MkFolder.vue
index a1d7210d7e..b97e36cd5f 100644
--- a/packages/frontend/src/components/MkFolder.vue
+++ b/packages/frontend/src/components/MkFolder.vue
@@ -1,13 +1,20 @@
<template>
<div ref="rootEl" :class="[$style.root, { [$style.opened]: opened }]">
<div :class="$style.header" class="_button" @click="toggle">
- <span :class="$style.headerIcon"><slot name="icon"></slot></span>
- <span :class="$style.headerText"><slot name="label"></slot></span>
- <span :class="$style.headerRight">
+ <div :class="$style.headerIcon"><slot name="icon"></slot></div>
+ <div :class="$style.headerText">
+ <div :class="$style.headerTextMain">
+ <slot name="label"></slot>
+ </div>
+ <div :class="$style.headerTextSub">
+ <slot name="caption"></slot>
+ </div>
+ </div>
+ <div :class="$style.headerRight">
<span :class="$style.headerRightText"><slot name="suffix"></slot></span>
<i v-if="opened" class="ti ti-chevron-up icon"></i>
<i v-else class="ti ti-chevron-down icon"></i>
- </span>
+ </div>
</div>
<div v-if="openedAtLeastOnce" :class="[$style.body, { [$style.bgSame]: bgSame }]" :style="{ maxHeight: maxHeight ? `${maxHeight}px` : null }">
<Transition
@@ -139,6 +146,17 @@ onMounted(() => {
}
}
+.headerUpper {
+ display: flex;
+ align-items: center;
+}
+
+.headerLower {
+ color: var(--fgTransparentWeak);
+ font-size: .85em;
+ padding-left: 4px;
+}
+
.headerIcon {
margin-right: 0.75em;
flex-shrink: 0;
@@ -161,6 +179,15 @@ onMounted(() => {
padding-right: 12px;
}
+.headerTextMain {
+
+}
+
+.headerTextSub {
+ color: var(--fgTransparentWeak);
+ font-size: .85em;
+}
+
.headerRight {
margin-left: auto;
opacity: 0.7;
diff --git a/packages/frontend/src/components/MkInput.vue b/packages/frontend/src/components/MkInput.vue
index da6177c2f9..3e3d7354c1 100644
--- a/packages/frontend/src/components/MkInput.vue
+++ b/packages/frontend/src/components/MkInput.vue
@@ -23,7 +23,7 @@
@input="onInput"
>
<datalist v-if="datalist" :id="id">
- <option v-for="data in datalist" :value="data"/>
+ <option v-for="data in datalist" :key="data" :value="data"/>
</datalist>
<div ref="suffixEl" class="suffix"><slot name="suffix"></slot></div>
</div>
@@ -41,7 +41,7 @@ import { useInterval } from '@/scripts/use-interval';
import { i18n } from '@/i18n';
const props = defineProps<{
- modelValue: string | number;
+ modelValue: string | number | null;
type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time' | 'search' | 'datetime-local';
required?: boolean;
readonly?: boolean;
@@ -49,7 +49,7 @@ const props = defineProps<{
pattern?: string;
placeholder?: string;
autofocus?: boolean;
- autocomplete?: boolean;
+ autocomplete?: string;
spellcheck?: boolean;
step?: any;
datalist?: string[];
diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue
index e957d8f56c..a12bb78e35 100644
--- a/packages/frontend/src/components/MkMediaList.vue
+++ b/packages/frontend/src/components/MkMediaList.vue
@@ -45,8 +45,8 @@ onMounted(() => {
src: media.url,
w: media.properties.width,
h: media.properties.height,
- alt: media.comment || media.name,
- comment: media.comment || media.name,
+ alt: media.comment ?? media.name,
+ comment: media.comment ?? media.name,
};
if (media.properties.orientation != null && media.properties.orientation >= 5) {
[item.w, item.h] = [item.h, item.w];
@@ -90,8 +90,8 @@ onMounted(() => {
[itemData.w, itemData.h] = [itemData.h, itemData.w];
}
itemData.msrc = file.thumbnailUrl;
- itemData.alt = file.comment || file.name;
- itemData.comment = file.comment || file.name;
+ itemData.alt = file.comment ?? file.name;
+ itemData.comment = file.comment ?? file.name;
itemData.thumbCropped = true;
});
diff --git a/packages/frontend/src/components/MkMenu.child.vue b/packages/frontend/src/components/MkMenu.child.vue
index cdd9d96b96..e0935efbe7 100644
--- a/packages/frontend/src/components/MkMenu.child.vue
+++ b/packages/frontend/src/components/MkMenu.child.vue
@@ -1,11 +1,11 @@
<template>
-<div ref="el" class="sfhdhdhr">
- <MkMenu ref="menu" :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
+<div ref="el" :class="$style.root">
+ <MkMenu :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
</div>
</template>
<script lang="ts" setup>
-import { nextTick, onMounted, shallowRef, watch } from 'vue';
+import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
import MkMenu from './MkMenu.vue';
import { MenuItem } from '@/types/menu';
@@ -25,11 +25,21 @@ const emit = defineEmits<{
const el = shallowRef<HTMLElement>();
const align = 'left';
+const SCROLLBAR_THICKNESS = 16;
+
function setPosition() {
const rootRect = props.rootElement.getBoundingClientRect();
- const rect = props.targetElement.getBoundingClientRect();
- const left = props.targetElement.offsetWidth;
- const top = (rect.top - rootRect.top) - 8;
+ const parentRect = props.targetElement.getBoundingClientRect();
+ const myRect = el.value.getBoundingClientRect();
+
+ let left = props.targetElement.offsetWidth;
+ let top = (parentRect.top - rootRect.top) - 8;
+ if (rootRect.left + left + myRect.width >= (window.innerWidth - SCROLLBAR_THICKNESS)) {
+ left = -myRect.width;
+ }
+ if (rootRect.top + top + myRect.height >= (window.innerHeight - SCROLLBAR_THICKNESS)) {
+ top = top - ((rootRect.top + top + myRect.height) - (window.innerHeight - SCROLLBAR_THICKNESS));
+ }
el.value.style.left = left + 'px';
el.value.style.top = top + 'px';
}
@@ -46,13 +56,22 @@ watch(() => props.targetElement, () => {
setPosition();
});
+const ro = new ResizeObserver((entries, observer) => {
+ setPosition();
+});
+
onMounted(() => {
+ ro.observe(el.value);
setPosition();
nextTick(() => {
setPosition();
});
});
+onUnmounted(() => {
+ ro.disconnect();
+});
+
defineExpose({
checkHit: (ev: MouseEvent) => {
return (ev.target === el.value || el.value.contains(ev.target));
@@ -60,8 +79,8 @@ defineExpose({
});
</script>
-<style lang="scss" scoped>
-.sfhdhdhr {
+<style lang="scss" module>
+.root {
position: absolute;
}
</style>
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index 52aba58455..09d530c4ea 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -56,7 +56,7 @@
</template>
<script lang="ts" setup>
-import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, watch } from 'vue';
+import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { focusPrev, focusNext } from '@/scripts/focus';
import MkSwitch from '@/components/MkSwitch.vue';
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from '@/types/menu';
@@ -111,11 +111,11 @@ watch(() => props.items, () => {
immediate: true,
});
-let childMenu = $ref<MenuItem[] | null>();
+let childMenu = ref<MenuItem[] | null>();
let childTarget = $shallowRef<HTMLElement | null>();
function closeChild() {
- childMenu = null;
+ childMenu.value = null;
childShowingItem = null;
}
@@ -140,13 +140,31 @@ function onItemMouseLeave(item) {
if (childCloseTimer) window.clearTimeout(childCloseTimer);
}
+let childrenCache = new WeakMap();
async function showChildren(item: MenuItem, ev: MouseEvent) {
+ const children = ref([]);
+ if (childrenCache.has(item)) {
+ children.value = childrenCache.get(item);
+ } else {
+ if (typeof item.children === 'function') {
+ children.value = [{
+ type: 'pending',
+ }];
+ item.children().then(x => {
+ children.value = x;
+ childrenCache.set(item, x);
+ });
+ } else {
+ children.value = item.children;
+ }
+ }
+
if (props.asDrawer) {
- os.popupMenu(item.children, ev.currentTarget ?? ev.target);
+ os.popupMenu(children, ev.currentTarget ?? ev.target);
close();
} else {
childTarget = ev.currentTarget ?? ev.target;
- childMenu = item.children;
+ childMenu = children;
childShowingItem = item;
}
}
diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue
index eba0f5847d..dbad02fb7e 100644
--- a/packages/frontend/src/components/MkModal.vue
+++ b/packages/frontend/src/components/MkModal.vue
@@ -125,7 +125,7 @@ function onBgClick() {
}
if (type === 'drawer') {
- maxHeight = window.innerHeight / 1.5;
+ maxHeight = (window.innerHeight - SCROLLBAR_THICKNESS) / 1.5;
}
const keymap = {
@@ -133,6 +133,7 @@ const keymap = {
};
const MARGIN = 16;
+const SCROLLBAR_THICKNESS = 16;
const align = () => {
if (props.src == null) return;
@@ -170,15 +171,15 @@ const align = () => {
if (fixed) {
// ç”»é¢ã‹ã‚‰æ¨ªã«ã¯ã¿å‡ºã‚‹å ´åˆ
- if (left + width > window.innerWidth) {
- left = window.innerWidth - width;
+ if (left + width > (window.innerWidth - SCROLLBAR_THICKNESS)) {
+ left = (window.innerWidth - SCROLLBAR_THICKNESS) - width;
}
- const underSpace = (window.innerHeight - MARGIN) - top;
+ const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top;
const upperSpace = (srcRect.top - MARGIN);
// ç”»é¢ã‹ã‚‰ç¸¦ã«ã¯ã¿å‡ºã‚‹å ´åˆ
- if (top + height > (window.innerHeight - MARGIN)) {
+ if (top + height > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight = underSpace;
@@ -187,22 +188,22 @@ const align = () => {
top = (upperSpace + MARGIN) - height;
}
} else {
- top = (window.innerHeight - MARGIN) - height;
+ top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height;
}
} else {
maxHeight = underSpace;
}
} else {
// ç”»é¢ã‹ã‚‰æ¨ªã«ã¯ã¿å‡ºã‚‹å ´åˆ
- if (left + width - window.pageXOffset > window.innerWidth) {
- left = window.innerWidth - width + window.pageXOffset - 1;
+ if (left + width - window.pageXOffset > (window.innerWidth - SCROLLBAR_THICKNESS)) {
+ left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset - 1;
}
- const underSpace = (window.innerHeight - MARGIN) - (top - window.pageYOffset);
+ const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.pageYOffset);
const upperSpace = (srcRect.top - MARGIN);
// ç”»é¢ã‹ã‚‰ç¸¦ã«ã¯ã¿å‡ºã‚‹å ´åˆ
- if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) {
+ if (top + height - window.pageYOffset > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight = underSpace;
@@ -211,7 +212,7 @@ const align = () => {
top = window.pageYOffset + ((upperSpace + MARGIN) - height);
}
} else {
- top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1;
+ top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.pageYOffset - 1;
}
} else {
maxHeight = underSpace;
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index f4c044e0bd..1040dac12e 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -31,7 +31,7 @@
<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
</span>
- <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['localOnly']"><i class="ti ti-world-off"></i></span>
+ <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-world-off"></i></span>
</div>
</div>
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
@@ -155,7 +155,6 @@ import { deepClone } from '@/scripts/clone';
import { useTooltip } from '@/scripts/use-tooltip';
import { claimAchievement } from '@/scripts/achievements';
import { getNoteSummary } from '@/scripts/get-note-summary';
-import { shownNoteIds } from '@/os';
import { MenuItem } from '@/types/menu';
const props = defineProps<{
@@ -195,6 +194,8 @@ const isMyRenote = $i && ($i.id === note.userId);
const showContent = ref(false);
const urls = appearNote.text ? extractUrlFromMfm(mfm.parse(appearNote.text)) : null;
const isLong = (appearNote.cw == null && appearNote.text != null && (
+ (appearNote.text.includes('$[x3')) ||
+ (appearNote.text.includes('$[x4')) ||
(appearNote.text.split('\n').length > 9) ||
(appearNote.text.length > 500) ||
(appearNote.files.length >= 5) ||
@@ -207,9 +208,7 @@ const translation = ref<any>(null);
const translating = ref(false);
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.user.instance);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibility) || appearNote.userId === $i.id);
-let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId)) || shownNoteIds.has(appearNote.id)));
-
-shownNoteIds.add(appearNote.id);
+let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId)) || (appearNote.myReaction != null)));
const keymap = {
'r': () => reply(true),
@@ -256,7 +255,7 @@ function renote(viaKeyboard = false) {
text: i18n.ts.inChannelRenote,
icon: 'ti ti-repeat',
action: () => {
- os.api('notes/create', {
+ os.apiWithDialog('notes/create', {
renoteId: appearNote.id,
channelId: appearNote.channelId,
});
@@ -277,7 +276,7 @@ function renote(viaKeyboard = false) {
text: i18n.ts.renote,
icon: 'ti ti-repeat',
action: () => {
- os.api('notes/create', {
+ os.apiWithDialog('notes/create', {
renoteId: appearNote.id,
});
},
@@ -674,9 +673,17 @@ function showReactions(): void {
opacity: 0.7;
}
-@container (max-width: 500px) {
+@container (max-width: 580px) {
.root {
- font-size: 0.9em;
+ font-size: 0.95em;
+ }
+
+ .renote {
+ padding: 12px 26px 0 26px;
+ }
+
+ .article {
+ padding: 24px 26px 14px;
}
.avatar {
@@ -685,7 +692,21 @@ function showReactions(): void {
}
}
-@container (max-width: 450px) {
+@container (max-width: 500px) {
+ .root {
+ font-size: 0.9em;
+ }
+
+ .renote {
+ padding: 10px 22px 0 22px;
+ }
+
+ .article {
+ padding: 20px 22px 12px;
+ }
+}
+
+@container (max-width: 480px) {
.renote {
padding: 8px 16px 0 16px;
}
@@ -702,7 +723,9 @@ function showReactions(): void {
.article {
padding: 14px 16px 9px;
}
+}
+@container (max-width: 450px) {
.avatar {
margin: 0 10px 8px 0;
width: 46px;
@@ -711,7 +734,7 @@ function showReactions(): void {
}
}
-@container (max-width: 350px) {
+@container (max-width: 400px) {
.footerButton {
&:not(:last-child) {
margin-right: 18px;
@@ -719,6 +742,14 @@ function showReactions(): void {
}
}
+@container (max-width: 350px) {
+ .footerButton {
+ &:not(:last-child) {
+ margin-right: 12px;
+ }
+ }
+}
+
@container (max-width: 300px) {
.avatar {
width: 44px;
@@ -727,7 +758,7 @@ function showReactions(): void {
.footerButton {
&:not(:last-child) {
- margin-right: 12px;
+ margin-right: 8px;
}
}
}
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 82e0f3e689..2eebe999a5 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -30,7 +30,7 @@
<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
</span>
- <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['localOnly']"><i class="ti ti-world-off"></i></span>
+ <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-world-off"></i></span>
</div>
</div>
<article class="article" @contextmenu.stop="onContextmenu">
@@ -48,7 +48,7 @@
<i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
<i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
</span>
- <span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['localOnly']"><i class="ti ti-world-off"></i></span>
+ <span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-world-off"></i></span>
</div>
</div>
<div class="username"><MkAcct :user="appearNote.user"/></div>
@@ -250,7 +250,7 @@ function renote(viaKeyboard = false) {
text: i18n.ts.inChannelRenote,
icon: 'ti ti-repeat',
action: () => {
- os.api('notes/create', {
+ os.apiWithDialog('notes/create', {
renoteId: appearNote.id,
channelId: appearNote.channelId,
});
@@ -271,7 +271,7 @@ function renote(viaKeyboard = false) {
text: i18n.ts.renote,
icon: 'ti ti-repeat',
action: () => {
- os.api('notes/create', {
+ os.apiWithDialog('notes/create', {
renoteId: appearNote.id,
});
},
diff --git a/packages/frontend/src/components/MkNoteHeader.vue b/packages/frontend/src/components/MkNoteHeader.vue
index 32998e1a70..ffd9a20ef7 100644
--- a/packages/frontend/src/components/MkNoteHeader.vue
+++ b/packages/frontend/src/components/MkNoteHeader.vue
@@ -17,7 +17,7 @@
<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
</span>
- <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['localOnly']"><i class="ti ti-world-off"></i></span>
+ <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-world-off"></i></span>
</div>
</header>
</template>
diff --git a/packages/frontend/src/components/MkNotificationSettingWindow.vue b/packages/frontend/src/components/MkNotificationSettingWindow.vue
index e303403872..f6d0e5681d 100644
--- a/packages/frontend/src/components/MkNotificationSettingWindow.vue
+++ b/packages/frontend/src/components/MkNotificationSettingWindow.vue
@@ -6,7 +6,7 @@
:with-ok-button="true"
:ok-button-disabled="false"
@ok="ok()"
- @close="dialog.close()"
+ @close="dialog?.close()"
@closed="emit('closed')"
>
<template #header>{{ i18n.ts.notificationSetting }}</template>
@@ -25,7 +25,7 @@
<MkButton inline @click="disableAll">{{ i18n.ts.disableAll }}</MkButton>
<MkButton inline @click="enableAll">{{ i18n.ts.enableAll }}</MkButton>
</div>
- <MkSwitch v-for="ntype in notificationTypes" :key="ntype" v-model="typesMap[ntype]">{{ i18n.t(`_notification._types.${ntype}`) }}</MkSwitch>
+ <MkSwitch v-for="ntype in notificationTypes" :key="ntype" v-model="typesMap[ntype].value">{{ i18n.t(`_notification._types.${ntype}`) }}</MkSwitch>
</template>
</div>
</MkSpacer>
@@ -33,14 +33,16 @@
</template>
<script lang="ts" setup>
-import { } from 'vue';
-import { notificationTypes } from 'misskey-js';
+import { ref, Ref } from 'vue';
import MkSwitch from './MkSwitch.vue';
import MkInfo from './MkInfo.vue';
import MkButton from './MkButton.vue';
import MkModalWindow from '@/components/MkModalWindow.vue';
+import { notificationTypes } from '@/const';
import { i18n } from '@/i18n';
+type TypesMap = Record<typeof notificationTypes[number], Ref<boolean>>
+
const emit = defineEmits<{
(ev: 'done', v: { includingTypes: string[] | null }): void,
(ev: 'closed'): void,
@@ -54,39 +56,35 @@ const props = withDefaults(defineProps<{
showGlobalToggle: true,
});
-let includingTypes = $computed(() => props.includingTypes || []);
+let includingTypes = $computed(() => props.includingTypes?.filter(x => notificationTypes.includes(x)) ?? []);
const dialog = $shallowRef<InstanceType<typeof MkModalWindow>>();
-let typesMap = $ref<Record<typeof notificationTypes[number], boolean>>({});
+const typesMap: TypesMap = notificationTypes.reduce((p, t) => ({ ...p, [t]: ref<boolean>(includingTypes.includes(t)) }), {} as any);
let useGlobalSetting = $ref((includingTypes === null || includingTypes.length === 0) && props.showGlobalToggle);
-for (const ntype of notificationTypes) {
- typesMap[ntype] = includingTypes.includes(ntype);
-}
-
function ok() {
if (useGlobalSetting) {
emit('done', { includingTypes: null });
} else {
emit('done', {
includingTypes: (Object.keys(typesMap) as typeof notificationTypes[number][])
- .filter(type => typesMap[type]),
+ .filter(type => typesMap[type].value),
});
}
- dialog.close();
+ if (dialog) dialog.close();
}
function disableAll() {
- for (const type in typesMap) {
- typesMap[type as typeof notificationTypes[number]] = false;
+ for (const type of notificationTypes) {
+ typesMap[type].value = false;
}
}
function enableAll() {
- for (const type in typesMap) {
- typesMap[type as typeof notificationTypes[number]] = true;
+ for (const type of notificationTypes) {
+ typesMap[type].value = true;
}
}
</script>
diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue
index 37ce7635a3..93b1c37055 100644
--- a/packages/frontend/src/components/MkNotifications.vue
+++ b/packages/frontend/src/components/MkNotifications.vue
@@ -18,7 +18,6 @@
<script lang="ts" setup>
import { onUnmounted, onMounted, computed, shallowRef } from 'vue';
-import { notificationTypes } from 'misskey-js';
import MkPagination, { Paging } from '@/components/MkPagination.vue';
import XNotification from '@/components/MkNotification.vue';
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
@@ -26,6 +25,7 @@ import XNote from '@/components/MkNote.vue';
import { stream } from '@/stream';
import { $i } from '@/account';
import { i18n } from '@/i18n';
+import { notificationTypes } from '@/const';
const props = defineProps<{
includeTypes?: typeof notificationTypes[number][];
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 98115dd424..02ce58451d 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -18,7 +18,7 @@
</template>
<div :class="$style.root" :style="{ background: pageMetadata?.value?.bg }" style="container-type: inline-size;">
- <RouterView :router="router"/>
+ <RouterView :key="reloadCount" :router="router"/>
</div>
</MkWindow>
</template>
@@ -67,6 +67,10 @@ const buttonsLeft = $computed(() => {
});
const buttonsRight = $computed(() => {
const buttons = [{
+ icon: 'ti ti-reload',
+ title: i18n.ts.reload,
+ onClick: reload,
+ }, {
icon: 'ti ti-player-eject',
title: i18n.ts.showInPage,
onClick: expand,
@@ -74,6 +78,7 @@ const buttonsRight = $computed(() => {
return buttons;
});
+let reloadCount = $ref(0);
router.addListener('push', ctx => {
history.push({ path: ctx.path, key: ctx.key });
@@ -115,6 +120,10 @@ function back() {
router.replace(history[history.length - 1].path, history[history.length - 1].key);
}
+function reload() {
+ reloadCount++;
+}
+
function close() {
windowEl.close();
}
diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue
index 224a42cdc2..378d0ac020 100644
--- a/packages/frontend/src/components/MkPagination.vue
+++ b/packages/frontend/src/components/MkPagination.vue
@@ -42,6 +42,7 @@ import { computed, ComputedRef, isRef, nextTick, onActivated, onBeforeUnmount, o
import * as misskey from 'misskey-js';
import * as os from '@/os';
import { onScrollTop, isTopVisible, getBodyScrollHeight, getScrollContainer, onScrollBottom, scrollToBottom, scroll, isBottomVisible } from '@/scripts/scroll';
+import { useDocumentVisibility } from '@/scripts/use-document-visibility';
import MkButton from '@/components/MkButton.vue';
import { defaultStore } from '@/store';
import { MisskeyEntity } from '@/types/date-separated-list';
@@ -104,9 +105,15 @@ const {
enableInfiniteScroll,
} = defaultStore.reactiveState;
-const contentEl = $computed(() => props.pagination.pageEl || rootEl);
+const contentEl = $computed(() => props.pagination.pageEl ?? rootEl);
const scrollableElement = $computed(() => getScrollContainer(contentEl));
+const visibility = useDocumentVisibility();
+
+let isPausingUpdate = false;
+let timerForSetPause: number | null = null;
+const BACKGROUND_PAUSE_WAIT_SEC = 10;
+
// 先頭ãŒè¡¨ç¤ºã•れã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’検出
// https://qiita.com/mkataigi/items/0154aefd2223ce23398e
let scrollObserver = $ref<IntersectionObserver>();
@@ -279,6 +286,28 @@ const fetchMoreAhead = async (): Promise<void> => {
});
};
+const isTop = (): boolean => isBackTop.value || (props.pagination.reversed ? isBottomVisible : isTopVisible)(contentEl, TOLERANCE);
+
+watch(visibility, () => {
+ if (visibility.value === 'hidden') {
+ timerForSetPause = window.setTimeout(() => {
+ isPausingUpdate = true;
+ timerForSetPause = null;
+ },
+ BACKGROUND_PAUSE_WAIT_SEC * 1000);
+ } else { // 'visible'
+ if (timerForSetPause) {
+ clearTimeout(timerForSetPause);
+ timerForSetPause = null;
+ } else {
+ isPausingUpdate = false;
+ if (isTop()) {
+ executeQueue();
+ }
+ }
+ }
+});
+
const prepend = (item: MisskeyEntity): void => {
// åˆå›žè¡¨ç¤ºæ™‚ã¯unshiftã ã‘ã§OK
if (!rootEl) {
@@ -286,9 +315,7 @@ const prepend = (item: MisskeyEntity): void => {
return;
}
- const isTop = isBackTop.value || (props.pagination.reversed ? isBottomVisible : isTopVisible)(contentEl, TOLERANCE);
-
- if (isTop) unshiftItems([item]);
+ if (isTop() && !isPausingUpdate) unshiftItems([item]);
else prependQueue(item);
};
@@ -357,6 +384,10 @@ onMounted(() => {
});
onBeforeUnmount(() => {
+ if (timerForSetPause) {
+ clearTimeout(timerForSetPause);
+ timerForSetPause = null;
+ }
scrollObserver.disconnect();
});
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 44462f8ff2..f73eab5b86 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -45,6 +45,7 @@
<button class="_buttonPrimary" style="padding: 4px; border-radius: 8px;" @click="addVisibleUser"><i class="ti ti-plus ti-fw"></i></button>
</div>
</div>
+ <MkInfo v-if="localOnly && channel == null" warn :class="$style.disableFederationWarn">{{ i18n.ts.disableFederationWarn }}</MkInfo>
<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
<input v-show="useCw" ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown">
<textarea ref="textareaEl" v-model="text" :class="[$style.text, { [$style.withCw]: useCw }]" :disabled="posting || posted" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
@@ -73,7 +74,6 @@ import { inject, watch, nextTick, onMounted, defineAsyncComponent } from 'vue';
import * as mfm from 'mfm-js';
import * as misskey from 'misskey-js';
import insertTextAtCursor from 'insert-text-at-cursor';
-import { length } from 'stringz';
import { toASCII } from 'punycode/';
import * as Acct from 'misskey-js/built/acct';
import MkNoteSimple from '@/components/MkNoteSimple.vue';
@@ -155,7 +155,7 @@ let autocomplete = $ref(null);
let draghover = $ref(false);
let quoteId = $ref(null);
let hasNotSpecifiedMentions = $ref(false);
-let recentHashtags = $ref(JSON.parse(miLocalStorage.getItem('hashtags') || '[]'));
+let recentHashtags = $ref(JSON.parse(miLocalStorage.getItem('hashtags') ?? '[]'));
let imeText = $ref('');
const draftKey = $computed((): string => {
@@ -201,7 +201,7 @@ const submitText = $computed((): string => {
});
const textLength = $computed((): number => {
- return length((text + imeText).trim());
+ return (text + imeText).trim().length;
});
const maxTextLength = $computed((): number => {
@@ -534,7 +534,7 @@ function onDrop(ev): void {
}
function saveDraft() {
- const draftData = JSON.parse(miLocalStorage.getItem('drafts') || '{}');
+ const draftData = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}');
draftData[draftKey] = {
updatedAt: new Date(),
@@ -643,7 +643,7 @@ async function post(ev?: MouseEvent) {
emit('posted');
if (postData.text && postData.text !== '') {
const hashtags_ = mfm.parse(postData.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag);
- const history = JSON.parse(miLocalStorage.getItem('hashtags') || '[]') as string[];
+ const history = JSON.parse(miLocalStorage.getItem('hashtags') ?? '[]') as string[];
miLocalStorage.setItem('hashtags', JSON.stringify(unique(hashtags_.concat(history))));
}
posting = false;
@@ -747,7 +747,7 @@ onMounted(() => {
nextTick(() => {
// 書ãã‹ã‘ã®æŠ•ç¨¿ã‚’å¾©å…ƒ
if (!props.instant && !props.mention && !props.specified) {
- const draft = JSON.parse(miLocalStorage.getItem('drafts') || '{}')[draftKey];
+ const draft = JSON.parse(miLocalStorage.getItem('drafts') ?? '{}')[draftKey];
if (draft) {
text = draft.data.text;
useCw = draft.data.useCw;
@@ -942,6 +942,10 @@ defineExpose({
background: var(--X4);
}
+.disableFederationWarn {
+ margin: 0 20px 16px 20px;
+}
+
.hasNotSpecifiedMentions {
margin: 0 20px 16px 20px;
}
diff --git a/packages/frontend/src/components/MkRolePreview.vue b/packages/frontend/src/components/MkRolePreview.vue
index 8c1d7af190..2f5866f340 100644
--- a/packages/frontend/src/components/MkRolePreview.vue
+++ b/packages/frontend/src/components/MkRolePreview.vue
@@ -1,10 +1,15 @@
<template>
-<MkA v-adaptive-bg :to="`/admin/roles/${role.id}`" class="_panel" :class="$style.root" tabindex="-1" :style="{ '--color': role.color }">
+<MkA v-adaptive-bg :to="forModeration ? `/admin/roles/${role.id}` : `/roles/${role.id}`" class="_panel" :class="$style.root" tabindex="-1" :style="{ '--color': role.color }">
<div :class="$style.title">
<span :class="$style.icon">
- <i v-if="role.isAdministrator" class="ti ti-crown" style="color: var(--accent);"></i>
- <i v-else-if="role.isModerator" class="ti ti-shield" style="color: var(--accent);"></i>
- <i v-else class="ti ti-user" style="opacity: 0.7;"></i>
+ <template v-if="role.iconUrl">
+ <img :class="$style.badge" :src="role.iconUrl"/>
+ </template>
+ <template v-else>
+ <i v-if="role.isAdministrator" class="ti ti-crown" style="color: var(--accent);"></i>
+ <i v-else-if="role.isModerator" class="ti ti-shield" style="color: var(--accent);"></i>
+ <i v-else class="ti ti-user" style="opacity: 0.7;"></i>
+ </template>
</span>
<span :class="$style.name">{{ role.name }}</span>
<span v-if="role.target === 'manual'" :class="$style.users">{{ role.usersCount }} users</span>
@@ -20,6 +25,7 @@ import { i18n } from '@/i18n';
const props = defineProps<{
role: any;
+ forModeration: boolean;
}>();
</script>
@@ -38,6 +44,11 @@ const props = defineProps<{
margin-right: 8px;
}
+.badge {
+ height: 1.3em;
+ vertical-align: -20%;
+}
+
.name {
font-weight: bold;
}
diff --git a/packages/frontend/src/components/MkSelect.vue b/packages/frontend/src/components/MkSelect.vue
index cb64b1e484..2de890186a 100644
--- a/packages/frontend/src/components/MkSelect.vue
+++ b/packages/frontend/src/components/MkSelect.vue
@@ -34,7 +34,7 @@ import { useInterval } from '@/scripts/use-interval';
import { i18n } from '@/i18n';
const props = defineProps<{
- modelValue: string;
+ modelValue: string | null;
required?: boolean;
readonly?: boolean;
disabled?: boolean;
@@ -48,7 +48,7 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'change', _ev: KeyboardEvent): void;
- (ev: 'update:modelValue', value: string): void;
+ (ev: 'update:modelValue', value: string | null): void;
}>();
const slots = useSlots();
diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue
index ae4f38e56c..ffc5e82b56 100644
--- a/packages/frontend/src/components/MkSignin.vue
+++ b/packages/frontend/src/components/MkSignin.vue
@@ -10,7 +10,7 @@
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</MkInput>
- <MkInput v-if="!user || user && !user.usePasswordLessLogin" v-model="password" :placeholder="i18n.ts.password" type="password" :with-password-toggle="true" required data-cy-signin-password>
+ <MkInput v-if="!user || user && !user.usePasswordLessLogin" v-model="password" :placeholder="i18n.ts.password" type="password" autocomplete="current-password" :with-password-toggle="true" required data-cy-signin-password>
<template #prefix><i class="ti ti-lock"></i></template>
<template #caption><button class="_textButton" type="button" @click="resetPassword">{{ i18n.ts.forgotPassword }}</button></template>
</MkInput>
@@ -28,11 +28,11 @@
</div>
<div class="twofa-group totp-group">
<p style="margin-bottom:0;">{{ i18n.ts.twoStepAuthentication }}</p>
- <MkInput v-if="user && user.usePasswordLessLogin" v-model="password" type="password" :with-password-toggle="true" required>
+ <MkInput v-if="user && user.usePasswordLessLogin" v-model="password" type="password" autocomplete="current-password" :with-password-toggle="true" required>
<template #label>{{ i18n.ts.password }}</template>
<template #prefix><i class="ti ti-lock"></i></template>
</MkInput>
- <MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" :spellcheck="false" required>
+ <MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="one-time-code" :spellcheck="false" required>
<template #label>{{ i18n.ts.token }}</template>
<template #prefix><i class="ti ti-123"></i></template>
</MkInput>
diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue
index 1ba48bf77d..87f7c61a92 100644
--- a/packages/frontend/src/components/MkTimeline.vue
+++ b/packages/frontend/src/components/MkTimeline.vue
@@ -1,10 +1,10 @@
<template>
-<XNotes ref="tlComponent" :no-gap="!$store.state.showGapBetweenNotesInTimeline" :pagination="pagination" @queue="emit('queue', $event)"/>
+<MkNotes ref="tlComponent" :no-gap="!$store.state.showGapBetweenNotesInTimeline" :pagination="pagination" @queue="emit('queue', $event)"/>
</template>
<script lang="ts" setup>
import { computed, provide, onUnmounted } from 'vue';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import { stream } from '@/stream';
import * as sound from '@/scripts/sound';
import { $i } from '@/account';
@@ -24,7 +24,7 @@ const emit = defineEmits<{
provide('inChannel', computed(() => props.src === 'channel'));
-const tlComponent: InstanceType<typeof XNotes> = $ref();
+const tlComponent: InstanceType<typeof MkNotes> = $ref();
const prepend = note => {
tlComponent.pagingComponent?.prepend(note);
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index b97b7cf07b..5381ecbfa5 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -1,12 +1,25 @@
<template>
-<div v-if="playerEnabled" :class="$style.player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`">
- <button :class="$style.disablePlayer" :title="i18n.ts.disablePlayer" @click="playerEnabled = false"><i class="ti ti-x"></i></button>
- <iframe v-if="player.url.startsWith('http://') || player.url.startsWith('https://')" :class="$style.playerIframe" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
- <span v-else>invalid url</span>
-</div>
-<div v-else-if="tweetId && tweetExpanded" ref="twitter" :class="$style.twitter">
- <iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&amp;hideCard=false&amp;hideThread=false&amp;lang=en&amp;theme=${$store.state.darkMode ? 'dark' : 'light'}&amp;id=${tweetId}`"></iframe>
-</div>
+<template v-if="playerEnabled">
+ <div :class="$style.player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`">
+ <iframe v-if="player.url.startsWith('http://') || player.url.startsWith('https://')" :class="$style.playerIframe" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
+ <span v-else>invalid url</span>
+ </div>
+ <div :class="$style.action">
+ <MkButton :small="true" inline @click="playerEnabled = false">
+ <i class="ti ti-x"></i> {{ i18n.ts.disablePlayer }}
+ </MkButton>
+ </div>
+</template>
+<template v-else-if="tweetId && tweetExpanded">
+ <div ref="twitter" :class="$style.twitter">
+ <iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&amp;hideCard=false&amp;hideThread=false&amp;lang=en&amp;theme=${$store.state.darkMode ? 'dark' : 'light'}&amp;id=${tweetId}`"></iframe>
+ </div>
+ <div :class="$style.action">
+ <MkButton :small="true" inline @click="tweetExpanded = false">
+ <i class="ti ti-x"></i> {{ i18n.ts.close }}
+ </MkButton>
+ </div>
+</template>
<div v-else :class="$style.urlPreview">
<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url">
<div v-if="thumbnail" :class="$style.thumbnail" :style="`background-image: url('${thumbnail}')`">
diff --git a/packages/frontend/src/components/MkUserList.vue b/packages/frontend/src/components/MkUserList.vue
index dd683fcc23..51eb426e97 100644
--- a/packages/frontend/src/components/MkUserList.vue
+++ b/packages/frontend/src/components/MkUserList.vue
@@ -7,9 +7,9 @@
</div>
</template>
- <template #default="{ items: users }">
+ <template #default="{ items }">
<div class="efvhhmdq">
- <MkUserInfo v-for="user in users" :key="user.id" class="user" :user="user"/>
+ <MkUserInfo v-for="item in items" :key="item.id" class="user" :user="extractor(item)"/>
</div>
</template>
</MkPagination>
@@ -20,10 +20,13 @@ import MkUserInfo from '@/components/MkUserInfo.vue';
import MkPagination, { Paging } from '@/components/MkPagination.vue';
import { i18n } from '@/i18n';
-const props = defineProps<{
+const props = withDefaults(defineProps<{
pagination: Paging;
noGap?: boolean;
-}>();
+ extractor?: (item: any) => any;
+}>(), {
+ extractor: (item) => item,
+});
</script>
<style lang="scss" scoped>
diff --git a/packages/frontend/src/components/MkUserSelectDialog.vue b/packages/frontend/src/components/MkUserSelectDialog.vue
index 981ae56e6c..dc78bbf42d 100644
--- a/packages/frontend/src/components/MkUserSelectDialog.vue
+++ b/packages/frontend/src/components/MkUserSelectDialog.vue
@@ -16,7 +16,7 @@
<template #label>{{ i18n.ts.username }}</template>
<template #prefix>@</template>
</MkInput>
- <MkInput v-model="host" @update:model-value="search">
+ <MkInput v-model="host" :datalist="[hostname]" @update:model-value="search">
<template #label>{{ i18n.ts.host }}</template>
<template #prefix>@</template>
</MkInput>
@@ -61,6 +61,7 @@ import * as os from '@/os';
import { defaultStore } from '@/store';
import { i18n } from '@/i18n';
import { $i } from '@/account';
+import { hostname } from '@/config';
const emit = defineEmits<{
(ev: 'ok', selected: misskey.entities.UserDetailed): void;
@@ -115,7 +116,7 @@ onMounted(() => {
os.api('users/show', {
userIds: defaultStore.state.recentlyUsedUsers,
}).then(users => {
- if (props.includeSelf) {
+ if (props.includeSelf && users.find(x => $i ? x.id === $i.id : true) == null) {
recentUsers = [$i, ...users];
} else {
recentUsers = users;
diff --git a/packages/frontend/src/components/MkVisibilityPicker.vue b/packages/frontend/src/components/MkVisibilityPicker.vue
index 516b88c13d..703c75c7d0 100644
--- a/packages/frontend/src/components/MkVisibilityPicker.vue
+++ b/packages/frontend/src/components/MkVisibilityPicker.vue
@@ -33,8 +33,8 @@
<button key="localOnly" class="_button" :class="[$style.item, $style.localOnly, { [$style.active]: localOnly }]" data-index="5" @click="localOnly = !localOnly">
<div :class="$style.icon"><i class="ti ti-world-off"></i></div>
<div :class="$style.body">
- <span :class="$style.itemTitle">{{ i18n.ts._visibility.localOnly }}</span>
- <span :class="$style.itemDescription">{{ i18n.ts._visibility.localOnlyDescription }}</span>
+ <span :class="$style.itemTitle">{{ i18n.ts._visibility.disableFederation }}</span>
+ <span :class="$style.itemDescription">{{ i18n.ts._visibility.disableFederationDescription }}</span>
</div>
<div :class="$style.toggle"><i :class="localOnly ? 'ti ti-toggle-right' : 'ti ti-toggle-left'"></i></div>
</button>
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index e6dedd0354..84aae1cff8 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -24,7 +24,7 @@ const rawUrl = computed(() => {
return props.url;
}
if (props.host == null && !customEmojiName.value.includes('@')) {
- return customEmojis.value.find(x => x.name === customEmojiName.value)?.url || null;
+ return customEmojis.value.find(x => x.name === customEmojiName.value)?.url ?? null;
}
return props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`;
});
@@ -32,7 +32,7 @@ const rawUrl = computed(() => {
const url = computed(() =>
defaultStore.reactiveState.disableShowingAnimatedImages.value && rawUrl.value
? getStaticImageUrl(rawUrl.value)
- : rawUrl.value
+ : rawUrl.value,
);
const alt = computed(() => `:${customEmojiName.value}:`);
@@ -41,7 +41,7 @@ let errored = $ref(url.value == null);
<style lang="scss" module>
.root {
- height: 2.5em;
+ height: 2em;
vertical-align: middle;
transition: transform 0.2s ease;
diff --git a/packages/frontend/src/components/global/MkPageHeader.tabs.vue b/packages/frontend/src/components/global/MkPageHeader.tabs.vue
index b181b62986..42760da08f 100644
--- a/packages/frontend/src/components/global/MkPageHeader.tabs.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.tabs.vue
@@ -1,23 +1,33 @@
<template>
- <div ref="el" :class="$style.tabs" @wheel="onTabWheel">
- <div :class="$style.tabsInner">
- <button v-for="t in tabs" :ref="(el) => tabRefs[t.key] = (el as HTMLElement)" v-tooltip.noDelay="t.title"
- class="_button" :class="[$style.tab, { [$style.active]: t.key != null && t.key === props.tab, [$style.animate]: defaultStore.reactiveState.animation.value }]"
- @mousedown="(ev) => onTabMousedown(t, ev)" @click="(ev) => onTabClick(t, ev)">
- <div :class="$style.tabInner">
- <i v-if="t.icon" :class="[$style.tabIcon, t.icon]"></i>
- <div v-if="!t.iconOnly || (!defaultStore.reactiveState.animation.value && t.key === tab)"
- :class="$style.tabTitle">{{ t.title }}</div>
- <Transition v-else mode="in-out" @enter="enter" @after-enter="afterEnter" @leave="leave"
- @after-leave="afterLeave">
- <div v-show="t.key === tab" :class="[$style.tabTitle, $style.animate]">{{ t.title }}</div>
- </Transition>
+<div ref="el" :class="$style.tabs" @wheel="onTabWheel">
+ <div :class="$style.tabsInner">
+ <button
+ v-for="t in tabs" :ref="(el) => tabRefs[t.key] = (el as HTMLElement)" v-tooltip.noDelay="t.title"
+ class="_button" :class="[$style.tab, { [$style.active]: t.key != null && t.key === props.tab, [$style.animate]: defaultStore.reactiveState.animation.value }]"
+ @mousedown="(ev) => onTabMousedown(t, ev)" @click="(ev) => onTabClick(t, ev)"
+ >
+ <div :class="$style.tabInner">
+ <i v-if="t.icon" :class="[$style.tabIcon, t.icon]"></i>
+ <div
+ v-if="!t.iconOnly || (!defaultStore.reactiveState.animation.value && t.key === tab)"
+ :class="$style.tabTitle"
+ >
+ {{ t.title }}
</div>
- </button>
- </div>
- <div ref="tabHighlightEl"
- :class="[$style.tabHighlight, { [$style.animate]: defaultStore.reactiveState.animation.value }]"></div>
+ <Transition
+ v-else mode="in-out" @enter="enter" @after-enter="afterEnter" @leave="leave"
+ @after-leave="afterLeave"
+ >
+ <div v-show="t.key === tab" :class="[$style.tabTitle, $style.animate]">{{ t.title }}</div>
+ </Transition>
+ </div>
+ </button>
</div>
+ <div
+ ref="tabHighlightEl"
+ :class="[$style.tabHighlight, { [$style.animate]: defaultStore.reactiveState.animation.value }]"
+ ></div>
+</div>
</template>
<script lang="ts">
@@ -93,7 +103,7 @@ function onTabWheel(ev: WheelEvent) {
ev.stopPropagation();
(ev.currentTarget as HTMLElement).scrollBy({
left: ev.deltaY,
- behavior: 'smooth',
+ behavior: 'instant',
});
}
return false;
@@ -206,8 +216,8 @@ onUnmounted(() => {
align-items: center;
}
-.tabIcon+.tabTitle {
- padding-left: 8px;
+.tabIcon + .tabTitle {
+ padding-left: 4px;
}
.tabTitle {
diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue
index 98233b02e0..589ca92d75 100644
--- a/packages/frontend/src/components/global/MkPageHeader.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.vue
@@ -2,9 +2,9 @@
<div v-if="show" ref="el" :class="[$style.root]" :style="{ background: bg }">
<div :class="[$style.upper, { [$style.slim]: narrow, [$style.thin]: thin_ }]">
<div v-if="!thin_ && narrow && props.displayMyAvatar && $i" class="_button" :class="$style.buttonsLeft" @click="openAccountMenu">
- <MkAvatar :class="$style.avatar" :user="$i" />
+ <MkAvatar :class="$style.avatar" :user="$i"/>
</div>
- <div v-else-if="!thin_ && narrow && !hideTitle" :class="$style.buttonsLeft" />
+ <div v-else-if="!thin_ && narrow && !hideTitle" :class="$style.buttonsLeft"/>
<template v-if="metadata">
<div v-if="!hideTitle" :class="$style.titleContainer" @click="top">
@@ -36,11 +36,11 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, inject } from 'vue';
import tinycolor from 'tinycolor2';
+import XTabs, { Tab } from './MkPageHeader.tabs.vue';
import { scrollToTop } from '@/scripts/scroll';
import { globalEvents } from '@/events';
import { injectPageMetadata } from '@/scripts/page-metadata';
import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
-import XTabs, { Tab } from './MkPageHeader.tabs.vue';
const props = withDefaults(defineProps<{
tabs?: Tab[];
@@ -96,7 +96,7 @@ function onTabClick(): void {
}
const calcBg = () => {
- const rawBg = metadata?.bg || 'var(--bg)';
+ const rawBg = metadata?.bg ?? 'var(--bg)';
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
tinyBg.setAlpha(0.85);
bg.value = tinyBg.toRgbString();
@@ -147,10 +147,7 @@ onUnmounted(() => {
.tabs:first-child {
margin-left: auto;
- }
- .tabs:not(:first-child) {
- padding-left: 16px;
- mask-image: linear-gradient(90deg, rgba(0,0,0,0), rgb(0,0,0) 16px, rgb(0,0,0) 100%);
+ padding: 0 12px;
}
.tabs {
margin-right: auto;
diff --git a/packages/frontend/src/components/global/MkTime.vue b/packages/frontend/src/components/global/MkTime.vue
index 66c0bd5135..3fa8bb9adc 100644
--- a/packages/frontend/src/components/global/MkTime.vue
+++ b/packages/frontend/src/components/global/MkTime.vue
@@ -1,6 +1,7 @@
<template>
<time :title="absolute">
- <template v-if="mode === 'relative'">{{ relative }}</template>
+ <template v-if="invalid">{{ i18n.ts._ago.invalid }}</template>
+ <template v-else-if="mode === 'relative'">{{ relative }}</template>
<template v-else-if="mode === 'absolute'">{{ absolute }}</template>
<template v-else-if="mode === 'detail'">{{ absolute }} ({{ relative }})</template>
</time>
@@ -12,18 +13,24 @@ import { i18n } from '@/i18n';
import { dateTimeFormat } from '@/scripts/intl-const';
const props = withDefaults(defineProps<{
- time: Date | string;
+ time: Date | string | number | null;
mode?: 'relative' | 'absolute' | 'detail';
}>(), {
mode: 'relative',
});
-const _time = typeof props.time === 'string' ? new Date(props.time) : props.time;
-const absolute = dateTimeFormat.format(_time);
+const _time = props.time == null ? NaN :
+ typeof props.time === 'number' ? props.time :
+ (props.time instanceof Date ? props.time : new Date(props.time)).getTime();
+const invalid = Number.isNaN(_time);
+const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid;
-let now = $shallowRef(new Date());
-const relative = $computed(() => {
- const ago = (now.getTime() - _time.getTime()) / 1000/*ms*/;
+let now = $ref((new Date()).getTime());
+const relative = $computed<string>(() => {
+ if (props.mode === 'absolute') return ''; // absoluteã§ã¯relativeを使ã‚ãªã„ã®ã§è¨ˆç®—ã—ãªã„
+ if (invalid) return i18n.ts._ago.invalid;
+
+ const ago = (now - _time) / 1000/*ms*/;
return (
ago >= 31536000 ? i18n.t('_ago.yearsAgo', { n: Math.round(ago / 31536000).toString() }) :
ago >= 2592000 ? i18n.t('_ago.monthsAgo', { n: Math.round(ago / 2592000).toString() }) :
@@ -39,8 +46,8 @@ const relative = $computed(() => {
let tickId: number;
function tick() {
- now = new Date();
- const ago = (now.getTime() - _time.getTime()) / 1000/*ms*/;
+ now = (new Date()).getTime();
+ const ago = (now - _time) / 1000/*ms*/;
const next = ago < 60 ? 10000 : ago < 3600 ? 60000 : 180000;
tickId = window.setTimeout(tick, next);
diff --git a/packages/frontend/src/components/mfm.ts b/packages/frontend/src/components/mfm.ts
index 1b1d27ea2a..e84eabcbcc 100644
--- a/packages/frontend/src/components/mfm.ts
+++ b/packages/frontend/src/components/mfm.ts
@@ -278,7 +278,7 @@ export default defineComponent({
case 'hashtag': {
return [h(MkA, {
key: Math.random(),
- to: this.isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.props.hashtag)}`,
+ to: this.isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/user-tags/${encodeURIComponent(token.props.hashtag)}`,
style: 'color:var(--hashtag);',
}, `#${token.props.hashtag}`)];
}
diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts
index 77366cf07b..1d44786a63 100644
--- a/packages/frontend/src/const.ts
+++ b/packages/frontend/src/const.ts
@@ -43,3 +43,6 @@ https://github.com/sindresorhus/file-type/blob/main/supported.js
https://github.com/sindresorhus/file-type/blob/main/core.js
https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers
*/
+
+export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app'] as const;
+export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const;
diff --git a/packages/frontend/src/init.ts b/packages/frontend/src/init.ts
index 8c657295f9..0a626b36c6 100644
--- a/packages/frontend/src/init.ts
+++ b/packages/frontend/src/init.ts
@@ -36,7 +36,6 @@ import { $i, refreshAccount, login, updateAccount, signout } from '@/account';
import { defaultStore, ColdDeviceStorage } from '@/store';
import { fetchInstance, instance } from '@/instance';
import { makeHotkey } from '@/scripts/hotkey';
-import { search } from '@/scripts/search';
import { deviceKind } from '@/scripts/device-kind';
import { initializeSw } from '@/scripts/initialize-sw';
import { reloadChannel } from '@/scripts/unison-reload';
@@ -47,6 +46,7 @@ import { deckStore } from './ui/deck/deck-store';
import { miLocalStorage } from './local-storage';
import { claimAchievement, claimedAchievements } from './scripts/achievements';
import { fetchCustomEmojis } from './custom-emojis';
+import { mainRouter } from './router';
console.info(`Misskey v${version}`);
@@ -352,7 +352,9 @@ const hotkeys = {
'd': (): void => {
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
- 's': search,
+ 's': (): void => {
+ mainRouter.push('/search');
+ }
};
if ($i) {
diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts
index 95bf6e8181..48bece05fa 100644
--- a/packages/frontend/src/navbar.ts
+++ b/packages/frontend/src/navbar.ts
@@ -1,7 +1,6 @@
import { computed, reactive } from 'vue';
import { $i } from './account';
import { miLocalStorage } from './local-storage';
-import { search } from '@/scripts/search';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { ui } from '@/config';
@@ -42,7 +41,7 @@ export const navbarItemDef = reactive({
search: {
title: i18n.ts.search,
icon: 'ti ti-search',
- action: () => search(),
+ to: '/search',
},
lists: {
title: i18n.ts.lists,
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 6bff12661f..7e38fe5f6d 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -246,7 +246,10 @@ export function inputText(props: {
title?: string | null;
text?: string | null;
placeholder?: string | null;
+ autocomplete?: string;
default?: string | null;
+ minLength?: number;
+ maxLength?: number;
}): Promise<{ canceled: true; result: undefined; } | {
canceled: false; result: string;
}> {
@@ -257,7 +260,10 @@ export function inputText(props: {
input: {
type: props.type,
placeholder: props.placeholder,
+ autocomplete: props.autocomplete,
default: props.default,
+ minLength: props.minLength,
+ maxLength: props.maxLength,
},
}, {
done: result => {
@@ -271,6 +277,7 @@ export function inputNumber(props: {
title?: string | null;
text?: string | null;
placeholder?: string | null;
+ autocomplete?: string;
default?: number | null;
}): Promise<{ canceled: true; result: undefined; } | {
canceled: false; result: number;
@@ -282,6 +289,7 @@ export function inputNumber(props: {
input: {
type: 'number',
placeholder: props.placeholder,
+ autocomplete: props.autocomplete,
default: props.default,
},
}, {
@@ -595,9 +603,3 @@ export function checkExistence(fileData: ArrayBuffer): Promise<any> {
});
});
}*/
-
-export const shownNoteIds = new Set();
-
-window.setInterval(() => {
- shownNoteIds.clear();
-}, 1000 * 60 * 5);
diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index bc3d248193..782fe9fdb2 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -84,6 +84,10 @@
</div>
<p>{{ i18n.ts._aboutMisskey.morePatrons }}</p>
</FormSection>
+ <FormSection>
+ <template #label>Credits</template>
+ <p>Misskeyã§ä½¿ã‚れる画åƒã®ä¸€éƒ¨ã¯ã€è¨±å¯ã‚’å¾—ã¦ã€Œã‚ã®å­ãŒã“ã£ã¡ã‚’見ã¦ã‚‹ãƒ¡ãƒ¼ã‚«ãƒ¼ã€ã§ä½œæˆã—ãŸã‚‚ã®ãŒå«ã¾ã‚Œã¾ã™ã€‚</p>
+ </FormSection>
</div>
</MkSpacer>
</div>
@@ -111,6 +115,12 @@ const patronsWithIcon = [{
}, {
name: 'ã ã‚Œã‹ã•ã‚“',
icon: 'https://misskey-hub.net/patrons/f7409b5e5a88477a9b9d740c408de125.jpg',
+}, {
+ name: 'narazaka',
+ icon: 'https://misskey-hub.net/patrons/e3affff31ffb4877b1196c7360abc3e5.jpg',
+}, {
+ name: 'ã²ã¨ã…',
+ icon: 'https://misskey-hub.net/patrons/8cc0d0a0a6d84c88bca1aedabf6ed5ab.jpg',
}];
const patrons = [
diff --git a/packages/frontend/src/pages/admin/_header_.vue b/packages/frontend/src/pages/admin/_header_.vue
index 599b16e465..372c63ff4c 100644
--- a/packages/frontend/src/pages/admin/_header_.vue
+++ b/packages/frontend/src/pages/admin/_header_.vue
@@ -113,7 +113,7 @@ function onTabClick(tab: Tab, ev: MouseEvent): void {
}
const calcBg = () => {
- const rawBg = metadata?.bg || 'var(--bg)';
+ const rawBg = metadata?.bg ?? 'var(--bg)';
const tinyBg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
tinyBg.setAlpha(0.85);
bg.value = tinyBg.toRgbString();
diff --git a/packages/frontend/src/pages/admin/ads.vue b/packages/frontend/src/pages/admin/ads.vue
index e5431b177c..828bfe6007 100644
--- a/packages/frontend/src/pages/admin/ads.vue
+++ b/packages/frontend/src/pages/admin/ads.vue
@@ -44,6 +44,9 @@
<MkButton class="button" inline danger @click="remove(ad)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
</div>
</div>
+ <MkButton class="button" @click="more()">
+ <i class="ti ti-reload"></i>{{ i18n.ts.more }}
+ </MkButton>
</div>
</MkSpacer>
</MkStickyContainer>
@@ -123,7 +126,21 @@ function save(ad) {
});
}
}
-
+function more() {
+ os.api('admin/ad/list', { untilId: ads.reduce((acc, ad) => ad.id != null ? ad : acc).id }).then(adsResponse => {
+ ads = ads.concat(adsResponse.map(r => {
+ const exdate = new Date(r.expiresAt);
+ const stdate = new Date(r.startsAt);
+ exdate.setMilliseconds(exdate.getMilliseconds() - localTimeDiff);
+ stdate.setMilliseconds(stdate.getMilliseconds() - localTimeDiff);
+ return {
+ ...r,
+ expiresAt: exdate.toISOString().slice(0, 16),
+ startsAt: stdate.toISOString().slice(0, 16),
+ };
+ }));
+ });
+}
const headerActions = $computed(() => [{
asFullButton: true,
icon: 'ti ti-plus',
diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue
index 0365165b5d..e7d57ad4f0 100644
--- a/packages/frontend/src/pages/admin/roles.role.vue
+++ b/packages/frontend/src/pages/admin/roles.role.vue
@@ -16,16 +16,29 @@
<MkFolder v-if="role.target === 'manual'" default-open>
<template #icon><i class="ti ti-users"></i></template>
<template #label>{{ i18n.ts.users }}</template>
- <template #suffix>{{ role.users.length }}</template>
+ <template #suffix>{{ role.usersCount }}</template>
<div class="_gaps">
<MkButton primary rounded @click="assign"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
- <div v-for="user in role.users" :key="user.id" :class="$style.userItem">
- <MkA :class="$style.user" :to="`/user-info/${user.id}`">
- <MkUserCardMini :user="user"/>
- </MkA>
- <button class="_button" :class="$style.unassign" @click="unassign(user, $event)"><i class="ti ti-x"></i></button>
- </div>
+ <MkPagination :pagination="usersPagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
+ <div>{{ i18n.ts.noUsers }}</div>
+ </div>
+ </template>
+
+ <template #default="{ items }">
+ <div class="_gaps_s">
+ <div v-for="item in items" :key="item.user.id" :class="$style.userItem">
+ <MkA :class="$style.user" :to="`/user-info/${item.user.id}`">
+ <MkUserCardMini :user="item.user"/>
+ </MkA>
+ <button class="_button" :class="$style.unassign" @click="unassign(item.user, $event)"><i class="ti ti-x"></i></button>
+ </div>
+ </div>
+ </template>
+ </MkPagination>
</div>
</MkFolder>
<MkInfo v-else>{{ i18n.ts._role.isConditionalRole }}</MkInfo>
@@ -47,6 +60,7 @@ import { useRouter } from '@/router';
import MkButton from '@/components/MkButton.vue';
import MkUserCardMini from '@/components/MkUserCardMini.vue';
import MkInfo from '@/components/MkInfo.vue';
+import MkPagination, { Paging } from '@/components/MkPagination.vue';
const router = useRouter();
@@ -54,6 +68,14 @@ const props = defineProps<{
id?: string;
}>();
+const usersPagination = {
+ endpoint: 'admin/roles/users' as const,
+ limit: 20,
+ params: computed(() => ({
+ roleId: props.id,
+ })),
+};
+
const role = reactive(await os.api('admin/roles/show', {
roleId: props.id,
}));
@@ -114,6 +136,7 @@ definePageMetadata(computed(() => ({
.user {
flex: 1;
+ min-width: 0;
}
.unassign {
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue
index 19a0f6617f..d89f0d2a7d 100644
--- a/packages/frontend/src/pages/admin/roles.vue
+++ b/packages/frontend/src/pages/admin/roles.vue
@@ -133,7 +133,7 @@
</div>
</MkFolder>
<div class="_gaps_s">
- <MkRolePreview v-for="role in roles" :key="role.id" :role="role"/>
+ <MkRolePreview v-for="role in roles" :key="role.id" :role="role" :for-moderation="true"/>
</div>
</div>
</MkSpacer>
diff --git a/packages/frontend/src/pages/antenna-timeline.vue b/packages/frontend/src/pages/antenna-timeline.vue
index 44c79b623a..cf803d6c7f 100644
--- a/packages/frontend/src/pages/antenna-timeline.vue
+++ b/packages/frontend/src/pages/antenna-timeline.vue
@@ -4,7 +4,7 @@
<div ref="rootEl" v-hotkey.global="keymap" class="tqmomfks">
<div v-if="queue > 0" class="new"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<div class="tl">
- <XTimeline
+ <MkTimeline
ref="tlEl" :key="antennaId"
class="tl"
src="antenna"
@@ -19,7 +19,7 @@
<script lang="ts" setup>
import { computed, watch } from 'vue';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import { scroll } from '@/scripts/scroll';
import * as os from '@/os';
import { useRouter } from '@/router';
@@ -35,7 +35,7 @@ const props = defineProps<{
let antenna = $ref(null);
let queue = $ref(0);
let rootEl = $shallowRef<HTMLElement>();
-let tlEl = $shallowRef<InstanceType<typeof XTimeline>>();
+let tlEl = $shallowRef<InstanceType<typeof MkTimeline>>();
const keymap = $computed(() => ({
't': focus,
}));
diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue
index 50afffc460..4f8afb9ea2 100644
--- a/packages/frontend/src/pages/auth.vue
+++ b/packages/frontend/src/pages/auth.vue
@@ -1,12 +1,12 @@
<template>
<MkStickyContainer>
- <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template>
+ <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 />
+ <MkLoading/>
</div>
<div v-else-if="$i && session">
<XForm
@@ -21,15 +21,16 @@
</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 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" />
+ <MkSignin @login="onLogin"/>
</div>
</MkSpacer>
</MkStickyContainer>
@@ -37,12 +38,12 @@
<script lang="ts" setup>
import { onMounted } from 'vue';
+import { AuthSession } from 'misskey-js/built/entities';
import XForm from './auth.form.vue';
import MkSignin from '@/components/MkSignin.vue';
import * as os from '@/os';
import { $i, login } from '@/account';
import { definePageMetadata } from '@/scripts/page-metadata';
-import { AuthSession } from 'misskey-js/built/entities';
import { i18n } from '@/i18n';
const props = defineProps<{
@@ -82,7 +83,7 @@ onMounted(async () => {
} else {
state = 'waiting';
}
- } catch (e) {
+ } catch (err) {
state = 'fetch-session-error';
}
});
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index 0bfc772353..6b4fcb32f8 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -1,9 +1,9 @@
<template>
<MkStickyContainer>
- <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
+ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :content-max="700">
- <div v-if="channel">
- <div class="wpgynlbz _panel _margin" :class="{ hide: !showBanner }">
+ <div v-if="channel && tab === 'timeline'" class="_gaps">
+ <div class="wpgynlbz _panel" :class="{ hide: !showBanner }">
<XChannelFollowButton :channel="channel" :full="true" class="subscribe"/>
<button class="_button toggle" @click="() => showBanner = !showBanner">
<template v-if="showBanner"><i class="ti ti-chevron-up"></i></template>
@@ -23,9 +23,13 @@
</div>
</div>
- <MkPostForm v-if="$i" :channel="channel" class="post-form _panel _margin" fixed/>
+ <!-- スマホ・タブレットã®å ´åˆã€ã‚­ãƒ¼ãƒœãƒ¼ãƒ‰ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã¨æŠ•ç¨¿ãŒè¦‹ã¥ã‚‰ããªã‚‹ã®ã§ã€ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—å ´åˆã®ã¿è‡ªå‹•ã§ãƒ•ォーカスを当ã¦ã‚‹ -->
+ <MkPostForm v-if="$i" :channel="channel" class="post-form _panel" fixed :autofocus="deviceKind === 'desktop'"/>
- <XTimeline :key="channelId" class="_margin" src="channel" :channel="channelId" @before="before" @after="after"/>
+ <MkTimeline :key="channelId" src="channel" :channel="channelId" @before="before" @after="after"/>
+ </div>
+ <div v-else-if="tab === 'featured'">
+ <MkNotes :pagination="featuredPagination"/>
</div>
</MkSpacer>
</MkStickyContainer>
@@ -34,13 +38,15 @@
<script lang="ts" setup>
import { computed, watch } from 'vue';
import MkPostForm from '@/components/MkPostForm.vue';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
import * as os from '@/os';
import { useRouter } from '@/router';
import { $i } from '@/account';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
+import { deviceKind } from '@/scripts/device-kind';
+import MkNotes from '@/components/MkNotes.vue';
const router = useRouter();
@@ -48,15 +54,17 @@ const props = defineProps<{
channelId: string;
}>();
+let tab = $ref('timeline');
let channel = $ref(null);
let showBanner = $ref(true);
-const pagination = {
- endpoint: 'channels/timeline' as const,
+const featuredPagination = $computed(() => ({
+ endpoint: 'notes/featured' as const,
limit: 10,
- params: computed(() => ({
+ offsetMode: true,
+ params: {
channelId: props.channelId,
- })),
-};
+ },
+}));
watch(() => props.channelId, async () => {
channel = await os.api('channels/show', {
@@ -74,7 +82,15 @@ const headerActions = $computed(() => channel && channel.userId ? [{
handler: edit,
}] : null);
-const headerTabs = $computed(() => []);
+const headerTabs = $computed(() => [{
+ key: 'timeline',
+ title: i18n.ts.timeline,
+ icon: 'ti ti-home',
+}, {
+ key: 'featured',
+ title: i18n.ts.featured,
+ icon: 'ti ti-bolt',
+}]);
definePageMetadata(computed(() => channel ? {
title: channel.name,
diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index cd9cec0d4f..d4e8f27005 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -12,7 +12,7 @@
</div>
</div>
- <XNotes :pagination="pagination" :detail="true"/>
+ <MkNotes :pagination="pagination" :detail="true"/>
</div>
</MkSpacer>
</MkStickyContainer>
@@ -21,7 +21,7 @@
<script lang="ts" setup>
import { computed, watch, provide } from 'vue';
import * as misskey from 'misskey-js';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import { $i } from '@/account';
import { i18n } from '@/i18n';
import * as os from '@/os';
diff --git a/packages/frontend/src/pages/explore.featured.vue b/packages/frontend/src/pages/explore.featured.vue
index 18a371a086..a972ae04ec 100644
--- a/packages/frontend/src/pages/explore.featured.vue
+++ b/packages/frontend/src/pages/explore.featured.vue
@@ -4,13 +4,13 @@
<option value="notes">{{ i18n.ts.notes }}</option>
<option value="polls">{{ i18n.ts.poll }}</option>
</MkTab>
- <XNotes v-if="tab === 'notes'" :pagination="paginationForNotes"/>
- <XNotes v-else-if="tab === 'polls'" :pagination="paginationForPolls"/>
+ <MkNotes v-if="tab === 'notes'" :pagination="paginationForNotes"/>
+ <MkNotes v-else-if="tab === 'polls'" :pagination="paginationForPolls"/>
</MkSpacer>
</template>
<script lang="ts" setup>
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import MkTab from '@/components/MkTab.vue';
import { i18n } from '@/i18n';
diff --git a/packages/frontend/src/pages/explore.roles.vue b/packages/frontend/src/pages/explore.roles.vue
new file mode 100644
index 0000000000..8be11008c2
--- /dev/null
+++ b/packages/frontend/src/pages/explore.roles.vue
@@ -0,0 +1,22 @@
+<template>
+<MkSpacer :content-max="1200">
+ <div class="_gaps_s">
+ <MkRolePreview v-for="role in roles" :key="role.id" :role="role" :for-moderation="false"/>
+ </div>
+</MkSpacer>
+</template>
+
+<script lang="ts" setup>
+import { } from 'vue';
+import MkRolePreview from '@/components/MkRolePreview.vue';
+import * as os from '@/os';
+
+let roles = $ref();
+
+os.api('roles/list', {
+ limit: 30,
+}).then(res => {
+ roles = res;
+});
+</script>
+
diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue
index 4d6ac7d710..c441407d97 100644
--- a/packages/frontend/src/pages/explore.users.vue
+++ b/packages/frontend/src/pages/explore.users.vue
@@ -8,19 +8,19 @@
<template v-if="tag == null">
<MkFoldableSection class="_margin" persist-key="explore-pinned-users">
<template #header><i class="ti ti-bookmark ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.pinnedUsers }}</template>
- <XUserList :pagination="pinnedUsers"/>
+ <MkUserList :pagination="pinnedUsers"/>
</MkFoldableSection>
<MkFoldableSection class="_margin" persist-key="explore-popular-users">
<template #header><i class="ti ti-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template>
- <XUserList :pagination="popularUsers"/>
+ <MkUserList :pagination="popularUsers"/>
</MkFoldableSection>
<MkFoldableSection class="_margin" persist-key="explore-recently-updated-users">
<template #header><i class="ti ti-message ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template>
- <XUserList :pagination="recentlyUpdatedUsers"/>
+ <MkUserList :pagination="recentlyUpdatedUsers"/>
</MkFoldableSection>
<MkFoldableSection class="_margin" persist-key="explore-recently-registered-users">
<template #header><i class="ti ti-plus ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyRegisteredUsers }}</template>
- <XUserList :pagination="recentlyRegisteredUsers"/>
+ <MkUserList :pagination="recentlyRegisteredUsers"/>
</MkFoldableSection>
</template>
</div>
@@ -29,28 +29,28 @@
<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularTags }}</template>
<div class="vxjfqztj">
- <MkA v-for="tag in tagsLocal" :key="'local:' + tag.tag" :to="`/explore/tags/${tag.tag}`" class="local">{{ tag.tag }}</MkA>
- <MkA v-for="tag in tagsRemote" :key="'remote:' + tag.tag" :to="`/explore/tags/${tag.tag}`">{{ tag.tag }}</MkA>
+ <MkA v-for="tag in tagsLocal" :key="'local:' + tag.tag" :to="`/user-tags/${tag.tag}`" class="local">{{ tag.tag }}</MkA>
+ <MkA v-for="tag in tagsRemote" :key="'remote:' + tag.tag" :to="`/user-tags/${tag.tag}`">{{ tag.tag }}</MkA>
</div>
</MkFoldableSection>
<MkFoldableSection v-if="tag != null" :key="`${tag}`" class="_margin">
<template #header><i class="ti ti-hash ti-fw" style="margin-right: 0.5em;"></i>{{ tag }}</template>
- <XUserList :pagination="tagUsers"/>
+ <MkUserList :pagination="tagUsers"/>
</MkFoldableSection>
<template v-if="tag == null">
<MkFoldableSection class="_margin">
<template #header><i class="ti ti-chart-line ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.popularUsers }}</template>
- <XUserList :pagination="popularUsersF"/>
+ <MkUserList :pagination="popularUsersF"/>
</MkFoldableSection>
<MkFoldableSection class="_margin">
<template #header><i class="ti ti-message ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyUpdatedUsers }}</template>
- <XUserList :pagination="recentlyUpdatedUsersF"/>
+ <MkUserList :pagination="recentlyUpdatedUsersF"/>
</MkFoldableSection>
<MkFoldableSection class="_margin">
<template #header><i class="ti ti-rocket ti-fw" style="margin-right: 0.5em;"></i>{{ i18n.ts.recentlyDiscoveredUsers }}</template>
- <XUserList :pagination="recentlyRegisteredUsersF"/>
+ <MkUserList :pagination="recentlyRegisteredUsersF"/>
</MkFoldableSection>
</template>
</div>
@@ -59,7 +59,7 @@
<script lang="ts" setup>
import { watch } from 'vue';
-import XUserList from '@/components/MkUserList.vue';
+import MkUserList from '@/components/MkUserList.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
import MkTab from '@/components/MkTab.vue';
import * as os from '@/os';
diff --git a/packages/frontend/src/pages/explore.vue b/packages/frontend/src/pages/explore.vue
index dd1685f272..2131188dde 100644
--- a/packages/frontend/src/pages/explore.vue
+++ b/packages/frontend/src/pages/explore.vue
@@ -8,22 +8,8 @@
<div v-else-if="tab === 'users'">
<XUsers/>
</div>
- <div v-else-if="tab === 'search'">
- <MkSpacer :content-max="1200">
- <div>
- <MkInput v-model="searchQuery" :debounce="true" type="search">
- <template #prefix><i class="ti ti-search"></i></template>
- <template #label>{{ i18n.ts.searchUser }}</template>
- </MkInput>
- <MkRadios v-model="searchOrigin">
- <option value="combined">{{ i18n.ts.all }}</option>
- <option value="local">{{ i18n.ts.local }}</option>
- <option value="remote">{{ i18n.ts.remote }}</option>
- </MkRadios>
- </div>
-
- <XUserList v-if="searchQuery" ref="searchEl" class="_margin" :pagination="searchPagination"/>
- </MkSpacer>
+ <div v-else-if="tab === 'roles'">
+ <XRoles/>
</div>
</div>
</MkStickyContainer>
@@ -33,12 +19,10 @@
import { computed, watch } from 'vue';
import XFeatured from './explore.featured.vue';
import XUsers from './explore.users.vue';
+import XRoles from './explore.roles.vue';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
-import MkInput from '@/components/MkInput.vue';
-import MkRadios from '@/components/MkRadios.vue';
import { definePageMetadata } from '@/scripts/page-metadata';
import { i18n } from '@/i18n';
-import XUserList from '@/components/MkUserList.vue';
const props = withDefaults(defineProps<{
tag?: string;
@@ -49,22 +33,11 @@ const props = withDefaults(defineProps<{
let tab = $ref(props.initialTab);
let tagsEl = $shallowRef<InstanceType<typeof MkFoldableSection>>();
-let searchQuery = $ref(null);
-let searchOrigin = $ref('combined');
watch(() => props.tag, () => {
if (tagsEl) tagsEl.toggleContent(props.tag == null);
});
-const searchPagination = {
- endpoint: 'users/search' as const,
- limit: 10,
- params: computed(() => (searchQuery && searchQuery !== '') ? {
- query: searchQuery,
- origin: searchOrigin,
- } : null),
-};
-
const headerActions = $computed(() => []);
const headerTabs = $computed(() => [{
@@ -76,8 +49,9 @@ const headerTabs = $computed(() => [{
icon: 'ti ti-users',
title: i18n.ts.users,
}, {
- key: 'search',
- title: i18n.ts.search,
+ key: 'roles',
+ icon: 'ti ti-badges',
+ title: i18n.ts.roles,
}]);
definePageMetadata(computed(() => ({
diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue
index 297286176b..165e357ebd 100644
--- a/packages/frontend/src/pages/note.vue
+++ b/packages/frontend/src/pages/note.vue
@@ -6,7 +6,7 @@
<Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
<div v-if="note" class="note">
<div v-if="showNext" class="_margin">
- <XNotes class="" :pagination="nextPagination" :no-gap="true"/>
+ <MkNotes class="" :pagination="nextPagination" :no-gap="true"/>
</div>
<div class="main _margin">
@@ -29,7 +29,7 @@
</div>
<div v-if="showPrev" class="_margin">
- <XNotes class="" :pagination="prevPagination" :no-gap="true"/>
+ <MkNotes class="" :pagination="prevPagination" :no-gap="true"/>
</div>
</div>
<MkError v-else-if="error" @retry="fetchNote()"/>
@@ -44,7 +44,7 @@
import { computed, watch } from 'vue';
import * as misskey from 'misskey-js';
import XNoteDetailed from '@/components/MkNoteDetailed.vue';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os';
diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue
index 7106951de2..da64a4c1e0 100644
--- a/packages/frontend/src/pages/notifications.vue
+++ b/packages/frontend/src/pages/notifications.vue
@@ -6,10 +6,10 @@
<XNotifications class="notifications" :include-types="includeTypes" :unread-only="unreadOnly"/>
</div>
<div v-else-if="tab === 'mentions'">
- <XNotes :pagination="mentionsPagination"/>
+ <MkNotes :pagination="mentionsPagination"/>
</div>
<div v-else-if="tab === 'directNotes'">
- <XNotes :pagination="directNotesPagination"/>
+ <MkNotes :pagination="directNotesPagination"/>
</div>
</MkSpacer>
</MkStickyContainer>
@@ -17,12 +17,12 @@
<script lang="ts" setup>
import { computed } from 'vue';
-import { notificationTypes } from 'misskey-js';
import XNotifications from '@/components/MkNotifications.vue';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
+import { notificationTypes } from '@/const';
let tab = $ref('all');
let includeTypes = $ref<string[] | null>(null);
diff --git a/packages/frontend/src/pages/role.vue b/packages/frontend/src/pages/role.vue
new file mode 100644
index 0000000000..2e9d3d6169
--- /dev/null
+++ b/packages/frontend/src/pages/role.vue
@@ -0,0 +1,47 @@
+<template>
+<MkStickyContainer>
+ <template #header><MkPageHeader/></template>
+
+ <MkSpacer :content-max="1200">
+ <div class="_gaps_s">
+ <div v-if="role">{{ role.description }}</div>
+ <MkUserList :pagination="users" :extractor="(item) => item.user"/>
+ </div>
+ </MkSpacer>
+</MkStickyContainer>
+</template>
+
+<script lang="ts" setup>
+import { computed, watch } from 'vue';
+import * as os from '@/os';
+import MkUserList from '@/components/MkUserList.vue';
+import { definePageMetadata } from '@/scripts/page-metadata';
+
+const props = defineProps<{
+ role: string;
+}>();
+
+let role = $ref();
+
+watch(() => props.role, () => {
+ os.api('roles/show', {
+ roleId: props.role,
+ }).then(res => {
+ role = res;
+ });
+}, { immediate: true });
+
+const users = $computed(() => ({
+ endpoint: 'roles/users' as const,
+ limit: 30,
+ params: {
+ roleId: props.role,
+ },
+}));
+
+definePageMetadata(computed(() => ({
+ title: role?.name,
+ icon: 'ti ti-badge',
+})));
+</script>
+
diff --git a/packages/frontend/src/pages/search.vue b/packages/frontend/src/pages/search.vue
index 7918f9f577..d32bdcd78e 100644
--- a/packages/frontend/src/pages/search.vue
+++ b/packages/frontend/src/pages/search.vue
@@ -2,18 +2,41 @@
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :content-max="800">
- <XNotes ref="notes" :pagination="pagination"/>
+ <MkInput v-model="searchQuery" :large="true" :autofocus="true" :debounce="true" type="search" style="margin-bottom: var(--margin);" @update:model-value="search()">
+ <template #prefix><i class="ti ti-search"></i></template>
+ </MkInput>
+ <MkTab v-model="searchType" style="margin-bottom: var(--margin);" @update:model-value="search()">
+ <option value="note">{{ i18n.ts.note }}</option>
+ <option value="user">{{ i18n.ts.user }}</option>
+ </MkTab>
+
+ <div v-if="searchType === 'note'">
+ <MkNotes v-if="searchQuery" ref="notes" :pagination="notePagination"/>
+ </div>
+ <div v-else>
+ <MkRadios v-model="searchOrigin" style="margin-bottom: var(--margin);" @update:model-value="search()">
+ <option value="combined">{{ i18n.ts.all }}</option>
+ <option value="local">{{ i18n.ts.local }}</option>
+ <option value="remote">{{ i18n.ts.remote }}</option>
+ </MkRadios>
+
+ <MkUserList v-if="searchQuery" ref="users" :pagination="userPagination"/>
+ </div>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
-import { computed } from 'vue';
-import XNotes from '@/components/MkNotes.vue';
+import { computed, onMounted } from 'vue';
+import MkNotes from '@/components/MkNotes.vue';
+import MkUserList from '@/components/MkUserList.vue';
+import MkInput from '@/components/MkInput.vue';
+import MkTab from '@/components/MkTab.vue';
+import MkRadios from '@/components/MkRadios.vue';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import * as os from '@/os';
-import { useRouter } from '@/router';
+import { useRouter, mainRouter } from '@/router';
import { $i } from '@/account';
const router = useRouter();
@@ -21,14 +44,63 @@ const router = useRouter();
const props = defineProps<{
query: string;
channel?: string;
+ type?: string;
+ origin?: string;
}>();
-const query = props.query;
+let searchQuery = $ref('');
+let searchType = $ref('note');
+let searchOrigin = $ref('combined');
+
+onMounted(() => {
+ searchQuery = props.query ?? '';
+ searchType = props.type ?? 'note';
+ searchOrigin = props.origin ?? 'combined';
+
+ if (searchQuery) {
+ search();
+ }
+});
+
+const search = async () => {
+ const query = searchQuery.toString().trim();
+
+ if (query == null || query === '') return;
+
+ if (query.startsWith('@') && !query.includes(' ')) {
+ mainRouter.push(`/${query}`);
+ return;
+ }
+
+ if (query.startsWith('#')) {
+ mainRouter.push(`/tags/${encodeURIComponent(query.substr(1))}`);
+ return;
+ }
+
+ // like 2018/03/12
+ if (/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}/.test(query.replace(/-/g, '/'))) {
+ const date = new Date(query.replace(/-/g, '/'));
+
+ // 日付ã—ã‹æŒ‡å®šã•れã¦ãªã„å ´åˆã€ä¾‹ãˆã° 2018/03/12 ãªã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯
+ // 2018/03/12 ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を「å«ã‚€ã€çµæžœã«ãªã‚‹ã“ã¨ã‚’期待ã™ã‚‹ã¯ãšãªã®ã§
+ // 23時間59分進ã‚ã‚‹(ãã®ã¾ã¾ã ã¨ 2018/03/12 00:00:00 「ã¾ã§ã€ã®
+ // çµæžœã«ãªã£ã¦ã—ã¾ã„ã€2018/03/12 ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯å«ã¾ã‚Œãªã„)
+ if (query.replace(/-/g, '/').match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/)) {
+ date.setHours(23, 59, 59, 999);
+ }
+
+ // TODO
+ //v.$root.$emit('warp', date);
+ os.alert({
+ icon: 'ti ti-history',
+ iconOnly: true, autoClose: true,
+ });
+ return;
+ }
-if ($i != null) {
- if (query.startsWith('https://') || (query.startsWith('@') && !query.includes(' '))) {
+ if (query.startsWith('https://')) {
const promise = os.api('ap/show', {
- uri: props.query,
+ uri: query,
});
os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
@@ -36,28 +108,58 @@ if ($i != null) {
const res = await promise;
if (res.type === 'User') {
- router.replace(`/@${res.object.username}@${res.object.host}`);
+ mainRouter.push(`/@${res.object.username}@${res.object.host}`);
} else if (res.type === 'Note') {
- router.replace(`/notes/${res.object.id}`);
+ mainRouter.push(`/notes/${res.object.id}`);
}
+
+ return;
}
-}
-const pagination = {
+ if ($i != null) {
+ if (query.startsWith('https://') || (query.startsWith('@') && !query.includes(' '))) {
+ const promise = os.api('ap/show', {
+ uri: query,
+ });
+
+ os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
+
+ const res = await promise;
+
+ if (res.type === 'User') {
+ router.replace(`/@${res.object.username}@${res.object.host}`);
+ } else if (res.type === 'Note') {
+ router.replace(`/notes/${res.object.id}`);
+ }
+ }
+ }
+
+ window.history.replaceState('', '', `/search?q=${encodeURIComponent(query)}&type=${searchType}${searchType === 'user' ? `&origin=${searchOrigin}` : ''}`);
+};
+
+const notePagination = {
endpoint: 'notes/search' as const,
limit: 10,
params: computed(() => ({
- query: props.query,
+ query: searchQuery,
channelId: props.channel,
})),
};
+const userPagination = {
+ endpoint: 'users/search' as const,
+ limit: 10,
+ params: computed(() => ({
+ query: searchQuery,
+ origin: searchOrigin,
+ })),
+};
const headerActions = $computed(() => []);
const headerTabs = $computed(() => []);
definePageMetadata(computed(() => ({
- title: i18n.t('searchWith', { q: props.query }),
+ title: searchQuery ? i18n.t('searchWith', { q: searchQuery }) : i18n.ts.search,
icon: 'ti ti-search',
})));
</script>
diff --git a/packages/frontend/src/pages/settings/2fa.qrdialog.vue b/packages/frontend/src/pages/settings/2fa.qrdialog.vue
new file mode 100644
index 0000000000..1d836db5f5
--- /dev/null
+++ b/packages/frontend/src/pages/settings/2fa.qrdialog.vue
@@ -0,0 +1,82 @@
+<template>
+<MkModal
+ ref="dialogEl"
+ :prefer-type="'dialog'"
+ :z-priority="'low'"
+ @click="cancel"
+ @close="cancel"
+ @closed="emit('closed')"
+>
+ <div :class="$style.root" class="_gaps_m">
+ <I18n :src="i18n.ts._2fa.step1" tag="div">
+ <template #a>
+ <a href="https://authy.com/" rel="noopener" target="_blank" class="_link">Authy</a>
+ </template>
+ <template #b>
+ <a href="https://support.google.com/accounts/answer/1066447" rel="noopener" target="_blank" class="_link">Google Authenticator</a>
+ </template>
+ </I18n>
+ <div>
+ {{ i18n.ts._2fa.step2 }}<br>
+ {{ i18n.ts._2fa.step2Click }}
+ </div>
+ <a :href="twoFactorData.url"><img :class="$style.qr" :src="twoFactorData.qr"></a>
+ <MkKeyValue :copy="twoFactorData.url">
+ <template #key>{{ i18n.ts._2fa.step2Url }}</template>
+ <template #value>{{ twoFactorData.url }}</template>
+ </MkKeyValue>
+ <div class="_buttons">
+ <MkButton primary @click="ok">{{ i18n.ts.next }}</MkButton>
+ <MkButton @click="cancel">{{ i18n.ts.cancel }}</MkButton>
+ </div>
+ </div>
+</MkModal>
+</template>
+
+<script lang="ts" setup>
+import MkButton from '@/components/MkButton.vue';
+import MkModal from '@/components/MkModal.vue';
+import MkKeyValue from '@/components/MkKeyValue.vue';
+import { i18n } from '@/i18n';
+
+defineProps<{
+ twoFactorData: {
+ qr: string;
+ url: string;
+ };
+}>();
+
+const emit = defineEmits<{
+ (ev: 'ok'): void;
+ (ev: 'cancel'): void;
+ (ev: 'closed'): void;
+}>();
+
+const cancel = () => {
+ emit('cancel');
+ emit('closed');
+};
+
+const ok = () => {
+ emit('ok');
+ emit('closed');
+};
+</script>
+
+<style lang="scss" module>
+.root {
+ position: relative;
+ margin: auto;
+ padding: 32px;
+ min-width: 320px;
+ max-width: calc(100svw - 64px);
+ box-sizing: border-box;
+ background: var(--panel);
+ border-radius: var(--radius);
+}
+
+.qr {
+ width: 20em;
+ max-width: 100%;
+}
+</style>
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index e6ef09668c..891934d706 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -1,216 +1,258 @@
<template>
-<div>
- <MkButton v-if="!twoFactorData && !$i.twoFactorEnabled" @click="register">{{ i18n.ts._2fa.registerDevice }}</MkButton>
- <template v-if="$i.twoFactorEnabled">
- <p>{{ i18n.ts._2fa.alreadyRegistered }}</p>
- <MkButton @click="unregister">{{ i18n.ts.unregister }}</MkButton>
+<FormSection :first="first">
+ <template #label>{{ i18n.ts['2fa'] }}</template>
- <template v-if="supportsCredentials">
- <hr class="totp-method-sep">
-
- <h2 class="heading">{{ i18n.ts.securityKey }}</h2>
- <p>{{ i18n.ts._2fa.securityKeyInfo }}</p>
- <div class="key-list">
- <div v-for="key in $i.securityKeysList" class="key">
- <h3>{{ key.name }}</h3>
- <div class="last-used">{{ i18n.ts.lastUsed }}<MkTime :time="key.lastUsed"/></div>
- <MkButton @click="unregisterKey(key)">{{ i18n.ts.unregister }}</MkButton>
- </div>
+ <div v-if="$i" class="_gaps_s">
+ <MkFolder>
+ <template #icon><i class="ti ti-shield-lock"></i></template>
+ <template #label>{{ i18n.ts.totp }}</template>
+ <template #caption>{{ i18n.ts.totpDescription }}</template>
+ <div v-if="$i.twoFactorEnabled" class="_gaps_s">
+ <div v-text="i18n.ts._2fa.alreadyRegistered"/>
+ <template v-if="$i.securityKeysList.length > 0">
+ <MkButton @click="renewTOTP">{{ i18n.ts._2fa.renewTOTP }}</MkButton>
+ <MkInfo>{{ i18n.ts._2fa.whyTOTPOnlyRenew }}</MkInfo>
+ </template>
+ <MkButton v-else @click="unregisterTOTP">{{ i18n.ts.unregister }}</MkButton>
</div>
- <MkSwitch v-if="$i.securityKeysList.length > 0" v-model="usePasswordLessLogin" @update:model-value="updatePasswordLessLogin">{{ i18n.ts.passwordLessLogin }}</MkSwitch>
+ <MkButton v-else-if="!twoFactorData && !$i.twoFactorEnabled" @click="registerTOTP">{{ i18n.ts._2fa.registerTOTP }}</MkButton>
+ </MkFolder>
+
+ <MkFolder>
+ <template #icon><i class="ti ti-key"></i></template>
+ <template #label>{{ i18n.ts.securityKeyAndPasskey }}</template>
+ <div class="_gaps_s">
+ <MkInfo>
+ {{ i18n.ts._2fa.securityKeyInfo }}<br>
+ <br>
+ {{ i18n.ts._2fa.chromePasskeyNotSupported }}
+ </MkInfo>
- <MkInfo v-if="registration && registration.error" warn>{{ i18n.ts.error }} {{ registration.error }}</MkInfo>
- <MkButton v-if="!registration || registration.error" @click="addSecurityKey">{{ i18n.ts._2fa.registerKey }}</MkButton>
+ <MkInfo v-if="!supportsCredentials" warn>
+ {{ i18n.ts._2fa.securityKeyNotSupported }}
+ </MkInfo>
- <ol v-if="registration && !registration.error">
- <li v-if="registration.stage >= 0">
- {{ i18n.ts.tapSecurityKey }}
- <MkLoading v-if="registration.saving && registration.stage == 0" :em="true"/>
- </li>
- <li v-if="registration.stage >= 1">
- <MkForm :disabled="registration.stage != 1 || registration.saving">
- <MkInput v-model="keyName" :max="30">
- <template #label>{{ i18n.ts.securityKeyName }}</template>
- </MkInput>
- <MkButton :disabled="keyName.length == 0" @click="registerKey">{{ i18n.ts.registerSecurityKey }}</MkButton>
- <MkLoading v-if="registration.saving && registration.stage == 1" :em="true"/>
- </MkForm>
- </li>
- </ol>
- </template>
- </template>
- <div v-if="twoFactorData && !$i.twoFactorEnabled">
- <ol style="margin: 0; padding: 0 0 0 1em;">
- <li>
- <I18n :src="i18n.ts._2fa.step1" tag="span">
- <template #a>
- <a href="https://authy.com/" rel="noopener" target="_blank" class="_link">Authy</a>
- </template>
- <template #b>
- <a href="https://support.google.com/accounts/answer/1066447" rel="noopener" target="_blank" class="_link">Google Authenticator</a>
- </template>
- </I18n>
- </li>
- <li>{{ i18n.ts._2fa.step2 }}<br><img :src="twoFactorData.qr"><p>{{ $ts._2fa.step2Url }}<br>{{ twoFactorData.url }}</p></li>
- <li>
- {{ i18n.ts._2fa.step3 }}<br>
- <MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" :spellcheck="false"><template #label>{{ i18n.ts.token }}</template></MkInput>
- <MkButton primary @click="submit">{{ i18n.ts.done }}</MkButton>
- </li>
- </ol>
- <MkInfo>{{ i18n.ts._2fa.step4 }}</MkInfo>
+ <MkInfo v-else-if="supportsCredentials && !$i.twoFactorEnabled" warn>
+ {{ i18n.ts._2fa.registerTOTPBeforeKey }}
+ </MkInfo>
+
+ <template v-else>
+ <MkButton primary @click="addSecurityKey">{{ i18n.ts._2fa.registerSecurityKey }}</MkButton>
+ <MkFolder v-for="key in $i.securityKeysList" :key="key.id">
+ <template #label>{{ key.name }}</template>
+ <template #suffix><I18n :src="i18n.ts.lastUsedAt"><template #t><MkTime :time="key.lastUsed"/></template></I18n></template>
+ <div class="_buttons">
+ <MkButton @click="renameKey(key)"><i class="ti ti-forms"></i> {{ i18n.ts.rename }}</MkButton>
+ <MkButton danger @click="unregisterKey(key)"><i class="ti ti-trash"></i> {{ i18n.ts.unregister }}</MkButton>
+ </div>
+ </MkFolder>
+ </template>
+ </div>
+ </MkFolder>
+
+ <MkSwitch :disabled="!$i.twoFactorEnabled || $i.securityKeysList.length === 0" :model-value="usePasswordLessLogin" @update:model-value="v => updatePasswordLessLogin(v)">
+ <template #label>{{ i18n.ts.passwordLessLogin }}</template>
+ <template #caption>{{ i18n.ts.passwordLessLoginDescription }}</template>
+ </MkSwitch>
</div>
-</div>
+</FormSection>
</template>
<script lang="ts" setup>
-import { ref } from 'vue';
+import { ref, defineAsyncComponent } from 'vue';
import { hostname } from '@/config';
import { byteify, hexify, stringify } from '@/scripts/2fa';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
-import MkInput from '@/components/MkInput.vue';
import MkSwitch from '@/components/MkSwitch.vue';
+import FormSection from '@/components/form/section.vue';
+import MkFolder from '@/components/MkFolder.vue';
import * as os from '@/os';
import { $i } from '@/account';
import { i18n } from '@/i18n';
+// メモ: å„エンドãƒã‚¤ãƒ³ãƒˆã¯meUpdatedを発行ã™ã‚‹ãŸã‚ã€refreshAccountã¯ä¸è¦
+
+withDefaults(defineProps<{
+ first?: boolean;
+}>(), {
+ first: false,
+});
+
const twoFactorData = ref<any>(null);
const supportsCredentials = ref(!!navigator.credentials);
-const usePasswordLessLogin = ref($i!.usePasswordLessLogin);
-const registration = ref<any>(null);
-const keyName = ref('');
-const token = ref(null);
+const usePasswordLessLogin = $computed(() => $i!.usePasswordLessLogin);
-function register() {
- os.inputText({
- title: i18n.ts.password,
+async function registerTOTP() {
+ const password = await os.inputText({
+ title: i18n.ts._2fa.registerTOTP,
+ text: i18n.ts._2fa.passwordToTOTP,
type: 'password',
- }).then(({ canceled, result: password }) => {
- if (canceled) return;
- os.api('i/2fa/register', {
- password: password,
- }).then(data => {
- twoFactorData.value = data;
- });
+ autocomplete: 'current-password',
+ });
+ if (password.canceled) return;
+
+ const twoFactorData = await os.apiWithDialog('i/2fa/register', {
+ password: password.result,
+ });
+
+ const qrdialog = await new Promise<boolean>(res => {
+ os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
+ twoFactorData,
+ }, {
+ 'ok': () => res(true),
+ 'cancel': () => res(false),
+ }, 'closed');
+ });
+ if (!qrdialog) return;
+
+ const token = await os.inputNumber({
+ title: i18n.ts._2fa.step3Title,
+ text: i18n.ts._2fa.step3,
+ autocomplete: 'one-time-code',
+ });
+ if (token.canceled) return;
+
+ await os.apiWithDialog('i/2fa/done', {
+ token: token.result.toString(),
+ });
+
+ await os.alert({
+ type: 'success',
+ text: i18n.ts._2fa.step4,
});
}
-function unregister() {
+function unregisterTOTP() {
os.inputText({
title: i18n.ts.password,
type: 'password',
+ autocomplete: 'current-password',
}).then(({ canceled, result: password }) => {
if (canceled) return;
- os.api('i/2fa/unregister', {
+ os.apiWithDialog('i/2fa/unregister', {
password: password,
- }).then(() => {
- usePasswordLessLogin.value = false;
- updatePasswordLessLogin();
- }).then(() => {
- os.success();
- $i!.twoFactorEnabled = false;
+ }).catch(error => {
+ os.alert({
+ type: 'error',
+ text: error,
+ });
});
});
}
-function submit() {
- os.api('i/2fa/done', {
- token: token.value,
- }).then(() => {
- os.success();
- $i!.twoFactorEnabled = true;
- }).catch(err => {
- os.alert({
- type: 'error',
- text: err,
- });
+function renewTOTP() {
+ os.confirm({
+ type: 'question',
+ title: i18n.ts._2fa.renewTOTP,
+ text: i18n.ts._2fa.renewTOTPConfirm,
+ okText: i18n.ts._2fa.renewTOTPOk,
+ cancelText: i18n.ts._2fa.renewTOTPCancel,
+ }).then(({ canceled }) => {
+ if (canceled) return;
+ registerTOTP();
});
}
-function registerKey() {
- registration.value.saving = true;
- os.api('i/2fa/key-done', {
- password: registration.value.password,
- name: keyName.value,
- challengeId: registration.value.challengeId,
- // we convert each 16 bits to a string to serialise
- clientDataJSON: stringify(registration.value.credential.response.clientDataJSON),
- attestationObject: hexify(registration.value.credential.response.attestationObject),
- }).then(key => {
- registration.value = null;
- key.lastUsed = new Date();
- os.success();
+async function unregisterKey(key) {
+ const confirm = await os.confirm({
+ type: 'question',
+ title: i18n.ts._2fa.removeKey,
+ text: i18n.t('_2fa.removeKeyConfirm', { name: key.name }),
});
-}
+ if (confirm.canceled) return;
-function unregisterKey(key) {
- os.inputText({
+ const password = await os.inputText({
title: i18n.ts.password,
type: 'password',
- }).then(({ canceled, result: password }) => {
- if (canceled) return;
- return os.api('i/2fa/remove-key', {
- password,
- credentialId: key.id,
- }).then(() => {
- usePasswordLessLogin.value = false;
- updatePasswordLessLogin();
- }).then(() => {
- os.success();
- });
+ autocomplete: 'current-password',
+ });
+ if (password.canceled) return;
+
+ await os.apiWithDialog('i/2fa/remove-key', {
+ password: password.result,
+ credentialId: key.id,
});
+ os.success();
}
-function addSecurityKey() {
- os.inputText({
+async function renameKey(key) {
+ const name = await os.inputText({
+ title: i18n.ts.rename,
+ default: key.name,
+ type: 'text',
+ minLength: 1,
+ maxLength: 30,
+ });
+ if (name.canceled) return;
+
+ await os.apiWithDialog('i/2fa/update-key', {
+ name: name.result,
+ credentialId: key.id,
+ });
+}
+
+async function addSecurityKey() {
+ const password = await os.inputText({
title: i18n.ts.password,
type: 'password',
- }).then(({ canceled, result: password }) => {
- if (canceled) return;
- os.api('i/2fa/register-key', {
- password,
- }).then(reg => {
- registration.value = {
- password,
- challengeId: reg!.challengeId,
- stage: 0,
- publicKeyOptions: {
- challenge: byteify(reg!.challenge, 'base64'),
- rp: {
- id: hostname,
- name: 'Misskey',
- },
- user: {
- id: byteify($i!.id, 'ascii'),
- name: $i!.username,
- displayName: $i!.name,
- },
- pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
- timeout: 60000,
- attestation: 'direct',
- },
- saving: true,
- };
- return navigator.credentials.create({
- publicKey: registration.value.publicKeyOptions,
- });
- }).then(credential => {
- registration.value.credential = credential;
- registration.value.saving = false;
- registration.value.stage = 1;
- }).catch(err => {
- console.warn('Error while registering?', err);
- registration.value.error = err.message;
- registration.value.stage = -1;
- });
+ autocomplete: 'current-password',
+ });
+ if (password.canceled) return;
+
+ const challenge: any = await os.apiWithDialog('i/2fa/register-key', {
+ password: password.result,
+ });
+
+ const name = await os.inputText({
+ title: i18n.ts._2fa.registerSecurityKey,
+ text: i18n.ts._2fa.securityKeyName,
+ type: 'text',
+ minLength: 1,
+ maxLength: 30,
+ });
+ if (name.canceled) return;
+
+ const webAuthnCreation = navigator.credentials.create({
+ publicKey: {
+ challenge: byteify(challenge.challenge, 'base64'),
+ rp: {
+ id: hostname,
+ name: 'Misskey',
+ },
+ user: {
+ id: byteify($i!.id, 'ascii'),
+ name: $i!.username,
+ displayName: $i!.name,
+ },
+ pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
+ timeout: 60000,
+ attestation: 'direct',
+ },
+ }) as Promise<PublicKeyCredential & { response: AuthenticatorAttestationResponse; } | null>;
+
+ const credential = await os.promiseDialog(
+ webAuthnCreation,
+ null,
+ () => {}, // ユーザーã®ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã¯rejectãªã®ã§ã‚¨ãƒ©ãƒ¼ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’出ã•ãªã„
+ i18n.ts._2fa.tapSecurityKey,
+ );
+ if (!credential) return;
+
+ await os.apiWithDialog('i/2fa/key-done', {
+ password: password.result,
+ name: name.result,
+ challengeId: challenge.challengeId,
+ // we convert each 16 bits to a string to serialise
+ clientDataJSON: stringify(credential.response.clientDataJSON),
+ attestationObject: hexify(credential.response.attestationObject),
});
}
-async function updatePasswordLessLogin() {
- await os.api('i/2fa/password-less', {
- value: !!usePasswordLessLogin.value,
+async function updatePasswordLessLogin(value: boolean) {
+ await os.apiWithDialog('i/2fa/password-less', {
+ value,
});
}
</script>
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index e6752460a8..a5619eab86 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -181,7 +181,7 @@ const menuDef = computed(() => [{
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt');
- await fetchCustomEmojis();
+ await fetchCustomEmojis(true);
unisonReload();
},
}, {
diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue
index f64202fff2..2cf2f6d7f6 100644
--- a/packages/frontend/src/pages/settings/notifications.vue
+++ b/packages/frontend/src/pages/settings/notifications.vue
@@ -27,7 +27,6 @@
<script lang="ts" setup>
import { defineAsyncComponent } from 'vue';
-import { notificationTypes } from 'misskey-js';
import FormLink from '@/components/form/link.vue';
import FormSection from '@/components/form/section.vue';
import MkSwitch from '@/components/MkSwitch.vue';
@@ -36,6 +35,7 @@ import { $i } from '@/account';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import MkPushNotificationAllowButton from '@/components/MkPushNotificationAllowButton.vue';
+import { notificationTypes } from '@/const';
let allowButton = $shallowRef<InstanceType<typeof MkPushNotificationAllowButton>>();
let pushRegistrationInServer = $computed(() => allowButton?.pushRegistrationInServer);
diff --git a/packages/frontend/src/pages/settings/plugin.vue b/packages/frontend/src/pages/settings/plugin.vue
index b3459a2e2e..8b57dceefb 100644
--- a/packages/frontend/src/pages/settings/plugin.vue
+++ b/packages/frontend/src/pages/settings/plugin.vue
@@ -4,27 +4,29 @@
<FormSection>
<template #label>{{ i18n.ts.manage }}</template>
- <div v-for="plugin in plugins" :key="plugin.id" class="_panel _gaps_s" style="padding: 20px;">
- <span style="display: flex;"><b>{{ plugin.name }}</b><span style="margin-left: auto;">v{{ plugin.version }}</span></span>
+ <div class="_gaps_s">
+ <div v-for="plugin in plugins" :key="plugin.id" class="_panel _gaps_s" style="padding: 20px;">
+ <span style="display: flex;"><b>{{ plugin.name }}</b><span style="margin-left: auto;">v{{ plugin.version }}</span></span>
- <MkSwitch :model-value="plugin.active" @update:model-value="changeActive(plugin, $event)">{{ i18n.ts.makeActive }}</MkSwitch>
+ <MkSwitch :model-value="plugin.active" @update:model-value="changeActive(plugin, $event)">{{ i18n.ts.makeActive }}</MkSwitch>
- <MkKeyValue>
- <template #key>{{ i18n.ts.author }}</template>
- <template #value>{{ plugin.author }}</template>
- </MkKeyValue>
- <MkKeyValue>
- <template #key>{{ i18n.ts.description }}</template>
- <template #value>{{ plugin.description }}</template>
- </MkKeyValue>
- <MkKeyValue>
- <template #key>{{ i18n.ts.permission }}</template>
- <template #value>{{ plugin.permission }}</template>
- </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.author }}</template>
+ <template #value>{{ plugin.author }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.description }}</template>
+ <template #value>{{ plugin.description }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.permission }}</template>
+ <template #value>{{ plugin.permission }}</template>
+ </MkKeyValue>
- <div class="_buttons">
- <MkButton v-if="plugin.config" inline @click="config(plugin)"><i class="ti ti-settings"></i> {{ i18n.ts.settings }}</MkButton>
- <MkButton inline danger @click="uninstall(plugin)"><i class="ti ti-trash"></i> {{ i18n.ts.uninstall }}</MkButton>
+ <div class="_buttons">
+ <MkButton v-if="plugin.config" inline @click="config(plugin)"><i class="ti ti-settings"></i> {{ i18n.ts.settings }}</MkButton>
+ <MkButton inline danger @click="uninstall(plugin)"><i class="ti ti-trash"></i> {{ i18n.ts.uninstall }}</MkButton>
+ </div>
</div>
</div>
</FormSection>
diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index 5692ce80cb..c83c48d5ad 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -46,7 +46,7 @@
<option value="followers">{{ i18n.ts._visibility.followers }}</option>
<option value="specified">{{ i18n.ts._visibility.specified }}</option>
</MkSelect>
- <MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.localOnly }}</MkSwitch>
+ <MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.disableFederation }}</MkSwitch>
</div>
</MkFolder>
</div>
diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue
index a492a82588..41563c441f 100644
--- a/packages/frontend/src/pages/settings/profile.vue
+++ b/packages/frontend/src/pages/settings/profile.vue
@@ -124,11 +124,11 @@ function saveFields() {
function save() {
os.apiWithDialog('i/update', {
- name: profile.name || null,
- description: profile.description || null,
- location: profile.location || null,
- birthday: profile.birthday || null,
- lang: profile.lang || null,
+ name: profile.name ?? null,
+ description: profile.description ?? null,
+ location: profile.location ?? null,
+ birthday: profile.birthday ?? null,
+ lang: profile.lang ?? null,
isBot: !!profile.isBot,
isCat: !!profile.isCat,
showTimelineReplies: !!profile.showTimelineReplies,
diff --git a/packages/frontend/src/pages/settings/security.vue b/packages/frontend/src/pages/settings/security.vue
index b09c4ffd2f..0cc2df09c5 100644
--- a/packages/frontend/src/pages/settings/security.vue
+++ b/packages/frontend/src/pages/settings/security.vue
@@ -5,11 +5,8 @@
<MkButton primary @click="change()">{{ i18n.ts.changePassword }}</MkButton>
</FormSection>
- <FormSection>
- <template #label>{{ i18n.ts.twoStepAuthentication }}</template>
- <X2fa/>
- </FormSection>
-
+ <X2fa/>
+
<FormSection>
<template #label>{{ i18n.ts.signinHistory }}</template>
<MkPagination :pagination="pagination" disable-auto-load>
@@ -56,18 +53,21 @@ async function change() {
const { canceled: canceled1, result: currentPassword } = await os.inputText({
title: i18n.ts.currentPassword,
type: 'password',
+ autocomplete: 'current-password',
});
if (canceled1) return;
const { canceled: canceled2, result: newPassword } = await os.inputText({
title: i18n.ts.newPassword,
type: 'password',
+ autocomplete: 'new-password',
});
if (canceled2) return;
const { canceled: canceled3, result: newPassword2 } = await os.inputText({
title: i18n.ts.newPasswordRetype,
type: 'password',
+ autocomplete: 'new-password',
});
if (canceled3) return;
@@ -109,7 +109,7 @@ definePageMetadata({
<style lang="scss" scoped>
.timnmucd {
- padding: 16px;
+ padding: 12px;
&:first-child {
border-top-left-radius: 6px;
diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue
index 5d6d01d2ae..511052c424 100644
--- a/packages/frontend/src/pages/tag.vue
+++ b/packages/frontend/src/pages/tag.vue
@@ -2,14 +2,14 @@
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :content-max="800">
- <XNotes class="" :pagination="pagination"/>
+ <MkNotes class="" :pagination="pagination"/>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import { definePageMetadata } from '@/scripts/page-metadata';
const props = defineProps<{
diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue
index f9ad609f56..d982a76d03 100644
--- a/packages/frontend/src/pages/timeline.vue
+++ b/packages/frontend/src/pages/timeline.vue
@@ -8,7 +8,7 @@
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div :class="$style.tl">
- <XTimeline
+ <MkTimeline
ref="tlComponent"
:key="src"
:src="src"
@@ -24,7 +24,7 @@
<script lang="ts" setup>
import { defineAsyncComponent, computed, watch, provide } from 'vue';
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import MkPostForm from '@/components/MkPostForm.vue';
import { scroll } from '@/scripts/scroll';
import * as os from '@/os';
@@ -44,7 +44,7 @@ const keymap = {
't': focus,
};
-const tlComponent = $shallowRef<InstanceType<typeof XTimeline>>();
+const tlComponent = $shallowRef<InstanceType<typeof MkTimeline>>();
const rootEl = $shallowRef<HTMLElement>();
let queue = $ref(0);
diff --git a/packages/frontend/src/pages/user-info.vue b/packages/frontend/src/pages/user-info.vue
index b8ed5787cf..13a06286f6 100644
--- a/packages/frontend/src/pages/user-info.vue
+++ b/packages/frontend/src/pages/user-info.vue
@@ -112,7 +112,7 @@
<MkButton v-if="user.host == null && iAmModerator" primary rounded @click="assignRole"><i class="ti ti-plus"></i> {{ i18n.ts.assign }}</MkButton>
<div v-for="role in info.roles" :key="role.id" :class="$style.roleItem">
- <MkRolePreview :class="$style.role" :role="role"/>
+ <MkRolePreview :class="$style.role" :role="role" :for-moderation="true"/>
<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="unassignRole(role, $event)"><i class="ti ti-x"></i></button>
<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
</div>
diff --git a/packages/frontend/src/pages/user-list-timeline.vue b/packages/frontend/src/pages/user-list-timeline.vue
index 2bfda12a6e..acf7ea9b2c 100644
--- a/packages/frontend/src/pages/user-list-timeline.vue
+++ b/packages/frontend/src/pages/user-list-timeline.vue
@@ -4,7 +4,7 @@
<div ref="rootEl" class="eqqrhokj">
<div v-if="queue > 0" class="new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div class="tl">
- <XTimeline
+ <MkTimeline
ref="tlEl" :key="listId"
class="tl"
src="list"
@@ -19,7 +19,7 @@
<script lang="ts" setup>
import { computed, watch } from 'vue';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import { scroll } from '@/scripts/scroll';
import * as os from '@/os';
import { useRouter } from '@/router';
@@ -34,7 +34,7 @@ const props = defineProps<{
let list = $ref(null);
let queue = $ref(0);
-let tlEl = $shallowRef<InstanceType<typeof XTimeline>>();
+let tlEl = $shallowRef<InstanceType<typeof MkTimeline>>();
let rootEl = $shallowRef<HTMLElement>();
watch(() => props.listId, async () => {
diff --git a/packages/frontend/src/pages/user-tag.vue b/packages/frontend/src/pages/user-tag.vue
new file mode 100644
index 0000000000..fac7593e9c
--- /dev/null
+++ b/packages/frontend/src/pages/user-tag.vue
@@ -0,0 +1,38 @@
+<template>
+<MkStickyContainer>
+ <template #header><MkPageHeader/></template>
+
+ <MkSpacer :content-max="1200">
+ <div class="_gaps_s">
+ <MkUserList :pagination="tagUsers"/>
+ </div>
+ </MkSpacer>
+</MkStickyContainer>
+</template>
+
+<script lang="ts" setup>
+import { computed, watch } from 'vue';
+import * as os from '@/os';
+import MkUserList from '@/components/MkUserList.vue';
+import { definePageMetadata } from '@/scripts/page-metadata';
+
+const props = defineProps<{
+ tag: string;
+}>();
+
+const tagUsers = $computed(() => ({
+ endpoint: 'hashtags/users' as const,
+ limit: 30,
+ params: {
+ tag: props.tag,
+ origin: 'combined',
+ sort: '+follower',
+ },
+}));
+
+definePageMetadata(computed(() => ({
+ title: props.tag,
+ icon: 'ti ti-user-search',
+})));
+</script>
+
diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue
index 66c754c452..441b19440c 100644
--- a/packages/frontend/src/pages/user/home.vue
+++ b/packages/frontend/src/pages/user/home.vue
@@ -100,7 +100,7 @@
<XPhotos :key="user.id" :user="user"/>
<XActivity :key="user.id" :user="user"/>
</template>
- <XNotes :class="$style.tl" :no-gap="true" :pagination="pagination"/>
+ <MkNotes :class="$style.tl" :no-gap="true" :pagination="pagination"/>
</div>
</div>
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
@@ -130,7 +130,7 @@ import { i18n } from '@/i18n';
import { $i } from '@/account';
import { dateString } from '@/filters/date';
import { confetti } from '@/scripts/confetti';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
diff --git a/packages/frontend/src/pages/user/index.timeline.vue b/packages/frontend/src/pages/user/index.timeline.vue
index aae55c5f1c..d8fc253910 100644
--- a/packages/frontend/src/pages/user/index.timeline.vue
+++ b/packages/frontend/src/pages/user/index.timeline.vue
@@ -8,7 +8,7 @@
<option value="files">{{ i18n.ts.withFiles }}</option>
</MkTab>
</template>
- <XNotes :no-gap="true" :pagination="pagination" :class="$style.tl"/>
+ <MkNotes :no-gap="true" :pagination="pagination" :class="$style.tl"/>
</MkStickyContainer>
</MkSpacer>
</template>
@@ -16,7 +16,7 @@
<script lang="ts" setup>
import { ref, computed } from 'vue';
import * as misskey from 'misskey-js';
-import XNotes from '@/components/MkNotes.vue';
+import MkNotes from '@/components/MkNotes.vue';
import MkTab from '@/components/MkTab.vue';
import { i18n } from '@/i18n';
diff --git a/packages/frontend/src/pages/welcome.entrance.a.vue b/packages/frontend/src/pages/welcome.entrance.a.vue
index 05c55fdf31..f62a6461c5 100644
--- a/packages/frontend/src/pages/welcome.entrance.a.vue
+++ b/packages/frontend/src/pages/welcome.entrance.a.vue
@@ -1,18 +1,18 @@
<template>
<div v-if="meta" class="rsqzvsbo">
- <div class="top">
- <MkFeaturedPhotos class="bg"/>
- <XTimeline class="tl"/>
- <div class="shape1"></div>
- <div class="shape2"></div>
- <img src="/client-assets/misskey.svg" class="misskey"/>
- <div class="emojis">
- <MkEmoji :normal="true" :no-style="true" emoji="ðŸ‘"/>
- <MkEmoji :normal="true" :no-style="true" emoji="â¤"/>
- <MkEmoji :normal="true" :no-style="true" emoji="😆"/>
- <MkEmoji :normal="true" :no-style="true" emoji="🎉"/>
- <MkEmoji :normal="true" :no-style="true" emoji="ðŸ®"/>
- </div>
+ <MkFeaturedPhotos class="bg"/>
+ <XTimeline class="tl"/>
+ <div class="shape1"></div>
+ <div class="shape2"></div>
+ <img src="/client-assets/misskey.svg" class="misskey"/>
+ <div class="emojis">
+ <MkEmoji :normal="true" :no-style="true" emoji="ðŸ‘"/>
+ <MkEmoji :normal="true" :no-style="true" emoji="â¤"/>
+ <MkEmoji :normal="true" :no-style="true" emoji="😆"/>
+ <MkEmoji :normal="true" :no-style="true" emoji="🎉"/>
+ <MkEmoji :normal="true" :no-style="true" emoji="ðŸ®"/>
+ </div>
+ <div class="contents">
<div class="main">
<img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
<button class="_button _acrylic menu" @click="showMenu"><i class="ti ti-dots"></i></button>
@@ -26,37 +26,46 @@
<!-- eslint-disable-next-line vue/no-v-html -->
<div class="desc" v-html="meta.description || i18n.ts.headlineMisskey"></div>
</div>
- <div class="action">
- <MkButton inline rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.signup }}</MkButton>
- <MkButton inline rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
+ <div class="action _gaps_s">
+ <MkButton full rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.joinThisServer }}</MkButton>
+ <MkButton full rounded @click="exploreOtherServers()">{{ i18n.ts.exploreOtherServers }}</MkButton>
+ <MkButton full rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
</div>
</div>
</div>
- <div v-if="instances && instances.length > 0" class="federation">
- <MarqueeText :duration="40">
- <MkA v-for="instance in instances" :key="instance.id" :class="$style.federationInstance" :to="`/instance-info/${instance.host}`" behavior="window">
- <!--<MkInstanceCardMini :instance="instance"/>-->
- <img v-if="instance.iconUrl" class="icon" :src="instance.iconUrl" alt=""/>
- <span class="name _monospace">{{ instance.host }}</span>
- </MkA>
- </MarqueeText>
+ <div v-if="instance.policies.ltlAvailable" class="tl">
+ <div class="title">{{ i18n.ts.letsLookAtTimeline }}</div>
+ <div class="body">
+ <MkTimeline src="local"/>
+ </div>
</div>
</div>
+ <div v-if="instances && instances.length > 0" class="federation">
+ <MarqueeText :duration="40">
+ <MkA v-for="instance in instances" :key="instance.id" :class="$style.federationInstance" :to="`/instance-info/${instance.host}`" behavior="window">
+ <!--<MkInstanceCardMini :instance="instance"/>-->
+ <img v-if="instance.iconUrl" class="icon" :src="instance.iconUrl" alt=""/>
+ <span class="name _monospace">{{ instance.host }}</span>
+ </MkA>
+ </MarqueeText>
+ </div>
</div>
</template>
<script lang="ts" setup>
import { } from 'vue';
+import { Instance } from 'misskey-js/built/entities';
import XTimeline from './welcome.timeline.vue';
import MarqueeText from '@/components/MkMarquee.vue';
import XSigninDialog from '@/components/MkSigninDialog.vue';
import XSignupDialog from '@/components/MkSignupDialog.vue';
import MkButton from '@/components/MkButton.vue';
import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import { instanceName } from '@/config';
import * as os from '@/os';
import { i18n } from '@/i18n';
-import { Instance } from 'misskey-js/built/entities';
+import { instance } from '@/instance';
let meta = $ref<Instance>();
let instances = $ref<any[]>();
@@ -105,100 +114,103 @@ function showMenu(ev) {
},
}], ev.currentTarget ?? ev.target);
}
+
+function exploreOtherServers() {
+ // TODO: 言語をよã—ãªã«
+ window.open('https://join.misskey.page/ja-JP/instances', '_blank');
+}
</script>
<style lang="scss" scoped>
.rsqzvsbo {
- > .top {
- display: flex;
- text-align: center;
- min-height: 100vh;
- box-sizing: border-box;
- padding: 16px;
+ > .bg {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 80vw; // 100%ã‹ã‚‰shapeã®å¹…を引ã„ã¦ã„ã‚‹
+ height: 100vh;
+ }
- > .bg {
- position: absolute;
- top: 0;
- right: 0;
- width: 80%; // 100%ã‹ã‚‰shapeã®å¹…を引ã„ã¦ã„ã‚‹
- height: 100%;
+ > .tl {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ right: 64px;
+ margin: auto;
+ padding: 128px 0;
+ width: 500px;
+ height: calc(100% - 256px);
+ overflow: hidden;
+ -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
+ mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
+
+ @media (max-width: 1200px) {
+ display: none;
}
+ }
- > .tl {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 64px;
- margin: auto;
- padding: 128px 0;
- width: 500px;
- height: calc(100% - 256px);
- overflow: hidden;
- -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
- mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
+ > .shape1 {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ background: var(--accent);
+ clip-path: polygon(0% 0%, 45% 0%, 20% 100%, 0% 100%);
+ }
+ > .shape2 {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ background: var(--accent);
+ clip-path: polygon(0% 0%, 25% 0%, 35% 100%, 0% 100%);
+ opacity: 0.5;
+ }
- @media (max-width: 1200px) {
- display: none;
- }
- }
+ > .misskey {
+ position: fixed;
+ top: 42px;
+ left: 42px;
+ width: 140px;
- > .shape1 {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: var(--accent);
- clip-path: polygon(0% 0%, 45% 0%, 20% 100%, 0% 100%);
- }
- > .shape2 {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: var(--accent);
- clip-path: polygon(0% 0%, 25% 0%, 35% 100%, 0% 100%);
- opacity: 0.5;
+ @media (max-width: 450px) {
+ width: 130px;
}
+ }
- > .misskey {
- position: absolute;
- top: 42px;
- left: 42px;
- width: 140px;
+ > .emojis {
+ position: fixed;
+ bottom: 32px;
+ left: 35px;
- @media (max-width: 450px) {
- width: 130px;
- }
+ > * {
+ margin-right: 8px;
}
- > .emojis {
- position: absolute;
- bottom: 32px;
- left: 35px;
+ @media (max-width: 1200px) {
+ display: none;
+ }
+ }
- > * {
- margin-right: 8px;
- }
+ > .contents {
+ position: relative;
+ width: min(430px, calc(100% - 32px));
+ margin-left: 128px;
+ padding: 150px 0 100px 0;
- @media (max-width: 1200px) {
- display: none;
- }
+ @media (max-width: 1200px) {
+ margin: auto;
}
> .main {
position: relative;
- width: min(480px, 100%);
- margin: auto auto auto 128px;
background: var(--panel);
border-radius: var(--radius);
box-shadow: 0 12px 32px rgb(0 0 0 / 25%);
-
- @media (max-width: 1200px) {
- margin: auto;
- }
-
+ text-align: center;
+
> .icon {
width: 85px;
margin-top: -47px;
@@ -247,25 +259,44 @@ function showMenu(ev) {
}
}
- > .federation {
- position: absolute;
- bottom: 16px;
- left: 0;
- right: 0;
- margin: auto;
- background: var(--acrylicPanel);
- -webkit-backdrop-filter: var(--blur, blur(15px));
- backdrop-filter: var(--blur, blur(15px));
- border-radius: 999px;
+ > .tl {
+ position: relative;
+ background: var(--panel);
+ border-radius: var(--radius);
overflow: clip;
- width: 800px;
- padding: 8px 0;
+ box-shadow: 0 12px 32px rgb(0 0 0 / 25%);
+ margin-top: 16px;
+
+ > .title {
+ padding: 12px 16px;
+ border-bottom: solid 1px var(--divider);
+ }
- @media (max-width: 900px) {
- display: none;
+ > .body {
+ height: 350px;
+ overflow: auto;
}
}
}
+
+ > .federation {
+ position: fixed;
+ bottom: 16px;
+ left: 0;
+ right: 0;
+ margin: auto;
+ background: var(--acrylicPanel);
+ -webkit-backdrop-filter: var(--blur, blur(15px));
+ backdrop-filter: var(--blur, blur(15px));
+ border-radius: 999px;
+ overflow: clip;
+ width: 800px;
+ padding: 8px 0;
+
+ @media (max-width: 900px) {
+ display: none;
+ }
+ }
}
</style>
diff --git a/packages/frontend/src/pizzax.ts b/packages/frontend/src/pizzax.ts
index 2ca89b7351..2616a8a1d5 100644
--- a/packages/frontend/src/pizzax.ts
+++ b/packages/frontend/src/pizzax.ts
@@ -48,8 +48,8 @@ export class Storage<T extends StateDef> {
// 簡易的ã«ã‚­ãƒ¥ãƒ¼ã‚¤ãƒ³ã‚°ã—ã¦å æœ‰ãƒ­ãƒƒã‚¯ã¨ã™ã‚‹
private currentIdbJob: Promise<any> = Promise.resolve();
private addIdbSetJob<T>(job: () => Promise<T>) {
- const promise = this.currentIdbJob.then(job, e => {
- console.error('Pizzax failed to save data to idb!', e);
+ const promise = this.currentIdbJob.then(job, err => {
+ console.error('Pizzax failed to save data to idb!', err);
return job();
});
this.currentIdbJob = promise;
@@ -130,22 +130,22 @@ export class Storage<T extends StateDef> {
await defaultStore.ready;
api('i/registry/get-all', { scope: ['client', this.key] })
- .then(kvs => {
- const cache: Partial<T> = {};
- for (const [k, v] of Object.entries(this.def) as [keyof T, T[keyof T]['default']][]) {
- if (v.where === 'account') {
- if (Object.prototype.hasOwnProperty.call(kvs, k)) {
- this.reactiveState[k].value = this.state[k] = (kvs as Partial<T>)[k];
- cache[k] = (kvs as Partial<T>)[k];
- } else {
- this.reactiveState[k].value = this.state[k] = v.default;
+ .then(kvs => {
+ const cache: Partial<T> = {};
+ for (const [k, v] of Object.entries(this.def) as [keyof T, T[keyof T]['default']][]) {
+ if (v.where === 'account') {
+ if (Object.prototype.hasOwnProperty.call(kvs, k)) {
+ this.reactiveState[k].value = this.state[k] = (kvs as Partial<T>)[k];
+ cache[k] = (kvs as Partial<T>)[k];
+ } else {
+ this.reactiveState[k].value = this.state[k] = v.default;
+ }
}
}
- }
- return set(this.registryCacheKeyName, cache);
- })
- .then(() => resolve());
+ return set(this.registryCacheKeyName, cache);
+ })
+ .then(() => resolve());
}, 1);
} else {
resolve();
diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts
index ff380df639..70576688b1 100644
--- a/packages/frontend/src/router.ts
+++ b/packages/frontend/src/router.ts
@@ -198,8 +198,11 @@ export const routes = [{
component: page(() => import('./pages/theme-editor.vue')),
loginRequired: true,
}, {
- path: '/explore/tags/:tag',
- component: page(() => import('./pages/explore.vue')),
+ path: '/roles/:role',
+ component: page(() => import('./pages/role.vue')),
+}, {
+ path: '/user-tags/:tag',
+ component: page(() => import('./pages/user-tag.vue')),
}, {
path: '/explore',
component: page(() => import('./pages/explore.vue')),
@@ -210,6 +213,8 @@ export const routes = [{
query: {
q: 'query',
channel: 'channel',
+ type: 'type',
+ origin: 'origin',
},
}, {
path: '/authorize-follow',
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 48b740f4c3..9c0ff3d1b2 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -9,6 +9,7 @@ import copyToClipboard from '@/scripts/copy-to-clipboard';
import { url } from '@/config';
import { noteActions } from '@/store';
import { miLocalStorage } from '@/local-storage';
+import { getUserMenu } from '@/scripts/get-user-menu';
export function getNoteMenu(props: {
note: misskey.entities.Note;
@@ -99,66 +100,6 @@ export function getNoteMenu(props: {
});
}
- async function clip(): Promise<void> {
- const clips = await os.api('clips/list');
- os.popupMenu([{
- icon: 'ti ti-plus',
- text: i18n.ts.createNew,
- action: async () => {
- const { canceled, result } = await os.form(i18n.ts.createNewClip, {
- name: {
- type: 'string',
- label: i18n.ts.name,
- },
- description: {
- type: 'string',
- required: false,
- multiline: true,
- label: i18n.ts.description,
- },
- isPublic: {
- type: 'boolean',
- label: i18n.ts.public,
- default: false,
- },
- });
- if (canceled) return;
-
- const clip = await os.apiWithDialog('clips/create', result);
-
- claimAchievement('noteClipped1');
- os.apiWithDialog('clips/add-note', { clipId: clip.id, noteId: appearNote.id });
- },
- }, null, ...clips.map(clip => ({
- text: clip.name,
- action: () => {
- claimAchievement('noteClipped1');
- os.promiseDialog(
- os.api('clips/add-note', { clipId: clip.id, noteId: appearNote.id }),
- null,
- async (err) => {
- if (err.id === '734806c4-542c-463a-9311-15c512803965') {
- const confirm = await os.confirm({
- type: 'warning',
- text: i18n.t('confirmToUnclipAlreadyClippedNote', { name: clip.name }),
- });
- if (!confirm.canceled) {
- os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id });
- if (props.currentClipPage?.value.id === clip.id) props.isDeleted.value = true;
- }
- } else {
- os.alert({
- type: 'error',
- text: err.message + '\n' + err.id,
- });
- }
- },
- );
- },
- }))], props.menuButton.value, {
- }).then(focus);
- }
-
async function unclip(): Promise<void> {
os.apiWithDialog('clips/remove-note', { clipId: props.currentClipPage.value.id, noteId: appearNote.id });
props.isDeleted.value = true;
@@ -200,7 +141,7 @@ export function getNoteMenu(props: {
props.translating.value = true;
const res = await os.api('notes/translate', {
noteId: appearNote.id,
- targetLang: miLocalStorage.getItem('lang') || navigator.language,
+ targetLang: miLocalStorage.getItem('lang') ?? navigator.language,
});
props.translating.value = false;
props.translation.value = res;
@@ -240,7 +181,7 @@ export function getNoteMenu(props: {
icon: 'ti ti-external-link',
text: i18n.ts.showOnRemote,
action: () => {
- window.open(appearNote.url || appearNote.uri, '_blank');
+ window.open(appearNote.url ?? appearNote.uri, '_blank');
},
} : undefined,
{
@@ -264,9 +205,67 @@ export function getNoteMenu(props: {
action: () => toggleFavorite(true),
}),
{
+ type: 'parent',
icon: 'ti ti-paperclip',
text: i18n.ts.clip,
- action: () => clip(),
+ children: async () => {
+ const clips = await os.api('clips/list');
+ return [{
+ icon: 'ti ti-plus',
+ text: i18n.ts.createNew,
+ action: async () => {
+ const { canceled, result } = await os.form(i18n.ts.createNewClip, {
+ name: {
+ type: 'string',
+ label: i18n.ts.name,
+ },
+ description: {
+ type: 'string',
+ required: false,
+ multiline: true,
+ label: i18n.ts.description,
+ },
+ isPublic: {
+ type: 'boolean',
+ label: i18n.ts.public,
+ default: false,
+ },
+ });
+ if (canceled) return;
+
+ const clip = await os.apiWithDialog('clips/create', result);
+
+ claimAchievement('noteClipped1');
+ os.apiWithDialog('clips/add-note', { clipId: clip.id, noteId: appearNote.id });
+ },
+ }, null, ...clips.map(clip => ({
+ text: clip.name,
+ action: () => {
+ claimAchievement('noteClipped1');
+ os.promiseDialog(
+ os.api('clips/add-note', { clipId: clip.id, noteId: appearNote.id }),
+ null,
+ async (err) => {
+ if (err.id === '734806c4-542c-463a-9311-15c512803965') {
+ const confirm = await os.confirm({
+ type: 'warning',
+ text: i18n.t('confirmToUnclipAlreadyClippedNote', { name: clip.name }),
+ });
+ if (!confirm.canceled) {
+ os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id });
+ if (props.currentClipPage?.value.id === clip.id) props.isDeleted.value = true;
+ }
+ } else {
+ os.alert({
+ type: 'error',
+ text: err.message + '\n' + err.id,
+ });
+ }
+ },
+ );
+ },
+ }))];
+ },
},
statePromise.then(state => state.isMutedThread ? {
icon: 'ti ti-message-off',
@@ -286,6 +285,15 @@ export function getNoteMenu(props: {
text: i18n.ts.pin,
action: () => togglePin(true),
} : undefined,
+ appearNote.userId !== $i.id ? {
+ type: 'parent',
+ icon: 'ti ti-user',
+ text: i18n.ts.user,
+ children: async () => {
+ const user = await os.api('users/show', { userId: appearNote.userId });
+ return getUserMenu(user);
+ },
+ } : undefined,
/*
...($i.isModerator || $i.isAdmin ? [
null,
@@ -302,7 +310,7 @@ export function getNoteMenu(props: {
icon: 'ti ti-exclamation-circle',
text: i18n.ts.reportAbuse,
action: () => {
- const u = appearNote.url || appearNote.uri || `${url}/notes/${appearNote.id}`;
+ const u = appearNote.url ?? appearNote.uri ?? `${url}/notes/${appearNote.id}`;
os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
user: appearNote.user,
initialComment: `Note: ${u}\n-----\n`,
@@ -344,7 +352,7 @@ export function getNoteMenu(props: {
icon: 'ti ti-external-link',
text: i18n.ts.showOnRemote,
action: () => {
- window.open(appearNote.url || appearNote.uri, '_blank');
+ window.open(appearNote.url ?? appearNote.uri, '_blank');
},
} : undefined]
.filter(x => x !== undefined);
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index 557b257f62..69d0ed085d 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -1,4 +1,5 @@
import { defineAsyncComponent } from 'vue';
+import * as misskey from 'misskey-js';
import { i18n } from '@/i18n';
import copyToClipboard from '@/scripts/copy-to-clipboard';
import { host } from '@/config';
@@ -8,7 +9,7 @@ import { $i, iAmModerator } from '@/account';
import { mainRouter } from '@/router';
import { Router } from '@/nirax';
-export function getUserMenu(user, router: Router = mainRouter) {
+export function getUserMenu(user: misskey.entities.UserDetailed, router: Router = mainRouter) {
const meId = $i ? $i.id : null;
async function pushList() {
@@ -102,6 +103,8 @@ export function getUserMenu(user, router: Router = mainRouter) {
}
async function invalidateFollow() {
+ if (!await getConfirmed(i18n.ts.breakFollowConfirm)) return;
+
os.apiWithDialog('following/invalidate', {
userId: user.id,
}).then(() => {
@@ -113,7 +116,7 @@ export function getUserMenu(user, router: Router = mainRouter) {
icon: 'ti ti-at',
text: i18n.ts.copyUsername,
action: () => {
- copyToClipboard(`@${user.username}@${user.host || host}`);
+ copyToClipboard(`@${user.username}@${user.host ?? host}`);
},
}, {
icon: 'ti ti-info-circle',
@@ -166,12 +169,6 @@ export function getUserMenu(user, router: Router = mainRouter) {
if (iAmModerator) {
menu = menu.concat([null, {
- icon: 'ti ti-user-exclamation',
- text: i18n.ts.moderation,
- action: () => {
- router.push('/user-info/' + user.id + '#moderation');
- },
- }, {
icon: 'ti ti-badges',
text: i18n.ts.roles,
action: async () => {
diff --git a/packages/frontend/src/scripts/get-user-name.ts b/packages/frontend/src/scripts/get-user-name.ts
index d499ea0203..4daf203e06 100644
--- a/packages/frontend/src/scripts/get-user-name.ts
+++ b/packages/frontend/src/scripts/get-user-name.ts
@@ -1,3 +1,3 @@
export default function(user: { name?: string | null, username: string }): string {
- return user.name || user.username;
+ return user.name === '' ? user.username : user.name ?? user.username;
}
diff --git a/packages/frontend/src/scripts/hpml/index.ts b/packages/frontend/src/scripts/hpml/index.ts
index 5c07a08315..587c6a36c8 100644
--- a/packages/frontend/src/scripts/hpml/index.ts
+++ b/packages/frontend/src/scripts/hpml/index.ts
@@ -58,7 +58,7 @@ export class HpmlScope {
constructor(layerdStates: HpmlScope['layerdStates'], name?: HpmlScope['name']) {
this.layerdStates = layerdStates;
- this.name = name || 'anonymous';
+ this.name = name ?? 'anonymous';
}
@autobind
diff --git a/packages/frontend/src/scripts/hpml/type-checker.ts b/packages/frontend/src/scripts/hpml/type-checker.ts
index 24c9ed8bcb..692826fc90 100644
--- a/packages/frontend/src/scripts/hpml/type-checker.ts
+++ b/packages/frontend/src/scripts/hpml/type-checker.ts
@@ -63,7 +63,7 @@ export class HpmlTypeChecker {
@autobind
public getExpectedType(v: Expr, slot: number): Type {
- const def = funcDefs[v.type || ''];
+ const def = funcDefs[v.type ?? ''];
if (def == null) {
throw new Error('Unknown type: ' + v.type);
}
@@ -107,7 +107,7 @@ export class HpmlTypeChecker {
return pageVar.type;
}
- const envVar = envVarsDef[v.value || ''];
+ const envVar = envVarsDef[v.value ?? ''];
if (envVar !== undefined) {
return envVar;
}
diff --git a/packages/frontend/src/scripts/scroll.ts b/packages/frontend/src/scripts/scroll.ts
index e3d9dc00c2..a002f02b5a 100644
--- a/packages/frontend/src/scripts/scroll.ts
+++ b/packages/frontend/src/scripts/scroll.ts
@@ -10,7 +10,7 @@ export function getScrollContainer(el: HTMLElement | null): HTMLElement | null {
}
}
-export function getStickyTop(el: HTMLElement, container: HTMLElement | null = null, top: number = 0) {
+export function getStickyTop(el: HTMLElement, container: HTMLElement | null = null, top = 0) {
if (!el.parentElement) return top;
const data = el.dataset.stickyContainerHeaderHeight;
const newTop = data ? Number(data) + top : top;
@@ -23,14 +23,14 @@ export function getScrollPosition(el: HTMLElement | null): number {
return container == null ? window.scrollY : container.scrollTop;
}
-export function onScrollTop(el: HTMLElement, cb: () => unknown, tolerance: number = 1, once: boolean = false) {
+export function onScrollTop(el: HTMLElement, cb: () => unknown, tolerance = 1, once = false) {
// ã¨ã‚Šã‚ãˆãšè©•価ã—ã¦ã¿ã‚‹
if (isTopVisible(el)) {
cb();
if (once) return null;
}
- const container = getScrollContainer(el) || window;
+ const container = getScrollContainer(el) ?? window;
const onScroll = ev => {
if (!document.body.contains(el)) return;
@@ -45,7 +45,7 @@ export function onScrollTop(el: HTMLElement, cb: () => unknown, tolerance: numbe
return removeListener;
}
-export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance: number = 1, once: boolean = false) {
+export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance = 1, once = false) {
const container = getScrollContainer(el);
// ã¨ã‚Šã‚ãˆãšè©•価ã—ã¦ã¿ã‚‹
@@ -54,7 +54,7 @@ export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance: nu
if (once) return null;
}
- const containerOrWindow = container || window;
+ const containerOrWindow = container ?? window;
const onScroll = ev => {
if (!document.body.contains(el)) return;
if (isBottomVisible(el, 1, container)) {
@@ -104,12 +104,12 @@ export function scrollToBottom(
} else {
window.scroll({
top: (el.scrollHeight - window.innerHeight + getStickyTop(el, container) + (window.innerWidth <= 500 ? 96 : 0)) || 0,
- ...options
+ ...options,
});
}
}
-export function isTopVisible(el: HTMLElement, tolerance: number = 1): boolean {
+export function isTopVisible(el: HTMLElement, tolerance = 1): boolean {
const scrollTop = getScrollPosition(el);
return scrollTop <= tolerance;
}
@@ -124,6 +124,6 @@ export function getBodyScrollHeight() {
return Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
- document.body.clientHeight, document.documentElement.clientHeight
+ document.body.clientHeight, document.documentElement.clientHeight,
);
}
diff --git a/packages/frontend/src/scripts/search.ts b/packages/frontend/src/scripts/search.ts
deleted file mode 100644
index 69f1586b77..0000000000
--- a/packages/frontend/src/scripts/search.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as os from '@/os';
-import { i18n } from '@/i18n';
-import { mainRouter } from '@/router';
-
-export async function search() {
- const { canceled, result: query } = await os.inputText({
- title: i18n.ts.search,
- });
- if (canceled || query == null || query === '') return;
-
- const q = query.trim();
-
- if (q.startsWith('@') && !q.includes(' ')) {
- mainRouter.push(`/${q}`);
- return;
- }
-
- if (q.startsWith('#')) {
- mainRouter.push(`/tags/${encodeURIComponent(q.substr(1))}`);
- return;
- }
-
- // like 2018/03/12
- if (/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}/.test(q.replace(/-/g, '/'))) {
- const date = new Date(q.replace(/-/g, '/'));
-
- // 日付ã—ã‹æŒ‡å®šã•れã¦ãªã„å ´åˆã€ä¾‹ãˆã° 2018/03/12 ãªã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯
- // 2018/03/12 ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を「å«ã‚€ã€çµæžœã«ãªã‚‹ã“ã¨ã‚’期待ã™ã‚‹ã¯ãšãªã®ã§
- // 23時間59分進ã‚ã‚‹(ãã®ã¾ã¾ã ã¨ 2018/03/12 00:00:00 「ã¾ã§ã€ã®
- // çµæžœã«ãªã£ã¦ã—ã¾ã„ã€2018/03/12 ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯å«ã¾ã‚Œãªã„)
- if (q.replace(/-/g, '/').match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/)) {
- date.setHours(23, 59, 59, 999);
- }
-
- // TODO
- //v.$root.$emit('warp', date);
- os.alert({
- icon: 'ti ti-history',
- iconOnly: true, autoClose: true,
- });
- return;
- }
-
- if (q.startsWith('https://')) {
- const promise = os.api('ap/show', {
- uri: q,
- });
-
- os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
-
- const res = await promise;
-
- if (res.type === 'User') {
- mainRouter.push(`/@${res.object.username}@${res.object.host}`);
- } else if (res.type === 'Note') {
- mainRouter.push(`/notes/${res.object.id}`);
- }
-
- return;
- }
-
- mainRouter.push(`/search?q=${encodeURIComponent(q)}`);
-}
diff --git a/packages/frontend/src/scripts/use-document-visibility.ts b/packages/frontend/src/scripts/use-document-visibility.ts
new file mode 100644
index 0000000000..47e91dd937
--- /dev/null
+++ b/packages/frontend/src/scripts/use-document-visibility.ts
@@ -0,0 +1,19 @@
+import { onMounted, onUnmounted, ref, Ref } from 'vue';
+
+export function useDocumentVisibility(): Ref<DocumentVisibilityState> {
+ const visibility = ref(document.visibilityState);
+
+ const onChange = (): void => {
+ visibility.value = document.visibilityState;
+ };
+
+ onMounted(() => {
+ document.addEventListener('visibilitychange', onChange);
+ });
+
+ onUnmounted(() => {
+ document.removeEventListener('visibilitychange', onChange);
+ });
+
+ return visibility;
+}
diff --git a/packages/frontend/src/theme-store.ts b/packages/frontend/src/theme-store.ts
index aa1244665b..580c7da007 100644
--- a/packages/frontend/src/theme-store.ts
+++ b/packages/frontend/src/theme-store.ts
@@ -1,13 +1,13 @@
-import { api } from '@/os';
-import { $i } from '@/account';
import { Theme } from './scripts/theme';
import { miLocalStorage } from './local-storage';
+import { api } from '@/os';
+import { $i } from '@/account';
const lsCacheKey = $i ? `themes:${$i.id}` as const : null;
export function getThemes(): Theme[] {
if ($i == null) return [];
- return JSON.parse(miLocalStorage.getItem(lsCacheKey!) || '[]');
+ return JSON.parse(miLocalStorage.getItem(lsCacheKey!) ?? '[]');
}
export async function fetchThemes(): Promise<void> {
diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue
index 34ddfa1d32..3dfb371d32 100644
--- a/packages/frontend/src/ui/classic.header.vue
+++ b/packages/frontend/src/ui/classic.header.vue
@@ -45,11 +45,11 @@
import { defineAsyncComponent, defineComponent } from 'vue';
import { openInstanceMenu } from './_common_/common';
import { host } from '@/config';
-import { search } from '@/scripts/search';
import * as os from '@/os';
import { navbarItemDef } from '@/navbar';
import { openAccountMenu } from '@/account';
import MkButton from '@/components/MkButton.vue';
+import { mainRouter } from '@/router';
export default defineComponent({
components: {
@@ -103,7 +103,7 @@ export default defineComponent({
},
search() {
- search();
+ mainRouter.push('/search');
},
more(ev) {
diff --git a/packages/frontend/src/ui/classic.sidebar.vue b/packages/frontend/src/ui/classic.sidebar.vue
index a11c2ba10e..6fff233ac5 100644
--- a/packages/frontend/src/ui/classic.sidebar.vue
+++ b/packages/frontend/src/ui/classic.sidebar.vue
@@ -44,12 +44,12 @@
import { defineAsyncComponent, defineComponent } from 'vue';
import { openInstanceMenu } from './_common_/common';
import { host } from '@/config';
-import { search } from '@/scripts/search';
import * as os from '@/os';
import { navbarItemDef } from '@/navbar';
import { openAccountMenu } from '@/account';
import MkButton from '@/components/MkButton.vue';
import { StickySidebar } from '@/scripts/sticky-sidebar';
+import { mainRouter } from '@/router';
//import MisskeyLogo from '@assets/client/misskey.svg';
export default defineComponent({
@@ -120,7 +120,7 @@ export default defineComponent({
},
search() {
- search();
+ mainRouter.push('/search');
},
more(ev) {
diff --git a/packages/frontend/src/ui/classic.vue b/packages/frontend/src/ui/classic.vue
index 92997ffb66..a359463d9b 100644
--- a/packages/frontend/src/ui/classic.vue
+++ b/packages/frontend/src/ui/classic.vue
@@ -125,7 +125,7 @@ function onAiClick(ev) {
if (window.innerWidth < 1024) {
const currentUI = miLocalStorage.getItem('ui');
- miLocalStorage.setItem('ui_temp', currentUI || 'default');
+ miLocalStorage.setItem('ui_temp', currentUI ?? 'default');
miLocalStorage.setItem('ui', 'default');
location.reload();
}
diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue
index ef29b2e72f..be168b4282 100644
--- a/packages/frontend/src/ui/deck.vue
+++ b/packages/frontend/src/ui/deck.vue
@@ -4,7 +4,7 @@
<div :class="$style.main">
<XStatusBars/>
- <div ref="columnsEl" :class="[$style.columns, deckStore.reactiveState.columnAlign.value]" @contextmenu.self.prevent="onContextmenu">
+ <div ref="columnsEl" :class="[$style.columns, deckStore.reactiveState.columnAlign.value, { [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu">
<template v-for="ids in layout">
<!-- sectionを利用ã—ã¦ã„ã‚‹ã®ã¯ã€deck.vueå´ã§columnã«å¯¾ã—ã¦first-of-typeを効ã‹ã›ã‚‹ãŸã‚ -->
<section
@@ -98,6 +98,7 @@ import { $i } from '@/account';
import { i18n } from '@/i18n';
import { mainRouter } from '@/router';
import { unisonReload } from '@/scripts/unison-reload';
+import { deviceKind } from '@/scripts/device-kind';
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
mainRouter.navHook = (path, flag): boolean => {
@@ -115,6 +116,7 @@ window.addEventListener('resize', () => {
isMobile.value = window.innerWidth <= 500;
});
+const snapScroll = deviceKind === 'smartphone' || deviceKind === 'tablet';
const drawerMenuShowing = ref(false);
const route = 'TODO';
@@ -297,9 +299,14 @@ async function deleteProfile() {
margin-right: auto;
}
}
+
+ &.snapScroll {
+ scroll-snap-type: x mandatory;
+ }
}
.column {
+ scroll-snap-align: start;
flex-shrink: 0;
border-right: solid var(--deckDividerThickness) var(--deckDivider);
diff --git a/packages/frontend/src/ui/deck/antenna-column.vue b/packages/frontend/src/ui/deck/antenna-column.vue
index 4c69c8e8e8..76a8b6e760 100644
--- a/packages/frontend/src/ui/deck/antenna-column.vue
+++ b/packages/frontend/src/ui/deck/antenna-column.vue
@@ -4,7 +4,7 @@
<i class="ti ti-antenna"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
- <XTimeline v-if="column.antennaId" ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => emit('loaded')"/>
+ <MkTimeline v-if="column.antennaId" ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => emit('loaded')"/>
</XColumn>
</template>
@@ -12,7 +12,7 @@
import { onMounted } from 'vue';
import XColumn from './column.vue';
import { updateColumn, Column } from './deck-store';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
@@ -26,7 +26,7 @@ const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
-let timeline = $shallowRef<InstanceType<typeof XTimeline>>();
+let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
onMounted(() => {
if (props.column.antennaId == null) {
diff --git a/packages/frontend/src/ui/deck/channel-column.vue b/packages/frontend/src/ui/deck/channel-column.vue
index 169d2c4056..4c6b41e42e 100644
--- a/packages/frontend/src/ui/deck/channel-column.vue
+++ b/packages/frontend/src/ui/deck/channel-column.vue
@@ -8,7 +8,7 @@
<div style="padding: 8px; text-align: center;">
<MkButton primary gradate rounded inline @click="post"><i class="ti ti-pencil"></i></MkButton>
</div>
- <XTimeline ref="timeline" src="channel" :channel="column.channelId" @after="() => emit('loaded')"/>
+ <MkTimeline ref="timeline" src="channel" :channel="column.channelId" @after="() => emit('loaded')"/>
</template>
</XColumn>
</template>
@@ -17,7 +17,7 @@
import { } from 'vue';
import XColumn from './column.vue';
import { updateColumn, Column } from './deck-store';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
@@ -32,7 +32,7 @@ const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
-let timeline = $shallowRef<InstanceType<typeof XTimeline>>();
+let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
if (props.column.channelId == null) {
setChannel();
diff --git a/packages/frontend/src/ui/deck/direct-column.vue b/packages/frontend/src/ui/deck/direct-column.vue
index 75b018cacd..15b76c4d92 100644
--- a/packages/frontend/src/ui/deck/direct-column.vue
+++ b/packages/frontend/src/ui/deck/direct-column.vue
@@ -2,15 +2,15 @@
<XColumn :column="column" :is-stacked="isStacked" @parent-focus="$event => emit('parent-focus', $event)">
<template #header><i class="ti ti-mail" style="margin-right: 8px;"></i>{{ column.name }}</template>
- <XNotes :pagination="pagination"/>
+ <MkNotes :pagination="pagination"/>
</XColumn>
</template>
<script lang="ts" setup>
import { } from 'vue';
import XColumn from './column.vue';
-import XNotes from '@/components/MkNotes.vue';
import { Column } from './deck-store';
+import MkNotes from '@/components/MkNotes.vue';
defineProps<{
column: Column;
diff --git a/packages/frontend/src/ui/deck/list-column.vue b/packages/frontend/src/ui/deck/list-column.vue
index 58633e5672..352c1d246a 100644
--- a/packages/frontend/src/ui/deck/list-column.vue
+++ b/packages/frontend/src/ui/deck/list-column.vue
@@ -4,7 +4,7 @@
<i class="ti ti-list"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
- <XTimeline v-if="column.listId" ref="timeline" src="list" :list="column.listId" @after="() => emit('loaded')"/>
+ <MkTimeline v-if="column.listId" ref="timeline" src="list" :list="column.listId" @after="() => emit('loaded')"/>
</XColumn>
</template>
@@ -12,7 +12,7 @@
import { } from 'vue';
import XColumn from './column.vue';
import { updateColumn, Column } from './deck-store';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import * as os from '@/os';
import { i18n } from '@/i18n';
@@ -26,7 +26,7 @@ const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
-let timeline = $shallowRef<InstanceType<typeof XTimeline>>();
+let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();
if (props.column.listId == null) {
setList();
diff --git a/packages/frontend/src/ui/deck/mentions-column.vue b/packages/frontend/src/ui/deck/mentions-column.vue
index 16962956a0..852d7a8f7e 100644
--- a/packages/frontend/src/ui/deck/mentions-column.vue
+++ b/packages/frontend/src/ui/deck/mentions-column.vue
@@ -2,15 +2,15 @@
<XColumn :column="column" :is-stacked="isStacked" @parent-focus="$event => emit('parent-focus', $event)">
<template #header><i class="ti ti-at" style="margin-right: 8px;"></i>{{ column.name }}</template>
- <XNotes :pagination="pagination"/>
+ <MkNotes :pagination="pagination"/>
</XColumn>
</template>
<script lang="ts" setup>
import { } from 'vue';
import XColumn from './column.vue';
-import XNotes from '@/components/MkNotes.vue';
import { Column } from './deck-store';
+import MkNotes from '@/components/MkNotes.vue';
defineProps<{
column: Column;
diff --git a/packages/frontend/src/ui/deck/tl-column.vue b/packages/frontend/src/ui/deck/tl-column.vue
index 8b1b920fa8..a947e27e57 100644
--- a/packages/frontend/src/ui/deck/tl-column.vue
+++ b/packages/frontend/src/ui/deck/tl-column.vue
@@ -15,7 +15,7 @@
</p>
<p :class="$style.disabledDescription">{{ $t('disabled-timeline.description') }}</p>
</div>
- <XTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl" @after="() => emit('loaded')"/>
+ <MkTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl" @after="() => emit('loaded')"/>
</XColumn>
</template>
@@ -23,7 +23,7 @@
import { onMounted } from 'vue';
import XColumn from './column.vue';
import { removeColumn, updateColumn, Column } from './deck-store';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import * as os from '@/os';
import { $i } from '@/account';
import { i18n } from '@/i18n';
diff --git a/packages/frontend/src/ui/visitor/a.vue b/packages/frontend/src/ui/visitor/a.vue
index 9494b1b705..023b7fdb94 100644
--- a/packages/frontend/src/ui/visitor/a.vue
+++ b/packages/frontend/src/ui/visitor/a.vue
@@ -40,7 +40,6 @@
import { defineComponent } from 'vue';
import XHeader from './header.vue';
import { host, instanceName } from '@/config';
-import { search } from '@/scripts/search';
import * as os from '@/os';
import MkButton from '@/components/MkButton.vue';
import { ColdDeviceStorage } from '@/store';
@@ -77,7 +76,9 @@ export default defineComponent({
if (ColdDeviceStorage.get('syncDeviceDarkMode')) return;
this.$store.set('darkMode', !this.$store.state.darkMode);
},
- 's': search,
+ 's': () => {
+ mainRouter.push('/search');
+ },
'h|/': this.help,
};
},
diff --git a/packages/frontend/src/ui/visitor/b.vue b/packages/frontend/src/ui/visitor/b.vue
index e36f36f153..e2168768e8 100644
--- a/packages/frontend/src/ui/visitor/b.vue
+++ b/packages/frontend/src/ui/visitor/b.vue
@@ -11,7 +11,10 @@
<div class="contents">
<XHeader v-if="!root" class="header"/>
- <main style="container-type: inline-size;">
+ <main v-if="!root" style="container-type: inline-size;">
+ <RouterView/>
+ </main>
+ <main v-else>
<RouterView/>
</main>
<div v-if="!root" class="powered-by">
@@ -55,7 +58,6 @@ import { ComputedRef, onMounted, provide } from 'vue';
import XHeader from './header.vue';
import XKanban from './kanban.vue';
import { host, instanceName } from '@/config';
-import { search } from '@/scripts/search';
import * as os from '@/os';
import { instance } from '@/instance';
import XSigninDialog from '@/components/MkSigninDialog.vue';
@@ -94,7 +96,9 @@ const keymap = $computed(() => {
if (ColdDeviceStorage.get('syncDeviceDarkMode')) return;
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
- 's': search,
+ 's': () => {
+ mainRouter.push('/search');
+ },
};
});
diff --git a/packages/frontend/src/ui/visitor/header.vue b/packages/frontend/src/ui/visitor/header.vue
index 2647d0e62a..aaa7e77e90 100644
--- a/packages/frontend/src/ui/visitor/header.vue
+++ b/packages/frontend/src/ui/visitor/header.vue
@@ -27,7 +27,7 @@ import XSigninDialog from '@/components/MkSigninDialog.vue';
import XSignupDialog from '@/components/MkSignupDialog.vue';
import * as os from '@/os';
import { instance } from '@/instance';
-import { search } from '@/scripts/search';
+import { mainRouter } from '@/router';
export default defineComponent({
data() {
@@ -55,7 +55,9 @@ export default defineComponent({
}, {}, 'closed');
},
- search,
+ search() {
+ mainRouter.push('/search');
+ },
},
});
</script>
diff --git a/packages/frontend/src/widgets/WidgetOnlineUsers.vue b/packages/frontend/src/widgets/WidgetOnlineUsers.vue
index a096cc8fe8..7949fc4a93 100644
--- a/packages/frontend/src/widgets/WidgetOnlineUsers.vue
+++ b/packages/frontend/src/widgets/WidgetOnlineUsers.vue
@@ -1,7 +1,7 @@
<template>
<div class="mkw-onlineUsers data-cy-mkw-onlineUsers" :class="{ _panel: !widgetProps.transparent, pad: !widgetProps.transparent }">
<I18n v-if="onlineUsersCount" :src="i18n.ts.onlineUsersCount" text-tag="span" class="text">
- <template #n><b>{{ onlineUsersCount }}</b></template>
+ <template #n><b>{{ number(onlineUsersCount) }}</b></template>
</I18n>
</div>
</template>
@@ -13,6 +13,7 @@ import { GetFormResultType } from '@/scripts/form';
import * as os from '@/os';
import { useInterval } from '@/scripts/use-interval';
import { i18n } from '@/i18n';
+import number from '@/filters/number';
const name = 'onlineUsers';
diff --git a/packages/frontend/src/widgets/WidgetTimeline.vue b/packages/frontend/src/widgets/WidgetTimeline.vue
index fde7048b00..d6be6532a6 100644
--- a/packages/frontend/src/widgets/WidgetTimeline.vue
+++ b/packages/frontend/src/widgets/WidgetTimeline.vue
@@ -16,7 +16,7 @@
</template>
<div>
- <XTimeline :key="widgetProps.src === 'list' ? `list:${widgetProps.list.id}` : widgetProps.src === 'antenna' ? `antenna:${widgetProps.antenna.id}` : widgetProps.src" :src="widgetProps.src" :list="widgetProps.list ? widgetProps.list.id : null" :antenna="widgetProps.antenna ? widgetProps.antenna.id : null"/>
+ <MkTimeline :key="widgetProps.src === 'list' ? `list:${widgetProps.list.id}` : widgetProps.src === 'antenna' ? `antenna:${widgetProps.antenna.id}` : widgetProps.src" :src="widgetProps.src" :list="widgetProps.list ? widgetProps.list.id : null" :antenna="widgetProps.antenna ? widgetProps.antenna.id : null"/>
</div>
</MkContainer>
</template>
@@ -27,7 +27,7 @@ import { useWidgetPropsManager, Widget, WidgetComponentExpose } from './widget';
import { GetFormResultType } from '@/scripts/form';
import * as os from '@/os';
import MkContainer from '@/components/MkContainer.vue';
-import XTimeline from '@/components/MkTimeline.vue';
+import MkTimeline from '@/components/MkTimeline.vue';
import { i18n } from '@/i18n';
const name = 'timeline';
diff --git a/packages/shared/.eslintrc.js b/packages/shared/.eslintrc.js
index 6d38a9fb9f..7c979a93dc 100644
--- a/packages/shared/.eslintrc.js
+++ b/packages/shared/.eslintrc.js
@@ -77,6 +77,17 @@ module.exports = {
'@typescript-eslint/prefer-nullish-coalescing': [
'error',
],
+ '@typescript-eslint/naming-convention': [
+ 'error',
+ {
+ "selector": "typeLike",
+ "format": ["PascalCase"]
+ },
+ {
+ "selector": "typeParameter",
+ "format": []
+ }
+ ],
'import/no-unresolved': ['off'],
'import/no-default-export': ['warn'],
'import/order': ['warn', {
diff --git a/packages/sw/package.json b/packages/sw/package.json
index 4de260fcfc..7fab90a243 100644
--- a/packages/sw/package.json
+++ b/packages/sw/package.json
@@ -14,9 +14,9 @@
"misskey-js": "0.0.15"
},
"devDependencies": {
- "@typescript-eslint/parser": "5.51.0",
+ "@typescript-eslint/parser": "5.52.0",
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.62",
- "eslint": "8.33.0",
+ "eslint": "8.34.0",
"eslint-plugin-import": "2.27.5",
"typescript": "4.9.5"
}
diff --git a/packages/sw/src/scripts/get-user-name.ts b/packages/sw/src/scripts/get-user-name.ts
index ccc38c298e..4daf203e06 100644
--- a/packages/sw/src/scripts/get-user-name.ts
+++ b/packages/sw/src/scripts/get-user-name.ts
@@ -1,7 +1,3 @@
export default function(user: { name?: string | null, username: string }): string {
- // Show username if name is empty.
- // XXX: typescript-eslint has no configuration to allow using `||` against string.
- // https://github.com/typescript-eslint/typescript-eslint/issues/4906
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- return user.name || user.username;
+ return user.name === '' ? user.username : user.name ?? user.username;
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b5e52ef9d2..6273952eab 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,11 +11,11 @@ importers:
'@tensorflow/tfjs-core': 4.2.0
'@types/gulp': 4.0.10
'@types/gulp-rename': 2.0.1
- '@typescript-eslint/eslint-plugin': 5.51.0
- '@typescript-eslint/parser': 5.51.0
+ '@typescript-eslint/eslint-plugin': 5.52.0
+ '@typescript-eslint/parser': 5.52.0
cross-env: 7.0.3
- cypress: 12.5.1
- eslint: 8.33.0
+ cypress: 12.6.0
+ eslint: 8.34.0
execa: 5.1.1
gulp: 4.0.2
gulp-cssnano: 2.1.3
@@ -23,7 +23,7 @@ importers:
gulp-replace: 1.1.4
gulp-terser: 2.1.0
js-yaml: 4.1.0
- start-server-and-test: 1.15.3
+ start-server-and-test: 1.15.4
typescript: 4.9.5
dependencies:
execa: 5.1.1
@@ -39,35 +39,46 @@ importers:
devDependencies:
'@types/gulp': 4.0.10
'@types/gulp-rename': 2.0.1
- '@typescript-eslint/eslint-plugin': 5.51.0_b635kmla6dsb4frxfihkw4m47e
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/eslint-plugin': 5.52.0_6cfvjsbua5ptj65675bqcn6oza
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
cross-env: 7.0.3
- cypress: 12.5.1
- eslint: 8.33.0
- start-server-and-test: 1.15.3
+ cypress: 12.6.0
+ eslint: 8.34.0
+ start-server-and-test: 1.15.4
packages/backend:
specifiers:
- '@bull-board/api': 4.11.1
- '@bull-board/fastify': 4.11.1
- '@bull-board/ui': 4.11.1
+ '@bull-board/api': 4.12.1
+ '@bull-board/fastify': 4.12.1
+ '@bull-board/ui': 4.12.1
'@discordapp/twemoji': 14.0.2
'@fastify/accepts': 4.1.0
'@fastify/cookie': 8.3.0
'@fastify/cors': 8.2.0
'@fastify/http-proxy': 8.4.0
- '@fastify/multipart': 7.4.0
- '@fastify/static': 6.8.0
+ '@fastify/multipart': 7.4.1
+ '@fastify/static': 6.9.0
'@fastify/view': 7.4.1
- '@jest/globals': 29.4.2
- '@nestjs/common': 9.3.7
- '@nestjs/core': 9.3.7
- '@nestjs/testing': 9.3.7
+ '@jest/globals': 29.4.3
+ '@nestjs/common': 9.3.9
+ '@nestjs/core': 9.3.9
+ '@nestjs/testing': 9.3.9
'@peertube/http-signature': 1.7.0
'@redocly/openapi-core': 1.0.0-beta.123
'@sinonjs/fake-timers': 10.0.2
- '@swc/cli': 0.1.61
- '@swc/core': 1.3.34
+ '@swc/cli': 0.1.62
+ '@swc/core': 1.3.36
+ '@swc/core-android-arm64': ^1.3.11
+ '@swc/core-darwin-arm64': ^1.3.36
+ '@swc/core-darwin-x64': ^1.3.36
+ '@swc/core-linux-arm-gnueabihf': ^1.3.36
+ '@swc/core-linux-arm64-gnu': ^1.3.36
+ '@swc/core-linux-arm64-musl': ^1.3.36
+ '@swc/core-linux-x64-gnu': ^1.3.36
+ '@swc/core-linux-x64-musl': ^1.3.36
+ '@swc/core-win32-arm64-msvc': ^1.3.36
+ '@swc/core-win32-ia32-msvc': ^1.3.36
+ '@swc/core-win32-x64-msvc': ^1.3.36
'@swc/jest': 0.2.24
'@tensorflow/tfjs': 4.2.0
'@tensorflow/tfjs-node': 4.2.0
@@ -87,7 +98,7 @@ importers:
'@types/jsonld': 1.5.8
'@types/jsrsasign': 10.5.5
'@types/mime-types': 2.1.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/node-fetch': 3.0.3
'@types/nodemailer': 6.4.7
'@types/oauth': 0.9.1
@@ -103,7 +114,6 @@ importers:
'@types/semver': 7.3.13
'@types/sharp': 0.31.1
'@types/sinonjs__fake-timers': 8.1.2
- '@types/speakeasy': 2.0.7
'@types/tinycolor2': 1.4.3
'@types/tmp': 0.2.3
'@types/unzipper': 0.10.5
@@ -112,16 +122,16 @@ importers:
'@types/web-push': 3.3.2
'@types/websocket': 1.0.5
'@types/ws': 8.5.4
- '@typescript-eslint/eslint-plugin': 5.51.0
- '@typescript-eslint/parser': 5.51.0
+ '@typescript-eslint/eslint-plugin': 5.52.0
+ '@typescript-eslint/parser': 5.52.0
accepts: 1.3.8
ajv: 8.12.0
archiver: 5.3.1
autwh: 0.1.0
- aws-sdk: 2.1295.0
+ aws-sdk: 2.1318.0
bcryptjs: 2.4.3
- blurhash: 2.0.4
- bull: 4.10.3
+ blurhash: 2.0.5
+ bull: 4.10.4
cacheable-lookup: 6.1.0
cbor: 8.1.0
chalk: 5.2.0
@@ -134,21 +144,22 @@ importers:
date-fns: 2.29.3
deep-email-validator: 0.1.21
escape-regexp: 0.0.1
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-plugin-import: 2.27.5
execa: 6.1.0
- fastify: 4.12.0
+ fastify: 4.13.0
feed: 4.2.2
- file-type: 18.2.0
+ file-type: 18.2.1
fluent-ffmpeg: 2.1.2
form-data: 4.0.0
got: 12.5.3
+ happy-dom: ^8.7.0
hpagent: 1.2.0
ioredis: 4.28.5
ip-cidr: 3.1.0
is-svg: 4.3.2
- jest: 29.4.2
- jest-mock: 29.4.2
+ jest: 29.4.3
+ jest-mock: 29.4.3
js-yaml: 4.1.0
jsdom: 21.1.0
json5: 2.2.3
@@ -164,6 +175,7 @@ importers:
nsfwjs: 2.4.2
oauth: 0.10.0
os-utils: 0.0.14
+ otpauth: ^9.0.2
parse5: 7.1.2
pg: 8.9.0
private-ip: 3.0.0
@@ -183,15 +195,14 @@ importers:
rss-parser: 3.12.0
rxjs: 7.8.0
s-age: 1.1.2
- sanitize-html: 2.9.0
+ sanitize-html: 2.10.0
seedrandom: 3.0.5
semver: 7.3.8
sharp: 0.31.3
- speakeasy: 2.0.0
strict-event-emitter-types: 2.0.0
stringz: 2.1.0
summaly: github:misskey-dev/summaly
- systeminformation: 5.17.8
+ systeminformation: 5.17.9
tinycolor2: 1.6.0
tmp: 0.2.1
tsc-alias: 1.8.2
@@ -205,33 +216,35 @@ importers:
vary: 1.1.2
web-push: 3.5.0
websocket: 1.0.34
- ws: 8.12.0
+ ws: 8.12.1
xev: 3.0.2
dependencies:
- '@bull-board/api': 4.11.1
- '@bull-board/fastify': 4.11.1
- '@bull-board/ui': 4.11.1
+ '@bull-board/api': 4.12.1
+ '@bull-board/fastify': 4.12.1
+ '@bull-board/ui': 4.12.1
'@discordapp/twemoji': 14.0.2
'@fastify/accepts': 4.1.0
'@fastify/cookie': 8.3.0
'@fastify/cors': 8.2.0
'@fastify/http-proxy': 8.4.0
- '@fastify/multipart': 7.4.0
- '@fastify/static': 6.8.0
+ '@fastify/multipart': 7.4.1
+ '@fastify/static': 6.9.0
'@fastify/view': 7.4.1
- '@nestjs/common': 9.3.7_mnr6j2del53muneqly5h4y27ai
- '@nestjs/core': 9.3.7_ojttuksvundfk3amlyo674va74
- '@nestjs/testing': 9.3.7_zmctrozi6xxh3beaccl6ebop6u
+ '@nestjs/common': 9.3.9_mnr6j2del53muneqly5h4y27ai
+ '@nestjs/core': 9.3.9_jrq2rdgfp2sx67wmylmrqliwxe
+ '@nestjs/testing': 9.3.9_77foi4w27ghy47yutmnzv7krjy
'@peertube/http-signature': 1.7.0
'@sinonjs/fake-timers': 10.0.2
+ '@swc/cli': 0.1.62_wyduggqpvtv2oy5nc7cgtozgpy
+ '@swc/core': 1.3.36
accepts: 1.3.8
ajv: 8.12.0
archiver: 5.3.1
autwh: 0.1.0
- aws-sdk: 2.1295.0
+ aws-sdk: 2.1318.0
bcryptjs: 2.4.3
- blurhash: 2.0.4
- bull: 4.10.3
+ blurhash: 2.0.5
+ bull: 4.10.4
cacheable-lookup: 6.1.0
cbor: 8.1.0
chalk: 5.2.0
@@ -243,12 +256,13 @@ importers:
date-fns: 2.29.3
deep-email-validator: 0.1.21
escape-regexp: 0.0.1
- fastify: 4.12.0
+ fastify: 4.13.0
feed: 4.2.2
- file-type: 18.2.0
+ file-type: 18.2.1
fluent-ffmpeg: 2.1.2
form-data: 4.0.0
got: 12.5.3
+ happy-dom: 8.7.0
hpagent: 1.2.0
ioredis: 4.28.5
ip-cidr: 3.1.0
@@ -268,6 +282,7 @@ importers:
nsfwjs: 2.4.2_@tensorflow+tfjs@4.2.0
oauth: 0.10.0
os-utils: 0.0.14
+ otpauth: 9.0.2
parse5: 7.1.2
pg: 8.9.0
private-ip: 3.0.0
@@ -287,15 +302,14 @@ importers:
rss-parser: 3.12.0
rxjs: 7.8.0
s-age: 1.1.2
- sanitize-html: 2.9.0
+ sanitize-html: 2.10.0
seedrandom: 3.0.5
semver: 7.3.8
sharp: 0.31.3
- speakeasy: 2.0.0
strict-event-emitter-types: 2.0.0
stringz: 2.1.0
- summaly: github.com/misskey-dev/summaly/5684f116c92f1fd122badc7aee062494bdb43b36
- systeminformation: 5.17.8
+ summaly: github.com/misskey-dev/summaly/51f3870e1ff5e0b22102e804112b10cb72f3c494
+ systeminformation: 5.17.9
tinycolor2: 1.6.0
tmp: 0.2.1
tsc-alias: 1.8.2
@@ -309,17 +323,26 @@ importers:
vary: 1.1.2
web-push: 3.5.0
websocket: 1.0.34
- ws: 8.12.0
+ ws: 8.12.1
xev: 3.0.2
optionalDependencies:
+ '@swc/core-android-arm64': 1.3.11
+ '@swc/core-darwin-arm64': 1.3.36
+ '@swc/core-darwin-x64': 1.3.36
+ '@swc/core-linux-arm-gnueabihf': 1.3.36
+ '@swc/core-linux-arm64-gnu': 1.3.36
+ '@swc/core-linux-arm64-musl': 1.3.36
+ '@swc/core-linux-x64-gnu': 1.3.36
+ '@swc/core-linux-x64-musl': 1.3.36
+ '@swc/core-win32-arm64-msvc': 1.3.36
+ '@swc/core-win32-ia32-msvc': 1.3.36
+ '@swc/core-win32-x64-msvc': 1.3.36
'@tensorflow/tfjs': 4.2.0_seedrandom@3.0.5
'@tensorflow/tfjs-node': 4.2.0_seedrandom@3.0.5
devDependencies:
- '@jest/globals': 29.4.2
+ '@jest/globals': 29.4.3
'@redocly/openapi-core': 1.0.0-beta.123
- '@swc/cli': 0.1.61_nh7rjdlljrxbrljvydz3oxxjt4
- '@swc/core': 1.3.34
- '@swc/jest': 0.2.24_@swc+core@1.3.34
+ '@swc/jest': 0.2.24_@swc+core@1.3.36
'@types/accepts': 1.3.5
'@types/archiver': 5.3.1
'@types/bcryptjs': 2.4.2
@@ -336,7 +359,7 @@ importers:
'@types/jsonld': 1.5.8
'@types/jsrsasign': 10.5.5
'@types/mime-types': 2.1.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/node-fetch': 3.0.3
'@types/nodemailer': 6.4.7
'@types/oauth': 0.9.1
@@ -352,7 +375,6 @@ importers:
'@types/semver': 7.3.13
'@types/sharp': 0.31.1
'@types/sinonjs__fake-timers': 8.1.2
- '@types/speakeasy': 2.0.7
'@types/tinycolor2': 1.4.3
'@types/tmp': 0.2.3
'@types/unzipper': 0.10.5
@@ -361,14 +383,14 @@ importers:
'@types/web-push': 3.3.2
'@types/websocket': 1.0.5
'@types/ws': 8.5.4
- '@typescript-eslint/eslint-plugin': 5.51.0_b635kmla6dsb4frxfihkw4m47e
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/eslint-plugin': 5.52.0_6cfvjsbua5ptj65675bqcn6oza
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
cross-env: 7.0.3
- eslint: 8.33.0
- eslint-plugin-import: 2.27.5_yzj2n2b43wonjwaifya6xmk2zy
+ eslint: 8.34.0
+ eslint-plugin-import: 2.27.5_mcvs2y73sfmcxqzpjj5lr7a2m4
execa: 6.1.0
- jest: 29.4.2_@types+node@18.13.0
- jest-mock: 29.4.2
+ jest: 29.4.3_@types+node@18.14.0
+ jest-mock: 29.4.3
packages/frontend:
specifiers:
@@ -383,7 +405,7 @@ importers:
'@types/gulp': 4.0.10
'@types/gulp-rename': 2.0.1
'@types/matter-js': 0.18.2
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/punycode': 2.1.0
'@types/sanitize-html': 2.8.0
'@types/seedrandom': 3.0.4
@@ -392,18 +414,18 @@ importers:
'@types/uuid': 9.0.0
'@types/websocket': 1.0.5
'@types/ws': 8.5.4
- '@typescript-eslint/eslint-plugin': 5.51.0
- '@typescript-eslint/parser': 5.51.0
+ '@typescript-eslint/eslint-plugin': 5.52.0
+ '@typescript-eslint/parser': 5.52.0
'@vitejs/plugin-vue': 4.0.0
'@vue/compiler-sfc': 3.2.47
'@vue/runtime-core': 3.2.47
autobind-decorator: 2.4.0
autosize: 5.0.2
- blurhash: 2.0.4
+ blurhash: 2.0.5
broadcast-channel: 4.20.2
- browser-image-resizer: git+https://github.com/misskey-dev/browser-image-resizer#v2.2.1-misskey.3
+ browser-image-resizer: github:misskey-dev/browser-image-resizer#v2.2.1-misskey.3
canvas-confetti: 1.6.0
- chart.js: 4.2.0
+ chart.js: 4.2.1
chartjs-adapter-date-fns: 3.0.0
chartjs-chart-matrix: 2.0.1
chartjs-plugin-gradient: 0.6.1
@@ -411,10 +433,10 @@ importers:
compare-versions: 5.0.1
cropperjs: 2.0.0-beta.2
cross-env: 7.0.3
- cypress: 12.5.1
+ cypress: 12.6.0
date-fns: 2.29.3
escape-regexp: 0.0.1
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-plugin-import: 2.27.5
eslint-plugin-vue: 9.9.0
eventemitter3: 5.0.0
@@ -423,7 +445,7 @@ importers:
insert-text-at-cursor: 0.3.0
is-file-animated: 1.0.2
json5: 2.2.3
- matter-js: 0.18.0
+ matter-js: 0.19.0
mfm-js: 0.23.3
misskey-js: 0.0.15
photoswipe: 5.3.5
@@ -431,14 +453,13 @@ importers:
punycode: 2.3.0
querystring: 0.2.1
rndstr: 1.0.0
- rollup: 3.14.0
+ rollup: 3.17.2
s-age: 1.1.2
- sanitize-html: 2.9.0
- sass: 1.58.0
+ sanitize-html: 2.10.0
+ sass: 1.58.3
seedrandom: 3.0.5
- start-server-and-test: 1.15.3
+ start-server-and-test: 1.15.4
strict-event-emitter-types: 2.0.0
- stringz: 2.1.0
syuilo-password-strength: 0.0.1
textarea-caret: 3.1.0
three: 0.149.0
@@ -450,33 +471,33 @@ importers:
typescript: 4.9.5
uuid: 9.0.0
vanilla-tilt: 1.8.0
- vite: 4.1.1
+ vite: 4.1.2
vue: 3.2.47
vue-eslint-parser: 9.1.0
vue-plyr: 7.0.0
vue-prism-editor: 2.0.0-alpha.2
- vue-tsc: 1.0.24
+ vue-tsc: 1.1.4
vuedraggable: next
dependencies:
'@discordapp/twemoji': 14.0.2
- '@rollup/plugin-alias': 4.0.3_rollup@3.14.0
- '@rollup/plugin-json': 6.0.0_rollup@3.14.0
- '@rollup/pluginutils': 5.0.2_rollup@3.14.0
+ '@rollup/plugin-alias': 4.0.3_rollup@3.17.2
+ '@rollup/plugin-json': 6.0.0_rollup@3.17.2
+ '@rollup/pluginutils': 5.0.2_rollup@3.17.2
'@syuilo/aiscript': 0.12.4
'@tabler/icons-webfont': 2.2.0
- '@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.47
+ '@vitejs/plugin-vue': 4.0.0_vite@4.1.2+vue@3.2.47
'@vue/compiler-sfc': 3.2.47
autobind-decorator: 2.4.0
autosize: 5.0.2
- blurhash: 2.0.4
+ blurhash: 2.0.5
broadcast-channel: 4.20.2
browser-image-resizer: github.com/misskey-dev/browser-image-resizer/0227e860621e55cbed0aabe6dc601096a7748c4a
canvas-confetti: 1.6.0
- chart.js: 4.2.0
- chartjs-adapter-date-fns: 3.0.0_n6szoxj4ax2zhp2sxsxxj6zdla
- chartjs-chart-matrix: 2.0.1_chart.js@4.2.0
- chartjs-plugin-gradient: 0.6.1_chart.js@4.2.0
- chartjs-plugin-zoom: 2.0.0_chart.js@4.2.0
+ chart.js: 4.2.1
+ chartjs-adapter-date-fns: 3.0.0_rid3rx6orfiwps7kg2r43n6mvu
+ chartjs-chart-matrix: 2.0.1_chart.js@4.2.1
+ chartjs-plugin-gradient: 0.6.1_chart.js@4.2.1
+ chartjs-plugin-zoom: 2.0.0_chart.js@4.2.1
compare-versions: 5.0.1
cropperjs: 2.0.0-beta.2
date-fns: 2.29.3
@@ -487,7 +508,7 @@ importers:
insert-text-at-cursor: 0.3.0
is-file-animated: 1.0.2
json5: 2.2.3
- matter-js: 0.18.0
+ matter-js: 0.19.0
mfm-js: 0.23.3
misskey-js: 0.0.15
photoswipe: 5.3.5
@@ -495,13 +516,12 @@ importers:
punycode: 2.3.0
querystring: 0.2.1
rndstr: 1.0.0
- rollup: 3.14.0
+ rollup: 3.17.2
s-age: 1.1.2
- sanitize-html: 2.9.0
- sass: 1.58.0
+ sanitize-html: 2.10.0
+ sass: 1.58.3
seedrandom: 3.0.5
strict-event-emitter-types: 2.0.0
- stringz: 2.1.0
syuilo-password-strength: 0.0.1
textarea-caret: 3.1.0
three: 0.149.0
@@ -513,7 +533,7 @@ importers:
typescript: 4.9.5
uuid: 9.0.0
vanilla-tilt: 1.8.0
- vite: 4.1.1_gyrp4zacqcjjrmgvdzgac5epyy
+ vite: 4.1.2_hlkwzk2izwsolfmdrejei4vrty
vue: 3.2.47
vue-plyr: 7.0.0
vue-prism-editor: 2.0.0-alpha.2_vue@3.2.47
@@ -524,7 +544,7 @@ importers:
'@types/gulp': 4.0.10
'@types/gulp-rename': 2.0.1
'@types/matter-js': 0.18.2
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/punycode': 2.1.0
'@types/sanitize-html': 2.8.0
'@types/seedrandom': 3.0.4
@@ -533,24 +553,24 @@ importers:
'@types/uuid': 9.0.0
'@types/websocket': 1.0.5
'@types/ws': 8.5.4
- '@typescript-eslint/eslint-plugin': 5.51.0_b635kmla6dsb4frxfihkw4m47e
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/eslint-plugin': 5.52.0_6cfvjsbua5ptj65675bqcn6oza
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
'@vue/runtime-core': 3.2.47
cross-env: 7.0.3
- cypress: 12.5.1
- eslint: 8.33.0
- eslint-plugin-import: 2.27.5_yzj2n2b43wonjwaifya6xmk2zy
- eslint-plugin-vue: 9.9.0_eslint@8.33.0
- start-server-and-test: 1.15.3
- vue-eslint-parser: 9.1.0_eslint@8.33.0
- vue-tsc: 1.0.24_typescript@4.9.5
+ cypress: 12.6.0
+ eslint: 8.34.0
+ eslint-plugin-import: 2.27.5_mcvs2y73sfmcxqzpjj5lr7a2m4
+ eslint-plugin-vue: 9.9.0_eslint@8.34.0
+ start-server-and-test: 1.15.4
+ vue-eslint-parser: 9.1.0_eslint@8.34.0
+ vue-tsc: 1.1.4_typescript@4.9.5
packages/sw:
specifiers:
- '@typescript-eslint/parser': 5.51.0
+ '@typescript-eslint/parser': 5.52.0
'@typescript/lib-webworker': npm:@types/serviceworker@0.0.62
esbuild: 0.14.42
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-plugin-import: 2.27.5
idb-keyval: 6.2.0
misskey-js: 0.0.15
@@ -560,10 +580,10 @@ importers:
idb-keyval: 6.2.0
misskey-js: 0.0.15
devDependencies:
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
'@typescript/lib-webworker': /@types/serviceworker/0.0.62
- eslint: 8.33.0
- eslint-plugin-import: 2.27.5_yzj2n2b43wonjwaifya6xmk2zy
+ eslint: 8.34.0
+ eslint-plugin-import: 2.27.5_mcvs2y73sfmcxqzpjj5lr7a2m4
typescript: 4.9.5
packages:
@@ -732,7 +752,6 @@ packages:
/@babel/parser/7.20.7:
resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==}
engines: {node: '>=6.0.0'}
- hasBin: true
dependencies:
'@babel/types': 7.20.7
@@ -911,26 +930,26 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true
- /@bull-board/api/4.11.1:
- resolution: {integrity: sha512-x+CKpLKZ4yJ1CETvoX9cIOMM1ZfsXr6N9pOsRj8/lh0Mo/rbQWbfdlZR1jiALMAKu1RzJnffZcn6uKeFoXMRBQ==}
+ /@bull-board/api/4.12.1:
+ resolution: {integrity: sha512-cJk7LhphNZHwbN4yON5rYiDgob3D7cwFGrxf6LlnR1w/a6zyap1x/o74MfV/0T6NpUpvUSf7ccbj3knU6DNYVw==}
dependencies:
redis-info: 3.1.0
dev: false
- /@bull-board/fastify/4.11.1:
- resolution: {integrity: sha512-xBTgSZKeLIwjLWsdW3vOJTubO6ZfiOKQSjtZ7n9ZUoiO4gg4m0MWfTBDgBFSgIqB5FjgdsIO6aP7QGsHI1wmng==}
+ /@bull-board/fastify/4.12.1:
+ resolution: {integrity: sha512-MAecvp+xTePdEHm4uCooojAlj2isdznfC9XuCjjGHHNCczjm/Wx14cDhKLKwkOFp5ZLhqgtOEulT5YVfVCu+EQ==}
dependencies:
- '@bull-board/api': 4.11.1
- '@bull-board/ui': 4.11.1
- '@fastify/static': 6.8.0
+ '@bull-board/api': 4.12.1
+ '@bull-board/ui': 4.12.1
+ '@fastify/static': 6.9.0
'@fastify/view': 7.4.1
ejs: 3.1.8
dev: false
- /@bull-board/ui/4.11.1:
- resolution: {integrity: sha512-jILv2JN8cfgtHRHYk9GNpQh3rI2zaiX6bEfa1yyFRjLKcY4g409MTOOkZvkXlN5I4mBs+V3aob8cmvS2ixESDA==}
+ /@bull-board/ui/4.12.1:
+ resolution: {integrity: sha512-nNTjxitLEre+UdZjwMHwlKKGxpg3OV/Sf7dNOlhJYoRjO7aYPb63M+BfGVrYgupk3V73Q0qvl1emtsnF/qz/Wg==}
dependencies:
- '@bull-board/api': 4.11.1
+ '@bull-board/api': 4.12.1
dev: false
/@chainsafe/is-ip/2.0.1:
@@ -1359,14 +1378,14 @@ packages:
resolution: {integrity: sha512-H8nwsmawFtKKRE6uhh1BtF1gQi/l147SmLsDGxB0HdYTHzjXz6uSQO3lEVmY7unKMzbArRjdoJQkEGpScszdSw==}
dependencies:
'@fastify/reply-from': 8.3.1
- ws: 8.12.0
+ ws: 8.12.1
transitivePeerDependencies:
- bufferutil
- utf-8-validate
dev: false
- /@fastify/multipart/7.4.0:
- resolution: {integrity: sha512-jl8KCMOjzniAMnF2/VdYFhGB03Oqtl24plxcnsKpdnRLu/ihVz4cNPz9bPn8mLUQW4r3dUlh6emINtZdJczkbg==}
+ /@fastify/multipart/7.4.1:
+ resolution: {integrity: sha512-PgBJIg/1krx1nWIXGZSUFQMPHXeFv559TmpaswzmNkK6V/yn1xi4nkATqBetv7s5XbXhxzc75uaJgXWdUefxvQ==}
dependencies:
'@fastify/busboy': 1.1.0
'@fastify/deepmerge': 1.3.0
@@ -1400,14 +1419,14 @@ packages:
mime: 3.0.0
dev: false
- /@fastify/static/6.8.0:
- resolution: {integrity: sha512-MNQp7KM0NIC+722OPN3MholnfvM+Vg2ao4OwbWWNJhAJEWOKGe4fJsEjIh3OkN0z5ymhklc7EXGCG0zDaIU5ZQ==}
+ /@fastify/static/6.9.0:
+ resolution: {integrity: sha512-9SBVNJi2+KTnfiW1WjiVXDsmUxliNI54OF1eOiaop264dh8FwXSuLmO62JXvx7+VD0vQXEqsyRbFCYUJ9aJxng==}
dependencies:
'@fastify/accept-negotiator': 1.0.0
'@fastify/send': 2.0.1
content-disposition: 0.5.4
fastify-plugin: 4.5.0
- glob: 8.0.3
+ glob: 8.1.0
p-limit: 3.1.0
readable-stream: 4.3.0
dev: false
@@ -1472,20 +1491,20 @@ packages:
engines: {node: '>=8'}
dev: true
- /@jest/console/29.4.2:
- resolution: {integrity: sha512-0I/rEJwMpV9iwi9cDEnT71a5nNGK9lj8Z4+1pRAU2x/thVXCDnaTGrvxyK+cAqZTFVFCiR+hfVrP4l2m+dCmQg==}
+ /@jest/console/29.4.3:
+ resolution: {integrity: sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
chalk: 4.1.2
- jest-message-util: 29.4.2
- jest-util: 29.4.2
+ jest-message-util: 29.4.3
+ jest-util: 29.4.3
slash: 3.0.0
dev: true
- /@jest/core/29.4.2:
- resolution: {integrity: sha512-KGuoQah0P3vGNlaS/l9/wQENZGNKGoWb+OPxh3gz+YzG7/XExvYu34MzikRndQCdM2S0tzExN4+FL37i6gZmCQ==}
+ /@jest/core/29.4.3:
+ resolution: {integrity: sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
@@ -1493,32 +1512,32 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/console': 29.4.2
- '@jest/reporters': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/transform': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/console': 29.4.3
+ '@jest/reporters': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/transform': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.7.1
exit: 0.1.2
graceful-fs: 4.2.10
- jest-changed-files: 29.4.2
- jest-config: 29.4.2_@types+node@18.13.0
- jest-haste-map: 29.4.2
- jest-message-util: 29.4.2
- jest-regex-util: 29.4.2
- jest-resolve: 29.4.2
- jest-resolve-dependencies: 29.4.2
- jest-runner: 29.4.2
- jest-runtime: 29.4.2
- jest-snapshot: 29.4.2
- jest-util: 29.4.2
- jest-validate: 29.4.2
- jest-watcher: 29.4.2
+ jest-changed-files: 29.4.3
+ jest-config: 29.4.3_@types+node@18.14.0
+ jest-haste-map: 29.4.3
+ jest-message-util: 29.4.3
+ jest-regex-util: 29.4.3
+ jest-resolve: 29.4.3
+ jest-resolve-dependencies: 29.4.3
+ jest-runner: 29.4.3
+ jest-runtime: 29.4.3
+ jest-snapshot: 29.4.3
+ jest-util: 29.4.3
+ jest-validate: 29.4.3
+ jest-watcher: 29.4.3
micromatch: 4.0.5
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
slash: 3.0.0
strip-ansi: 6.0.1
transitivePeerDependencies:
@@ -1533,14 +1552,14 @@ packages:
'@jest/types': 27.5.1
dev: true
- /@jest/environment/29.4.2:
- resolution: {integrity: sha512-JKs3VUtse0vQfCaFGJRX1bir9yBdtasxziSyu+pIiEllAQOe4oQhdCYIf3+Lx+nGglFktSKToBnRJfD5QKp+NQ==}
+ /@jest/environment/29.4.3:
+ resolution: {integrity: sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/fake-timers': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
- jest-mock: 29.4.2
+ '@jest/fake-timers': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
+ jest-mock: 29.4.3
dev: true
/@jest/expect-utils/29.3.1:
@@ -1550,49 +1569,49 @@ packages:
jest-get-type: 29.4.2
dev: true
- /@jest/expect-utils/29.4.2:
- resolution: {integrity: sha512-Dd3ilDJpBnqa0GiPN7QrudVs0cczMMHtehSo2CSTjm3zdHx0RcpmhFNVEltuEFeqfLIyWKFI224FsMSQ/nsJQA==}
+ /@jest/expect-utils/29.4.3:
+ resolution: {integrity: sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- jest-get-type: 29.4.2
+ jest-get-type: 29.4.3
dev: true
- /@jest/expect/29.4.2:
- resolution: {integrity: sha512-NUAeZVApzyaeLjfWIV/64zXjA2SS+NuUPHpAlO7IwVMGd5Vf9szTl9KEDlxY3B4liwLO31os88tYNHl6cpjtKQ==}
+ /@jest/expect/29.4.3:
+ resolution: {integrity: sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- expect: 29.4.2
- jest-snapshot: 29.4.2
+ expect: 29.4.3
+ jest-snapshot: 29.4.3
transitivePeerDependencies:
- supports-color
dev: true
- /@jest/fake-timers/29.4.2:
- resolution: {integrity: sha512-Ny1u0Wg6kCsHFWq7A/rW/tMhIedq2siiyHyLpHCmIhP7WmcAmd2cx95P+0xtTZlj5ZbJxIRQi4OPydZZUoiSQQ==}
+ /@jest/fake-timers/29.4.3:
+ resolution: {integrity: sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
'@sinonjs/fake-timers': 10.0.2
- '@types/node': 18.13.0
- jest-message-util: 29.4.2
- jest-mock: 29.4.2
- jest-util: 29.4.2
+ '@types/node': 18.14.0
+ jest-message-util: 29.4.3
+ jest-mock: 29.4.3
+ jest-util: 29.4.3
dev: true
- /@jest/globals/29.4.2:
- resolution: {integrity: sha512-zCk70YGPzKnz/I9BNFDPlK+EuJLk21ur/NozVh6JVM86/YYZtZHqxFFQ62O9MWq7uf3vIZnvNA0BzzrtxD9iyg==}
+ /@jest/globals/29.4.3:
+ resolution: {integrity: sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.4.2
- '@jest/expect': 29.4.2
- '@jest/types': 29.4.2
- jest-mock: 29.4.2
+ '@jest/environment': 29.4.3
+ '@jest/expect': 29.4.3
+ '@jest/types': 29.4.3
+ jest-mock: 29.4.3
transitivePeerDependencies:
- supports-color
dev: true
- /@jest/reporters/29.4.2:
- resolution: {integrity: sha512-10yw6YQe75zCgYcXgEND9kw3UZZH5tJeLzWv4vTk/2mrS1aY50A37F+XT2hPO5OqQFFnUWizXD8k1BMiATNfUw==}
+ /@jest/reporters/29.4.3:
+ resolution: {integrity: sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
@@ -1601,12 +1620,12 @@ packages:
optional: true
dependencies:
'@bcoe/v8-coverage': 0.2.3
- '@jest/console': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/transform': 29.4.2
- '@jest/types': 29.4.2
+ '@jest/console': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/transform': 29.4.3
+ '@jest/types': 29.4.3
'@jridgewell/trace-mapping': 0.3.17
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
chalk: 4.1.2
collect-v8-coverage: 1.0.1
exit: 0.1.2
@@ -1617,9 +1636,9 @@ packages:
istanbul-lib-report: 3.0.0
istanbul-lib-source-maps: 4.0.1
istanbul-reports: 3.1.5
- jest-message-util: 29.4.2
- jest-util: 29.4.2
- jest-worker: 29.4.2
+ jest-message-util: 29.4.3
+ jest-util: 29.4.3
+ jest-worker: 29.4.3
slash: 3.0.0
string-length: 4.0.2
strip-ansi: 6.0.1
@@ -1635,8 +1654,15 @@ packages:
'@sinclair/typebox': 0.25.21
dev: true
- /@jest/source-map/29.4.2:
- resolution: {integrity: sha512-tIoqV5ZNgYI9XCKXMqbYe5JbumcvyTgNN+V5QW4My033lanijvCD0D4PI9tBw4pRTqWOc00/7X3KVvUh+qnF4Q==}
+ /@jest/schemas/29.4.3:
+ resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@sinclair/typebox': 0.25.21
+ dev: true
+
+ /@jest/source-map/29.4.3:
+ resolution: {integrity: sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@jridgewell/trace-mapping': 0.3.17
@@ -1644,41 +1670,41 @@ packages:
graceful-fs: 4.2.10
dev: true
- /@jest/test-result/29.4.2:
- resolution: {integrity: sha512-HZsC3shhiHVvMtP+i55MGR5bPcc3obCFbA5bzIOb8pCjwBZf11cZliJncCgaVUbC5yoQNuGqCkC0Q3t6EItxZA==}
+ /@jest/test-result/29.4.3:
+ resolution: {integrity: sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/console': 29.4.2
- '@jest/types': 29.4.2
+ '@jest/console': 29.4.3
+ '@jest/types': 29.4.3
'@types/istanbul-lib-coverage': 2.0.4
collect-v8-coverage: 1.0.1
dev: true
- /@jest/test-sequencer/29.4.2:
- resolution: {integrity: sha512-9Z2cVsD6CcObIVrWigHp2McRJhvCxL27xHtrZFgNC1RwnoSpDx6fZo8QYjJmziFlW9/hr78/3sxF54S8B6v8rg==}
+ /@jest/test-sequencer/29.4.3:
+ resolution: {integrity: sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/test-result': 29.4.2
+ '@jest/test-result': 29.4.3
graceful-fs: 4.2.10
- jest-haste-map: 29.4.2
+ jest-haste-map: 29.4.3
slash: 3.0.0
dev: true
- /@jest/transform/29.4.2:
- resolution: {integrity: sha512-kf1v5iTJHn7p9RbOsBuc/lcwyPtJaZJt5885C98omWz79NIeD3PfoiiaPSu7JyCyFzNOIzKhmMhQLUhlTL9BvQ==}
+ /@jest/transform/29.4.3:
+ resolution: {integrity: sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/core': 7.20.12
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
'@jridgewell/trace-mapping': 0.3.17
babel-plugin-istanbul: 6.1.1
chalk: 4.1.2
convert-source-map: 2.0.0
fast-json-stable-stringify: 2.1.0
graceful-fs: 4.2.10
- jest-haste-map: 29.4.2
- jest-regex-util: 29.4.2
- jest-util: 29.4.2
+ jest-haste-map: 29.4.3
+ jest-regex-util: 29.4.3
+ jest-util: 29.4.3
micromatch: 4.0.5
pirates: 4.0.5
slash: 3.0.0
@@ -1693,19 +1719,19 @@ packages:
dependencies:
'@types/istanbul-lib-coverage': 2.0.4
'@types/istanbul-reports': 3.0.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/yargs': 16.0.5
chalk: 4.1.2
dev: true
- /@jest/types/29.4.2:
- resolution: {integrity: sha512-CKlngyGP0fwlgC1BRUtPZSiWLBhyS9dKwKmyGxk8Z6M82LBEGB2aLQSg+U1MyLsU+M7UjnlLllBM2BLWKVm/Uw==}
+ /@jest/types/29.4.3:
+ resolution: {integrity: sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/schemas': 29.4.2
+ '@jest/schemas': 29.4.3
'@types/istanbul-lib-coverage': 2.0.4
'@types/istanbul-reports': 3.0.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/yargs': 17.0.19
chalk: 4.1.2
dev: true
@@ -1766,7 +1792,6 @@ packages:
/@mapbox/node-pre-gyp/1.0.9:
resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==}
- hasBin: true
dependencies:
detect-libc: 2.0.1
https-proxy-agent: 5.0.1
@@ -1795,7 +1820,7 @@ packages:
filenamify: 5.1.1
got: 11.8.5
os-filter-obj: 2.0.0
- dev: true
+ dev: false
/@msgpackr-extract/msgpackr-extract-darwin-arm64/2.2.0:
resolution: {integrity: sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==}
@@ -1839,8 +1864,8 @@ packages:
requiresBuild: true
optional: true
- /@nestjs/common/9.3.7_mnr6j2del53muneqly5h4y27ai:
- resolution: {integrity: sha512-7hwY2lIkmB+K8wPSP9T8auzKPSlO15Gzujl3/ZxLX9SBt6B7N5Niv5E+5AzOcfL+h2X8JGysMG620hiGbUsT9A==}
+ /@nestjs/common/9.3.9_mnr6j2del53muneqly5h4y27ai:
+ resolution: {integrity: sha512-GshTD9Xz+wD2em6NyzU4NXw5IXMUmapgDgD+iuj6XL0258hvDwODmNk37mBBnZvTZlqER+krvIUKnS34etqF/A==}
peerDependencies:
cache-manager: <=5
class-transformer: '*'
@@ -1862,8 +1887,8 @@ packages:
uid: 2.0.1
dev: false
- /@nestjs/core/9.3.7_ojttuksvundfk3amlyo674va74:
- resolution: {integrity: sha512-FXGVivZiujZl1aJF6jdPpg1XnLKp7kDhVGhWhJtnpv2IW/cz/YQHD2uMz/o+GZ9TCZxsGlxg79jbcuJITG11iQ==}
+ /@nestjs/core/9.3.9_jrq2rdgfp2sx67wmylmrqliwxe:
+ resolution: {integrity: sha512-9g1A1G9eirLXEpH21rc6dKb08zHc2+adhCRz8NW39hbejcsxxD72FApJzt4QBQAKvu862ixt/tdpStnFT7lOSw==}
requiresBuild: true
peerDependencies:
'@nestjs/common': ^9.0.0
@@ -1880,7 +1905,7 @@ packages:
'@nestjs/websockets':
optional: true
dependencies:
- '@nestjs/common': 9.3.7_mnr6j2del53muneqly5h4y27ai
+ '@nestjs/common': 9.3.9_mnr6j2del53muneqly5h4y27ai
'@nuxtjs/opencollective': 0.3.2
fast-safe-stringify: 2.1.1
iterare: 1.2.1
@@ -1893,8 +1918,8 @@ packages:
- encoding
dev: false
- /@nestjs/testing/9.3.7_zmctrozi6xxh3beaccl6ebop6u:
- resolution: {integrity: sha512-tNJuNYfDXMJzTgQXRwnQtLdd7PIIqrSsZ//TP/wnqPnbUpTkWMCSK5exWfPWvdyS8P3Fy2wy5hNj8Rvp9+KvYw==}
+ /@nestjs/testing/9.3.9_77foi4w27ghy47yutmnzv7krjy:
+ resolution: {integrity: sha512-+mPvSVvSC2SAkYgZZv1mOI2xsdGc1pmq7/sem7iin/JDoFtlvoGSK+pfZHD3IV3EpYtq1v/8/5gi+UFH9yZnDg==}
peerDependencies:
'@nestjs/common': ^9.0.0
'@nestjs/core': ^9.0.0
@@ -1906,8 +1931,8 @@ packages:
'@nestjs/platform-express':
optional: true
dependencies:
- '@nestjs/common': 9.3.7_mnr6j2del53muneqly5h4y27ai
- '@nestjs/core': 9.3.7_ojttuksvundfk3amlyo674va74
+ '@nestjs/common': 9.3.9_mnr6j2del53muneqly5h4y27ai
+ '@nestjs/core': 9.3.9_jrq2rdgfp2sx67wmylmrqliwxe
tslib: 2.5.0
dev: false
@@ -1940,7 +1965,6 @@ packages:
/@npmcli/move-file/2.0.1:
resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
- deprecated: This functionality has been moved to @npmcli/fs
dependencies:
mkdirp: 1.0.4
rimraf: 3.0.2
@@ -1967,7 +1991,6 @@ packages:
/@nuxtjs/opencollective/0.3.2:
resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==}
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
- hasBin: true
dependencies:
chalk: 4.1.2
consola: 2.15.3
@@ -2061,7 +2084,7 @@ packages:
- encoding
dev: true
- /@rollup/plugin-alias/4.0.3_rollup@3.14.0:
+ /@rollup/plugin-alias/4.0.3_rollup@3.17.2:
resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2070,11 +2093,11 @@ packages:
rollup:
optional: true
dependencies:
- rollup: 3.14.0
+ rollup: 3.17.2
slash: 4.0.0
dev: false
- /@rollup/plugin-json/6.0.0_rollup@3.14.0:
+ /@rollup/plugin-json/6.0.0_rollup@3.17.2:
resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2083,11 +2106,11 @@ packages:
rollup:
optional: true
dependencies:
- '@rollup/pluginutils': 5.0.2_rollup@3.14.0
- rollup: 3.14.0
+ '@rollup/pluginutils': 5.0.2_rollup@3.17.2
+ rollup: 3.17.2
dev: false
- /@rollup/pluginutils/5.0.2_rollup@3.14.0:
+ /@rollup/pluginutils/5.0.2_rollup@3.17.2:
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2099,7 +2122,7 @@ packages:
'@types/estree': 1.0.0
estree-walker: 2.0.2
picomatch: 2.3.1
- rollup: 3.14.0
+ rollup: 3.17.2
dev: false
/@sideway/address/4.1.4:
@@ -2123,7 +2146,7 @@ packages:
/@sindresorhus/is/4.6.0:
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'}
- dev: true
+ dev: false
/@sindresorhus/is/5.3.0:
resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==}
@@ -2144,8 +2167,8 @@ packages:
resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
dev: false
- /@swc/cli/0.1.61_nh7rjdlljrxbrljvydz3oxxjt4:
- resolution: {integrity: sha512-HeYMJ+8gKfJzM9xgcZqTpAHJYAJVGSljBSmWRUx2B6UiGraLsLjEcqxITwi6/t6Af+QboBMiQX5Wwll89oPK7g==}
+ /@swc/cli/0.1.62_wyduggqpvtv2oy5nc7cgtozgpy:
+ resolution: {integrity: sha512-kOFLjKY3XH1DWLfXL1/B5MizeNorHR8wHKEi92S/Zi9Md/AK17KSqR8MgyRJ6C1fhKHvbBCl8wboyKAFXStkYw==}
engines: {node: '>= 12.13'}
hasBin: true
peerDependencies:
@@ -2156,133 +2179,139 @@ packages:
optional: true
dependencies:
'@mole-inc/bin-wrapper': 8.0.1
- '@swc/core': 1.3.34
+ '@swc/core': 1.3.36
chokidar: 3.5.3
commander: 7.2.0
fast-glob: 3.2.12
semver: 7.3.8
slash: 3.0.0
source-map: 0.7.4
- dev: true
+ dev: false
+
+ /@swc/core-android-arm64/1.3.11:
+ resolution: {integrity: sha512-M7FamR3kFpVTyTw73FzKcOZmS7/TWHX75eqtwBTaU9fW4shf0KTLr/h9DnMxNKAnwUMeub/lqlINUe5EKFIKwQ==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dependencies:
+ '@swc/wasm': 1.2.130
+ dev: false
+ optional: true
- /@swc/core-darwin-arm64/1.3.34:
- resolution: {integrity: sha512-m7+kybVLO9uo/TiGBlf/ISmpmm27I/NrFEBGOVBF2xNOs5BY1XHHM6ddbPPckQa38C19nWeAzdJPwGzJw+qO3A==}
+ /@swc/core-darwin-arm64/1.3.36:
+ resolution: {integrity: sha512-lsP+C8p9cC/Vd9uAbtxpEnM8GoJI/MMnVuXak7OlxOtDH9/oTwmAcAQTfNGNaH19d2FAIRwf+5RbXCPnxa2Zjw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-darwin-x64/1.3.34:
- resolution: {integrity: sha512-arH7LtcOhuC1wy88qgbCO/E5NnBThbxv9HhjScDfoUPRunyvT9whEvSK0eXCXxGvDAiAtXIrW3blIrteOsQaOQ==}
+ /@swc/core-darwin-x64/1.3.36:
+ resolution: {integrity: sha512-jaLXsozWN5xachl9fPxDMi5nbWq1rRxPAt6ISeiYB6RJk0MQKH1634pOweBBem2pUDDzwDFXFw6f22LTm/cFvA==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-linux-arm-gnueabihf/1.3.34:
- resolution: {integrity: sha512-+pvjXsXTBzSxEL3U9869y3Am/3yo6kQfU6VGVAebgLv+pjM+mIHywbgo1Uxw+pgpTuD38BsrtYcaPNeBICN/wA==}
+ /@swc/core-linux-arm-gnueabihf/1.3.36:
+ resolution: {integrity: sha512-vcBdTHjoEpvJDbFlgto+S6VwAHzLA9GyCiuNcTU2v4KNQlFzhbO4A4PMfMCb/Z0RLJEr16tirfHdWIxjU3h8nw==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-linux-arm64-gnu/1.3.34:
- resolution: {integrity: sha512-hOV1n1j+mDAgp19J+aeAnW4itMTWbaPbSbhEvLsNbVB00LoL6q6pUkWvCi+UbrejV6BIyyE9t7F5fU26SdKR8A==}
+ /@swc/core-linux-arm64-gnu/1.3.36:
+ resolution: {integrity: sha512-o7f5OsvwWppJo+qIZmrGO5+XC6DPt6noecSbRHjF6o1YAcR13ETPC14k1eC9H1YbQwpyCFNVAFXyNcUbCeQyrQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-linux-arm64-musl/1.3.34:
- resolution: {integrity: sha512-r2/Hegp1DRSzG+kg36Tujdn+WX+gO/2wQpVj/g6RPxIPdjy53OOf+UwvJ23Ecn5ZbyJcgKhhTN6H6/ZNHQPqjQ==}
+ /@swc/core-linux-arm64-musl/1.3.36:
+ resolution: {integrity: sha512-FSHPngMi3c0fuGt9yY2Ubn5UcELi3EiPLJxBSC3X8TF9atI/WHZzK9PE9Gtn0C/LyRh4CoyOugDtSOPzGYmLQg==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-linux-x64-gnu/1.3.34:
- resolution: {integrity: sha512-jPxxAo7XlAT7bdIi49PtYN/K1TAxvpVS7otteJLhThOPPTVblIDg63U94ivp3mVQJb3WFH4KNYatEXypyvXppQ==}
+ /@swc/core-linux-x64-gnu/1.3.36:
+ resolution: {integrity: sha512-PHSsH2rek5pr3e0K09VgWAbrWK2vJhaI7MW9TPoTjyACYjcs3WwjcjQ30MghXUs2Dc/bXjWAOi9KFTjq/uCyFg==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-linux-x64-musl/1.3.34:
- resolution: {integrity: sha512-eJaUuhvnNtcwpK9Mil4hZTSYZqG519gX5AQQ2VZOhrWBEBJi+jM0RXAvWdESsaXpS7W0CRtbmEXqeUff6UEgpQ==}
+ /@swc/core-linux-x64-musl/1.3.36:
+ resolution: {integrity: sha512-4LfMYQHzozHCKkIcmQy83b+4SpI+mOp6sYNbXqSRz5dYvTVjegKZXe596P1U/87cK2cgR4uYvkgkgBXquaWvwQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-win32-arm64-msvc/1.3.34:
- resolution: {integrity: sha512-KFdeC5bXDcxIQ/1J5Pjj8BOblRFjh89TTJxujxAhKdoD1k0NV9BKEZACja2cTBz0hWD4cYlBX0cESVdL2rkm3w==}
+ /@swc/core-win32-arm64-msvc/1.3.36:
+ resolution: {integrity: sha512-7y3dDcun79TAjCyk3Iv0eOMw1X/KNQbkVyKOGqnEgq9g22F8F1FoUGKHNTzUqVdzpHeJSsHgW5PlkEkl3c/d9w==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-win32-ia32-msvc/1.3.34:
- resolution: {integrity: sha512-MgWkAQDiWIHfJL5b5aoogenGIt3qcqBSvwLnDQqSWEhkodZjHyCWpQFuaa7Y6ER3pKUIZ5kR8O9aAkDmF39awQ==}
+ /@swc/core-win32-ia32-msvc/1.3.36:
+ resolution: {integrity: sha512-zK0VR3B4LX5hzQ+7eD+K+FkxJlJg5Lo36BeahMzQ+/i0IURpnuyFlW88sdkFkMsc2swdU6bpvxLZeIRQ3W4OUg==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
requiresBuild: true
- dev: true
optional: true
- /@swc/core-win32-x64-msvc/1.3.34:
- resolution: {integrity: sha512-UhaikgVRYBZZdMI7Zo4/eUyYLnjGrC6QAn9aggt1+PiFIM9tXpX8aONUL3LoLkhQhd+6iWygfQ298RRxjKAKuw==}
+ /@swc/core-win32-x64-msvc/1.3.36:
+ resolution: {integrity: sha512-2bIjr9DhAckGiXZEvj6z2z7ECPcTimG+wD0VuQTvr+wkx46uAJKl5Kq+Zk+dd15ErL7JGUtCet1T7bf1k4FwvQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
requiresBuild: true
- dev: true
optional: true
- /@swc/core/1.3.34:
- resolution: {integrity: sha512-kaOCGRpciMEs2FpCUFaPJSNHgggFteOGZToM88uL5k/CEy0nU/6wzl8kUO5J+rI/8/8vN7qyhM1Ajhyj3WCSsw==}
+ /@swc/core/1.3.36:
+ resolution: {integrity: sha512-Ogrd9uRNIj7nHjXxG66UlKBIcXESUenJ7OD6K2a8p82qlg6ne7Ne5Goiipm/heHYhSfVmjcnRWL9ZJ4gv+YCPA==}
engines: {node: '>=10'}
requiresBuild: true
optionalDependencies:
- '@swc/core-darwin-arm64': 1.3.34
- '@swc/core-darwin-x64': 1.3.34
- '@swc/core-linux-arm-gnueabihf': 1.3.34
- '@swc/core-linux-arm64-gnu': 1.3.34
- '@swc/core-linux-arm64-musl': 1.3.34
- '@swc/core-linux-x64-gnu': 1.3.34
- '@swc/core-linux-x64-musl': 1.3.34
- '@swc/core-win32-arm64-msvc': 1.3.34
- '@swc/core-win32-ia32-msvc': 1.3.34
- '@swc/core-win32-x64-msvc': 1.3.34
- dev: true
+ '@swc/core-darwin-arm64': 1.3.36
+ '@swc/core-darwin-x64': 1.3.36
+ '@swc/core-linux-arm-gnueabihf': 1.3.36
+ '@swc/core-linux-arm64-gnu': 1.3.36
+ '@swc/core-linux-arm64-musl': 1.3.36
+ '@swc/core-linux-x64-gnu': 1.3.36
+ '@swc/core-linux-x64-musl': 1.3.36
+ '@swc/core-win32-arm64-msvc': 1.3.36
+ '@swc/core-win32-ia32-msvc': 1.3.36
+ '@swc/core-win32-x64-msvc': 1.3.36
- /@swc/jest/0.2.24_@swc+core@1.3.34:
+ /@swc/jest/0.2.24_@swc+core@1.3.36:
resolution: {integrity: sha512-fwgxQbM1wXzyKzl1+IW0aGrRvAA8k0Y3NxFhKigbPjOJ4mCKnWEcNX9HQS3gshflcxq8YKhadabGUVfdwjCr6Q==}
engines: {npm: '>= 7.0.0'}
peerDependencies:
'@swc/core': '*'
dependencies:
'@jest/create-cache-key-function': 27.5.1
- '@swc/core': 1.3.34
+ '@swc/core': 1.3.36
jsonc-parser: 3.2.0
dev: true
+ /@swc/wasm/1.2.130:
+ resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@syuilo/aiscript/0.12.4:
resolution: {integrity: sha512-fIWEAHsnw9vMWTcjmSM2rCsadhb+BLirLDLW6lnRw3PFC8LV76Np8Ih8ssfAb00udh6oiGBSj+WiBdkMagbjmQ==}
dependencies:
@@ -2297,7 +2326,7 @@ packages:
engines: {node: '>=10'}
dependencies:
defer-to-connect: 2.0.1
- dev: true
+ dev: false
/@szmarczak/http-timer/5.0.1:
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
@@ -2352,7 +2381,6 @@ packages:
/@tensorflow/tfjs-core/4.2.0:
resolution: {integrity: sha512-uuHkiWVC8b00ngFbHvAV7J7haRlN/9PEdeenCi0CzBjgKd7aN25wPWaoN0TSQcU+GT4FJ8mofMZ9VBYZ/s/WLg==}
engines: {yarn: '>= 1.3.2'}
- requiresBuild: true
dependencies:
'@types/long': 4.0.2
'@types/offscreencanvas': 2019.7.0
@@ -2411,7 +2439,6 @@ packages:
/@tensorflow/tfjs/4.2.0_seedrandom@3.0.5:
resolution: {integrity: sha512-iZmtyGC9IJkx+TpFnkgDol8BHv2BU3zJ01HyNcuvnm1w1EqoNe+1n8bwvLzI/sxHMcHTqzuu7VugMaphryxE+A==}
- hasBin: true
dependencies:
'@tensorflow/tfjs-backend-cpu': 4.2.0_tkoh6rxfpzme3tc2ndqbqcrg7y
'@tensorflow/tfjs-backend-webgl': 4.2.0_tkoh6rxfpzme3tc2ndqbqcrg7y
@@ -2431,6 +2458,7 @@ packages:
/@tokenizer/token/0.3.0:
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
+ dev: false
/@tootallnate/once/2.0.0:
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
@@ -2440,7 +2468,7 @@ packages:
/@types/accepts/1.3.5:
resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/archiver/5.3.1:
@@ -2484,9 +2512,8 @@ packages:
/@types/bull/4.10.0:
resolution: {integrity: sha512-RkYW8K2H3J76HT6twmHYbzJ0GtLDDotpLP9ah9gtiA7zfF6peBH1l5fEiK0oeIZ3/642M7Jcb9sPmor8Vf4w6g==}
- deprecated: This is a stub types definition. bull provides its own type definitions, so you do not need this installed.
dependencies:
- bull: 4.10.3
+ bull: 4.10.4
transitivePeerDependencies:
- supports-color
dev: true
@@ -2496,13 +2523,12 @@ packages:
dependencies:
'@types/http-cache-semantics': 4.0.1
'@types/keyv': 3.1.4
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/responselike': 1.0.0
- dev: true
+ dev: false
/@types/cbor/6.0.0:
resolution: {integrity: sha512-mGQ1lbYOwVti5Xlarn1bTeBZqgY0kstsdjnkoEovgohYKdBjGejHyNGXHdMBeqyQazIv32Jjp33+5pBEaSRy2w==}
- deprecated: This is a stub types definition. cbor provides its own type definitions, so you do not need this installed.
dependencies:
cbor: 8.1.0
dev: true
@@ -2539,34 +2565,34 @@ packages:
/@types/fluent-ffmpeg/2.1.20:
resolution: {integrity: sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/glob-stream/6.1.1:
resolution: {integrity: sha512-AGOUTsTdbPkRS0qDeyeS+6KypmfVpbT5j23SN8UPG63qjKXNKjXn6V9wZUr8Fin0m9l8oGYaPK8b2WUMF8xI1A==}
dependencies:
'@types/glob': 8.0.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/glob/8.0.0:
resolution: {integrity: sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==}
dependencies:
'@types/minimatch': 5.1.2
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/glob/8.0.1:
resolution: {integrity: sha512-8bVUjXZvJacUFkJXHdyZ9iH1Eaj5V7I8c4NdH5sQJsdXkqT4CA5Dhb4yb4VE/3asyx4L9ayZr1NIhTsWHczmMw==}
dependencies:
'@types/minimatch': 5.1.2
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/graceful-fs/4.1.6:
resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/gulp-rename/2.0.1:
@@ -2586,11 +2612,12 @@ packages:
/@types/http-cache-semantics/4.0.1:
resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==}
+ dev: false
/@types/ioredis/4.28.10:
resolution: {integrity: sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/istanbul-lib-coverage/2.0.4:
@@ -2623,7 +2650,7 @@ packages:
/@types/jsdom/21.1.0:
resolution: {integrity: sha512-leWreJOdnuIxq9Y70tBVm/bvTuh31DSlF/r4l7Cfi4uhVQqLHD0Q4v301GMisEMwwbMgF7ZKxuZ+Jbd4NcdmRw==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/tough-cookie': 4.0.2
parse5: 7.1.2
dev: true
@@ -2647,8 +2674,8 @@ packages:
/@types/keyv/3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies:
- '@types/node': 18.13.0
- dev: true
+ '@types/node': 18.14.0
+ dev: false
/@types/long/4.0.2:
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
@@ -2669,13 +2696,12 @@ packages:
/@types/node-fetch/2.6.2:
resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
form-data: 3.0.1
dev: false
/@types/node-fetch/3.0.3:
resolution: {integrity: sha512-HhggYPH5N+AQe/OmN6fmhKmRRt2XuNJow+R3pQwJxOOF9GuwM7O2mheyGeIrs5MOIeNjDEdgdoyHBOrFeJBR3g==}
- deprecated: This is a stub types definition. node-fetch provides its own type definitions, so you do not need this installed.
dependencies:
node-fetch: 3.3.0
dev: true
@@ -2687,19 +2713,19 @@ packages:
/@types/node/18.11.18:
resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
- /@types/node/18.13.0:
- resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==}
+ /@types/node/18.14.0:
+ resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==}
/@types/nodemailer/6.4.7:
resolution: {integrity: sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/oauth/0.9.1:
resolution: {integrity: sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/offscreencanvas/2019.3.0:
@@ -2713,7 +2739,7 @@ packages:
/@types/pg/8.6.6:
resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
pg-protocol: 1.5.0
pg-types: 2.2.0
dev: true
@@ -2733,7 +2759,7 @@ packages:
/@types/qrcode/1.5.0:
resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/random-seed/0.3.3:
@@ -2746,7 +2772,6 @@ packages:
/@types/redis/4.0.11:
resolution: {integrity: sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==}
- deprecated: This is a stub types definition. redis provides its own type definitions, so you do not need this installed.
dependencies:
redis: 4.5.1
dev: true
@@ -2758,8 +2783,8 @@ packages:
/@types/responselike/1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
- '@types/node': 18.13.0
- dev: true
+ '@types/node': 18.14.0
+ dev: false
/@types/sanitize-html/2.8.0:
resolution: {integrity: sha512-Uih6caOm3DsBYnVGOYn0A9NoTNe1c4aPStmHC/YA2JrpP9kx//jzaRcIklFvSpvVQEcpl/ZCr4DgISSf/YxTvg==}
@@ -2786,7 +2811,7 @@ packages:
/@types/sharp/0.31.1:
resolution: {integrity: sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/sinonjs__fake-timers/8.1.1:
@@ -2801,12 +2826,6 @@ packages:
resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==}
dev: true
- /@types/speakeasy/2.0.7:
- resolution: {integrity: sha512-JEcOhN2SQCoX86ZfiZEe8px84sVJtivBXMZfOVyARTYEj0hrwwbj1nF0FwEL3nJSoEV6uTbcdLllMKBgAYHWCQ==}
- dependencies:
- '@types/node': 18.13.0
- dev: true
-
/@types/stack-utils/2.0.1:
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
dev: true
@@ -2834,7 +2853,7 @@ packages:
/@types/undertaker/1.2.8:
resolution: {integrity: sha512-gW3PRqCHYpo45XFQHJBhch7L6hytPsIe0QeLujlnFsjHPnXLhJcPdN6a9368d7aIQgH2I/dUTPFBlGeSNA3qOg==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/undertaker-registry': 1.0.1
async-done: 1.3.2
dev: true
@@ -2842,7 +2861,7 @@ packages:
/@types/unzipper/0.10.5:
resolution: {integrity: sha512-NrLJb29AdnBARpg9S/4ktfPEisbJ0AvaaAr3j7Q1tg8AgcEUsq2HqbNzvgLRoWyRtjzeLEv7vuL39u1mrNIyNA==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/uuid/9.0.0:
@@ -2852,14 +2871,14 @@ packages:
/@types/vary/1.1.0:
resolution: {integrity: sha512-LQWqrIa0dvEOOH37lGksMEXbypRLUFqu6Gx0pmX7zIUisD2I/qaVgEX/vJ/PSVSW0Hk6yz1BNkFpqg6dZm3Wug==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/vinyl-fs/2.4.12:
resolution: {integrity: sha512-LgBpYIWuuGsihnlF+OOWWz4ovwCYlT03gd3DuLwex50cYZLmX3yrW+sFF9ndtmh7zcZpS6Ri47PrIu+fV+sbXw==}
dependencies:
'@types/glob-stream': 6.1.1
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
'@types/vinyl': 2.0.7
dev: true
@@ -2867,12 +2886,12 @@ packages:
resolution: {integrity: sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==}
dependencies:
'@types/expect': 1.20.4
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
/@types/web-push/3.3.2:
resolution: {integrity: sha512-JxWGVL/m7mWTIg4mRYO+A6s0jPmBkr4iJr39DqJpRJAc+jrPiEe1/asmkwerzRon8ZZDxaZJpsxpv0Z18Wo9gw==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/webgl-ext/0.0.30:
@@ -2882,13 +2901,13 @@ packages:
/@types/websocket/1.0.5:
resolution: {integrity: sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/ws/8.5.4:
resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==}
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
/@types/yargs-parser/21.0.0:
@@ -2911,12 +2930,12 @@ packages:
resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==}
requiresBuild: true
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
dev: true
optional: true
- /@typescript-eslint/eslint-plugin/5.51.0_b635kmla6dsb4frxfihkw4m47e:
- resolution: {integrity: sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==}
+ /@typescript-eslint/eslint-plugin/5.52.0_6cfvjsbua5ptj65675bqcn6oza:
+ resolution: {integrity: sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
@@ -2926,12 +2945,12 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
- '@typescript-eslint/scope-manager': 5.51.0
- '@typescript-eslint/type-utils': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
- '@typescript-eslint/utils': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
+ '@typescript-eslint/scope-manager': 5.52.0
+ '@typescript-eslint/type-utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
+ '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
debug: 4.3.4
- eslint: 8.33.0
+ eslint: 8.34.0
grapheme-splitter: 1.0.4
ignore: 5.2.4
natural-compare-lite: 1.4.0
@@ -2943,8 +2962,8 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/parser/5.51.0_4vsywjlpuriuw3tl5oq6zy5a64:
- resolution: {integrity: sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==}
+ /@typescript-eslint/parser/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm:
+ resolution: {integrity: sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@@ -2953,26 +2972,26 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/scope-manager': 5.51.0
- '@typescript-eslint/types': 5.51.0
- '@typescript-eslint/typescript-estree': 5.51.0_typescript@4.9.5
+ '@typescript-eslint/scope-manager': 5.52.0
+ '@typescript-eslint/types': 5.52.0
+ '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5
debug: 4.3.4
- eslint: 8.33.0
+ eslint: 8.34.0
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/scope-manager/5.51.0:
- resolution: {integrity: sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==}
+ /@typescript-eslint/scope-manager/5.52.0:
+ resolution: {integrity: sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
- '@typescript-eslint/types': 5.51.0
- '@typescript-eslint/visitor-keys': 5.51.0
+ '@typescript-eslint/types': 5.52.0
+ '@typescript-eslint/visitor-keys': 5.52.0
dev: true
- /@typescript-eslint/type-utils/5.51.0_4vsywjlpuriuw3tl5oq6zy5a64:
- resolution: {integrity: sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==}
+ /@typescript-eslint/type-utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm:
+ resolution: {integrity: sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
@@ -2981,23 +3000,23 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/typescript-estree': 5.51.0_typescript@4.9.5
- '@typescript-eslint/utils': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5
+ '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
debug: 4.3.4
- eslint: 8.33.0
+ eslint: 8.34.0
tsutils: 3.21.0_typescript@4.9.5
typescript: 4.9.5
transitivePeerDependencies:
- supports-color
dev: true
- /@typescript-eslint/types/5.51.0:
- resolution: {integrity: sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==}
+ /@typescript-eslint/types/5.52.0:
+ resolution: {integrity: sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
- /@typescript-eslint/typescript-estree/5.51.0_typescript@4.9.5:
- resolution: {integrity: sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==}
+ /@typescript-eslint/typescript-estree/5.52.0_typescript@4.9.5:
+ resolution: {integrity: sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
@@ -3005,8 +3024,8 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/types': 5.51.0
- '@typescript-eslint/visitor-keys': 5.51.0
+ '@typescript-eslint/types': 5.52.0
+ '@typescript-eslint/visitor-keys': 5.52.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@@ -3017,82 +3036,82 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/utils/5.51.0_4vsywjlpuriuw3tl5oq6zy5a64:
- resolution: {integrity: sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==}
+ /@typescript-eslint/utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm:
+ resolution: {integrity: sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@types/json-schema': 7.0.11
'@types/semver': 7.3.13
- '@typescript-eslint/scope-manager': 5.51.0
- '@typescript-eslint/types': 5.51.0
- '@typescript-eslint/typescript-estree': 5.51.0_typescript@4.9.5
- eslint: 8.33.0
+ '@typescript-eslint/scope-manager': 5.52.0
+ '@typescript-eslint/types': 5.52.0
+ '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5
+ eslint: 8.34.0
eslint-scope: 5.1.1
- eslint-utils: 3.0.0_eslint@8.33.0
+ eslint-utils: 3.0.0_eslint@8.34.0
semver: 7.3.8
transitivePeerDependencies:
- supports-color
- typescript
dev: true
- /@typescript-eslint/visitor-keys/5.51.0:
- resolution: {integrity: sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==}
+ /@typescript-eslint/visitor-keys/5.52.0:
+ resolution: {integrity: sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
- '@typescript-eslint/types': 5.51.0
+ '@typescript-eslint/types': 5.52.0
eslint-visitor-keys: 3.3.0
dev: true
- /@vitejs/plugin-vue/4.0.0_vite@4.1.1+vue@3.2.47:
+ /@vitejs/plugin-vue/4.0.0_vite@4.1.2+vue@3.2.47:
resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
vite: ^4.0.0
vue: ^3.2.25
dependencies:
- vite: 4.1.1_gyrp4zacqcjjrmgvdzgac5epyy
+ vite: 4.1.2_hlkwzk2izwsolfmdrejei4vrty
vue: 3.2.47
dev: false
- /@volar/language-core/1.0.24:
- resolution: {integrity: sha512-vTN+alJiWwK0Pax6POqrmevbtFW2dXhjwWiW/MW4f48eDYPLdyURWcr8TixO7EN/nHsUBj2udT7igFKPtjyAKg==}
+ /@volar/language-core/1.2.0-alpha.16:
+ resolution: {integrity: sha512-aIktWe9Zg0M+u/RIXHCuL+IoLRHTrpsbTib8olrg4etlurHDXahoVhoEnH9wmlliray0iigIo2z5vwueYInp3g==}
dependencies:
- '@volar/source-map': 1.0.24
- muggle-string: 0.1.0
+ '@volar/source-map': 1.2.0-alpha.16
dev: true
- /@volar/source-map/1.0.24:
- resolution: {integrity: sha512-Qsv/tkplx18pgBr8lKAbM1vcDqgkGKQzbChg6NW+v0CZc3G7FLmK+WrqEPzKlN7Cwdc6XVL559Nod8WKAfKr4A==}
+ /@volar/source-map/1.2.0-alpha.16:
+ resolution: {integrity: sha512-/AK3VqnFqONd221COI2ZnEvfgBulfoQkjA/ZjPOXpsOkWri99TLcfZY/NTQRytp7Hx6EP/1p1DDeyGuMCUYjgA==}
dependencies:
- muggle-string: 0.1.0
+ muggle-string: 0.2.2
dev: true
- /@volar/typescript/1.0.24:
- resolution: {integrity: sha512-f8hCSk+PfKR1/RQHxZ79V1NpDImHoivqoizK+mstphm25tn/YJ/JnKNjZHB+o21fuW0yKlI26NV3jkVb2Cc/7A==}
+ /@volar/typescript/1.2.0-alpha.16:
+ resolution: {integrity: sha512-ltlTLHIkLxgmTVBZmOnhmnlNzEj2lpvlBmmaV2GWYTrBUMt0z1OgeCq0Utlj9HjjrGPhwWxZNkv86ZABgrMA3Q==}
dependencies:
- '@volar/language-core': 1.0.24
+ '@volar/language-core': 1.2.0-alpha.16
dev: true
- /@volar/vue-language-core/1.0.24:
- resolution: {integrity: sha512-2NTJzSgrwKu6uYwPqLiTMuAzi7fAY3yFy5PJ255bGJc82If0Xr+cW8pC80vpjG0D/aVLmlwAdO4+Ya2BI8GdDg==}
+ /@volar/vue-language-core/1.1.4:
+ resolution: {integrity: sha512-2C2CwHvaT5AzNzDbYZQ85lNr4jACZARoZMZBLuU5+JyIwhWeAfxvyAeoE3VbgfgycN5t6X4uBqx/Wzh1QLgD8Q==}
dependencies:
- '@volar/language-core': 1.0.24
- '@volar/source-map': 1.0.24
+ '@volar/language-core': 1.2.0-alpha.16
+ '@volar/source-map': 1.2.0-alpha.16
'@vue/compiler-dom': 3.2.47
'@vue/compiler-sfc': 3.2.47
'@vue/reactivity': 3.2.47
'@vue/shared': 3.2.47
- minimatch: 5.1.2
+ minimatch: 6.2.0
+ muggle-string: 0.2.2
vue-template-compiler: 2.7.14
dev: true
- /@volar/vue-typescript/1.0.24:
- resolution: {integrity: sha512-9a25oHDvGaNC0okRS47uqJI6FxY4hUQZUsxeOUFHcqVxZEv8s17LPuP/pMMXyz7jPygrZubB/qXqHY5jEu/akA==}
+ /@volar/vue-typescript/1.1.4:
+ resolution: {integrity: sha512-x5i5TUUXb1PM0rM80Y8XUeMBUcoS3/TjR3WTxvvEUIol9uEOPp6uxxQQ67uSv7ocN6vB0LugJqS6FA7Z93oL0Q==}
dependencies:
- '@volar/typescript': 1.0.24
- '@volar/vue-language-core': 1.0.24
+ '@volar/typescript': 1.2.0-alpha.16
+ '@volar/vue-language-core': 1.1.4
dev: true
/@vue/compiler-core/3.2.47:
@@ -3232,13 +3251,11 @@ packages:
/acorn/7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
- hasBin: true
dev: false
/acorn/8.8.1:
resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==}
engines: {node: '>=0.4.0'}
- hasBin: true
/adm-zip/0.5.10:
resolution: {integrity: sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==}
@@ -3414,7 +3431,6 @@ packages:
/arch/2.2.0:
resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
- dev: true
/archiver-utils/2.1.0:
resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==}
@@ -3647,7 +3663,6 @@ packages:
/atob/2.1.2:
resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
engines: {node: '>= 4.5.0'}
- hasBin: true
dev: false
/atomic-sleep/1.0.0:
@@ -3696,8 +3711,8 @@ packages:
- supports-color
dev: false
- /aws-sdk/2.1295.0:
- resolution: {integrity: sha512-HVYoFCyfiL8gzL/c0lSRTg8tWBLfqAEDfwzGe338ww/LahpmC6C07S71SBBIvtGq3dpd7IwEobAbubZDijrA0Q==}
+ /aws-sdk/2.1318.0:
+ resolution: {integrity: sha512-xRCKqx4XWXUIpjDCVHmdOSINEVCIC5+yhmgUGR9A6VfxfPs59HbxKyd5LB+CmXhVbwVUM4SRWG5O+agQj+w7Eg==}
engines: {node: '>= 10.0.0'}
dependencies:
buffer: 4.9.2
@@ -3721,7 +3736,7 @@ packages:
/axios/0.24.0:
resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==}
dependencies:
- follow-redirects: 1.15.2_debug@4.3.4
+ follow-redirects: 1.15.2
transitivePeerDependencies:
- debug
dev: false
@@ -3729,23 +3744,23 @@ packages:
/axios/0.27.2_debug@4.3.4:
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
dependencies:
- follow-redirects: 1.15.2_debug@4.3.4
+ follow-redirects: 1.15.2
form-data: 4.0.0
transitivePeerDependencies:
- debug
dev: true
- /babel-jest/29.4.2_@babel+core@7.20.12:
- resolution: {integrity: sha512-vcghSqhtowXPG84posYkkkzcZsdayFkubUgbE3/1tuGbX7AQtwCkkNA/wIbB0BMjuCPoqTkiDyKN7Ty7d3uwNQ==}
+ /babel-jest/29.4.3_@babel+core@7.20.12:
+ resolution: {integrity: sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@babel/core': ^7.8.0
dependencies:
'@babel/core': 7.20.12
- '@jest/transform': 29.4.2
+ '@jest/transform': 29.4.3
'@types/babel__core': 7.1.20
babel-plugin-istanbul: 6.1.1
- babel-preset-jest: 29.4.2_@babel+core@7.20.12
+ babel-preset-jest: 29.4.3_@babel+core@7.20.12
chalk: 4.1.2
graceful-fs: 4.2.10
slash: 3.0.0
@@ -3766,8 +3781,8 @@ packages:
- supports-color
dev: true
- /babel-plugin-jest-hoist/29.4.2:
- resolution: {integrity: sha512-5HZRCfMeWypFEonRbEkwWXtNS1sQK159LhRVyRuLzyfVBxDy/34Tr/rg4YVi0SScSJ4fqeaR/OIeceJ/LaQ0pQ==}
+ /babel-plugin-jest-hoist/29.4.3:
+ resolution: {integrity: sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/template': 7.20.7
@@ -3796,14 +3811,14 @@ packages:
'@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12
dev: true
- /babel-preset-jest/29.4.2_@babel+core@7.20.12:
- resolution: {integrity: sha512-ecWdaLY/8JyfUDr0oELBMpj3R5I1L6ZqG+kRJmwqfHtLWuPrJStR0LUkvUhfykJWTsXXMnohsayN/twltBbDrQ==}
+ /babel-preset-jest/29.4.3_@babel+core@7.20.12:
+ resolution: {integrity: sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.20.12
- babel-plugin-jest-hoist: 29.4.2
+ babel-plugin-jest-hoist: 29.4.3
babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12
dev: true
@@ -3849,10 +3864,6 @@ packages:
pascalcase: 0.1.1
dev: false
- /base32.js/0.0.1:
- resolution: {integrity: sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==}
- dev: false
-
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -3876,7 +3887,7 @@ packages:
dependencies:
execa: 0.7.0
executable: 4.1.1
- dev: true
+ dev: false
/bin-version-check/5.0.0:
resolution: {integrity: sha512-Q3FMQnS5eZmrBGqmDXLs4dbAn/f+52voP6ykJYmweSA60t6DyH4UTSwZhtbK5UH+LBoWvDljILUQMLRUtsynsA==}
@@ -3885,7 +3896,7 @@ packages:
bin-version: 6.0.0
semver: 7.3.8
semver-truncate: 2.0.0
- dev: true
+ dev: false
/bin-version/6.0.0:
resolution: {integrity: sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==}
@@ -3893,7 +3904,7 @@ packages:
dependencies:
execa: 5.1.1
find-versions: 5.1.0
- dev: true
+ dev: false
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
@@ -3931,8 +3942,8 @@ packages:
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
dev: true
- /blurhash/2.0.4:
- resolution: {integrity: sha512-r/As72u2FbucLoK5NTegM/GucxJc3d8GvHc4ngo13IO/nt2HU4gONxNLq1XPN6EM/V8Y9URIa7PcSz2RZu553A==}
+ /blurhash/2.0.5:
+ resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==}
dev: false
/bn.js/4.12.0:
@@ -3989,8 +4000,6 @@ packages:
/browserslist/1.7.7:
resolution: {integrity: sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==}
- deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.
- hasBin: true
dependencies:
caniuse-db: 1.0.30001443
electron-to-chromium: 1.4.284
@@ -3999,7 +4008,6 @@ packages:
/browserslist/4.21.4:
resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
dependencies:
caniuse-lite: 1.0.30001443
electron-to-chromium: 1.4.284
@@ -4072,8 +4080,8 @@ packages:
node-gyp-build: 4.6.0
dev: false
- /bull/4.10.3:
- resolution: {integrity: sha512-pp403srpkn9tYi7Z3Mu0sozehZ7rEEFGNJnN+nLxQwml6MySzefC9bPeCYedZoCkXdZ6VbIB8uNkMZg+hN/dAg==}
+ /bull/4.10.4:
+ resolution: {integrity: sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA==}
engines: {node: '>=12'}
dependencies:
cron-parser: 4.7.1
@@ -4138,7 +4146,7 @@ packages:
/cacheable-lookup/5.0.4:
resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
engines: {node: '>=10.6.0'}
- dev: true
+ dev: false
/cacheable-lookup/6.1.0:
resolution: {integrity: sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==}
@@ -4174,7 +4182,7 @@ packages:
lowercase-keys: 2.0.0
normalize-url: 6.1.0
responselike: 2.0.1
- dev: true
+ dev: false
/cachedir/2.3.0:
resolution: {integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==}
@@ -4295,45 +4303,45 @@ packages:
is-regex: 1.1.4
dev: false
- /chart.js/4.2.0:
- resolution: {integrity: sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==}
+ /chart.js/4.2.1:
+ resolution: {integrity: sha512-6YbpQ0nt3NovAgOzbkSSeeAQu/3za1319dPUQTXn9WcOpywM8rGKxJHrhS8V8xEkAlk8YhEfjbuAPfUyp6jIsw==}
engines: {pnpm: ^7.0.0}
dependencies:
'@kurkle/color': 0.3.2
dev: false
- /chartjs-adapter-date-fns/3.0.0_n6szoxj4ax2zhp2sxsxxj6zdla:
+ /chartjs-adapter-date-fns/3.0.0_rid3rx6orfiwps7kg2r43n6mvu:
resolution: {integrity: sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==}
peerDependencies:
chart.js: '>=2.8.0'
date-fns: '>=2.0.0'
dependencies:
- chart.js: 4.2.0
+ chart.js: 4.2.1
date-fns: 2.29.3
dev: false
- /chartjs-chart-matrix/2.0.1_chart.js@4.2.0:
+ /chartjs-chart-matrix/2.0.1_chart.js@4.2.1:
resolution: {integrity: sha512-BGfeY+/PHnITyDlc7WfnKJ1RyOfgOzIqWp/gxzzl7pUjyoGzHDcw51qd2xJF9gdT9Def7ZwOnOMm8GJUXDxI0w==}
peerDependencies:
chart.js: '>=3.0.0'
dependencies:
- chart.js: 4.2.0
+ chart.js: 4.2.1
dev: false
- /chartjs-plugin-gradient/0.6.1_chart.js@4.2.0:
+ /chartjs-plugin-gradient/0.6.1_chart.js@4.2.1:
resolution: {integrity: sha512-TGHNIh8KqQMLdb+UfY80cBHYRyOC47eeokmgkeajRdKGbFt462lJiyiq4ZJ25fiM7BGsmzoBLhmVyEw4B3gQxw==}
peerDependencies:
chart.js: '>=2.6.0'
dependencies:
- chart.js: 4.2.0
+ chart.js: 4.2.1
dev: false
- /chartjs-plugin-zoom/2.0.0_chart.js@4.2.0:
+ /chartjs-plugin-zoom/2.0.0_chart.js@4.2.1:
resolution: {integrity: sha512-bqpi7DGy9a5hX7ThKl/xQaLzXvneSwhS0w/lNimZ8AJaoRVMKz5JfUoqwciJYV5ixKXJbgyvwC9HcJnyVsYmjg==}
peerDependencies:
chart.js: '>=3.2.0'
dependencies:
- chart.js: 4.2.0
+ chart.js: 4.2.1
hammerjs: 2.0.8
dev: false
@@ -4429,7 +4437,6 @@ packages:
/cli-highlight/2.1.11:
resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==}
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
- hasBin: true
dependencies:
chalk: 4.1.2
highlight.js: 10.7.3
@@ -4497,7 +4504,7 @@ packages:
resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
dependencies:
mimic-response: 1.0.1
- dev: true
+ dev: false
/clone-stats/1.0.0:
resolution: {integrity: sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==}
@@ -4600,7 +4607,6 @@ packages:
/color-support/1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
- hasBin: true
dev: false
/color/0.11.4:
@@ -4658,7 +4664,7 @@ packages:
/commander/7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
- dev: true
+ dev: false
/commander/9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
@@ -4721,6 +4727,7 @@ packages:
engines: {node: '>= 0.6'}
dependencies:
safe-buffer: 5.2.1
+ dev: false
/convert-source-map/1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
@@ -4761,7 +4768,6 @@ packages:
/crc-32/1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'}
- hasBin: true
dev: false
/crc32-stream/4.0.2:
@@ -4788,7 +4794,6 @@ packages:
/cross-env/7.0.3:
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
- hasBin: true
dependencies:
cross-spawn: 7.0.3
dev: true
@@ -4799,7 +4804,7 @@ packages:
lru-cache: 4.1.5
shebang-command: 1.2.0
which: 1.3.1
- dev: true
+ dev: false
/cross-spawn/7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
@@ -4828,10 +4833,13 @@ packages:
engines: {node: '>= 6'}
dev: false
+ /css.escape/1.5.1:
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+ dev: false
+
/cssesc/3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
- hasBin: true
dev: true
/cssnano/3.10.0:
@@ -4874,7 +4882,6 @@ packages:
/csso/2.3.2:
resolution: {integrity: sha512-FmCI/hmqDeHHLaIQckMhMZneS84yzUZdrWDAvJVVxOwcKE1P1LF9FGmzr1ktIQSxOw6fl3PaQsmfg+GN+VvR3w==}
engines: {node: '>=0.10.0'}
- hasBin: true
dependencies:
clap: 1.2.3
source-map: 0.5.7
@@ -4913,10 +4920,9 @@ packages:
uniq: 1.0.1
dev: false
- /cypress/12.5.1:
- resolution: {integrity: sha512-ZmCmJ3lsyeOpBfh410m5+AO2CO1AxAzFBt7k6/uVbNcrNZje1vdiwYTpj2ksPKg9mjr9lR6V8tmlDNMvr4H/YQ==}
+ /cypress/12.6.0:
+ resolution: {integrity: sha512-WdHSVaS1lumSd5XpVTslZd8ui9GIGphrzvXq9+3DtVhqjRZC5M70gu5SW/Y/SLPq3D1wiXGZoHC6HJ7ESVE2lw==}
engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
- hasBin: true
requiresBuild: true
dependencies:
'@cypress/request': 2.88.11
@@ -5085,6 +5091,7 @@ packages:
engines: {node: '>=10'}
dependencies:
mimic-response: 3.1.0
+ dev: false
/dedent/0.7.0:
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
@@ -5128,6 +5135,7 @@ packages:
/defer-to-connect/2.0.1:
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
engines: {node: '>=10'}
+ dev: false
/define-properties/1.1.4:
resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==}
@@ -5204,8 +5212,8 @@ packages:
engines: {node: '>=8'}
dev: true
- /diff-sequences/29.4.2:
- resolution: {integrity: sha512-R6P0Y6PrsH3n4hUXxL3nns0rbRk6Q33js3ygJBeEpbzLzgcNuJ61+u0RXasFpTKISw99TxUzFnumSnRLsjhLaw==}
+ /diff-sequences/29.4.3:
+ resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
@@ -5317,7 +5325,6 @@ packages:
/ejs/3.1.8:
resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==}
engines: {node: '>=0.10.0'}
- hasBin: true
dependencies:
jake: 10.8.5
dev: false
@@ -5653,7 +5660,6 @@ packages:
/esbuild/0.14.42:
resolution: {integrity: sha512-V0uPZotCEHokJdNqyozH6qsaQXqmZEOiZWrXnds/zaH/0SyrIayRXWRB98CENO73MIZ9T3HBIOsmds5twWtmgw==}
engines: {node: '>=12'}
- hasBin: true
requiresBuild: true
optionalDependencies:
esbuild-android-64: 0.14.42
@@ -5681,7 +5687,6 @@ packages:
/esbuild/0.16.17:
resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
engines: {node: '>=12'}
- hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/android-arm': 0.16.17
@@ -5736,12 +5741,11 @@ packages:
/escape-string-regexp/5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
- dev: true
+ dev: false
/escodegen/2.0.0:
resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==}
engines: {node: '>=6.0'}
- hasBin: true
dependencies:
esprima: 4.0.1
estraverse: 5.3.0
@@ -5761,7 +5765,7 @@ packages:
- supports-color
dev: true
- /eslint-module-utils/2.7.4_fwto6vsnn2m6f5yglaeo6vhd5y:
+ /eslint-module-utils/2.7.4_npjqex3ey3rgd34fjcuucz7la4:
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
engines: {node: '>=4'}
peerDependencies:
@@ -5782,15 +5786,15 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
debug: 3.2.7
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-import-resolver-node: 0.3.7
transitivePeerDependencies:
- supports-color
dev: true
- /eslint-plugin-import/2.27.5_yzj2n2b43wonjwaifya6xmk2zy:
+ /eslint-plugin-import/2.27.5_mcvs2y73sfmcxqzpjj5lr7a2m4:
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
@@ -5800,15 +5804,15 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
- '@typescript-eslint/parser': 5.51.0_4vsywjlpuriuw3tl5oq6zy5a64
+ '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
debug: 3.2.7
doctrine: 2.1.0
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-import-resolver-node: 0.3.7
- eslint-module-utils: 2.7.4_fwto6vsnn2m6f5yglaeo6vhd5y
+ eslint-module-utils: 2.7.4_npjqex3ey3rgd34fjcuucz7la4
has: 1.0.3
is-core-module: 2.11.0
is-glob: 4.0.3
@@ -5823,19 +5827,19 @@ packages:
- supports-color
dev: true
- /eslint-plugin-vue/9.9.0_eslint@8.33.0:
+ /eslint-plugin-vue/9.9.0_eslint@8.34.0:
resolution: {integrity: sha512-YbubS7eK0J7DCf0U2LxvVP7LMfs6rC6UltihIgval3azO3gyDwEGVgsCMe1TmDiEkl6GdMKfRpaME6QxIYtzDQ==}
engines: {node: ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
dependencies:
- eslint: 8.33.0
- eslint-utils: 3.0.0_eslint@8.33.0
+ eslint: 8.34.0
+ eslint-utils: 3.0.0_eslint@8.34.0
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.0.11
semver: 7.3.8
- vue-eslint-parser: 9.1.0_eslint@8.33.0
+ vue-eslint-parser: 9.1.0_eslint@8.34.0
xml-name-validator: 4.0.0
transitivePeerDependencies:
- supports-color
@@ -5857,13 +5861,13 @@ packages:
estraverse: 5.3.0
dev: true
- /eslint-utils/3.0.0_eslint@8.33.0:
+ /eslint-utils/3.0.0_eslint@8.34.0:
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
peerDependencies:
eslint: '>=5'
dependencies:
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-visitor-keys: 2.1.0
dev: true
@@ -5877,10 +5881,9 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
- /eslint/8.33.0:
- resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==}
+ /eslint/8.34.0:
+ resolution: {integrity: sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- hasBin: true
dependencies:
'@eslint/eslintrc': 1.4.1
'@humanwhocodes/config-array': 0.11.8
@@ -5893,7 +5896,7 @@ packages:
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.1.1
- eslint-utils: 3.0.0_eslint@8.33.0
+ eslint-utils: 3.0.0_eslint@8.34.0
eslint-visitor-keys: 3.3.0
espree: 9.4.1
esquery: 1.4.0
@@ -5937,13 +5940,11 @@ packages:
/esprima/2.7.3:
resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==}
engines: {node: '>=0.10.0'}
- hasBin: true
dev: false
/esprima/4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
- hasBin: true
/esquery/1.4.0:
resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==}
@@ -6025,7 +6026,7 @@ packages:
p-finally: 1.0.0
signal-exit: 3.0.7
strip-eof: 1.0.0
- dev: true
+ dev: false
/execa/4.1.0:
resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
@@ -6076,7 +6077,6 @@ packages:
engines: {node: '>=4'}
dependencies:
pify: 2.3.0
- dev: true
/exit/0.1.2:
resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==}
@@ -6121,15 +6121,15 @@ packages:
jest-util: 29.4.2
dev: true
- /expect/29.4.2:
- resolution: {integrity: sha512-+JHYg9O3hd3RlICG90OPVjRkPBoiUH7PxvDVMnRiaq1g6JUgZStX514erMl0v2Dc5SkfVbm7ztqbd6qHHPn+mQ==}
+ /expect/29.4.3:
+ resolution: {integrity: sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/expect-utils': 29.4.2
- jest-get-type: 29.4.2
- jest-matcher-utils: 29.4.2
- jest-message-util: 29.4.2
- jest-util: 29.4.2
+ '@jest/expect-utils': 29.4.3
+ jest-get-type: 29.4.3
+ jest-matcher-utils: 29.4.3
+ jest-message-util: 29.4.3
+ jest-util: 29.4.3
dev: true
/ext-list/2.2.2:
@@ -6137,7 +6137,7 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
mime-db: 1.52.0
- dev: true
+ dev: false
/ext-name/5.0.0:
resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==}
@@ -6145,7 +6145,7 @@ packages:
dependencies:
ext-list: 2.2.2
sort-keys-length: 1.0.1
- dev: true
+ dev: false
/ext/1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
@@ -6190,7 +6190,6 @@ packages:
/extract-zip/2.0.1_supports-color@8.1.1:
resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
engines: {node: '>= 10.17.0'}
- hasBin: true
dependencies:
debug: 4.3.4_supports-color@8.1.1
get-stream: 5.2.0
@@ -6278,7 +6277,6 @@ packages:
/fast-xml-parser/3.21.1:
resolution: {integrity: sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==}
- hasBin: true
dependencies:
strnum: 1.0.5
dev: false
@@ -6287,8 +6285,8 @@ packages:
resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==}
dev: false
- /fastify/4.12.0:
- resolution: {integrity: sha512-Hh2GCsOCqnOuewWSvqXlpq5V/9VA+/JkVoooQWUhrU6gryO9+/UGOoF/dprGcKSDxkM/9TkMXSffYp8eA/YhYQ==}
+ /fastify/4.13.0:
+ resolution: {integrity: sha512-p9ibdFWH3pZ7KPgmfHPKGUy2W4EWU2TEpwlcu58w4CwGyU3ARFfh2kwq6zpZ5W2ZGVbufi4tZbqHIHAlX/9Z/A==}
dependencies:
'@fastify/ajv-compiler': 3.5.0
'@fastify/error': 3.2.0
@@ -6361,10 +6359,10 @@ packages:
readable-web-to-node-stream: 3.0.2
strtok3: 7.0.0
token-types: 5.0.1
- dev: true
+ dev: false
- /file-type/18.2.0:
- resolution: {integrity: sha512-M3RQMWY3F2ykyWZ+IHwNCjpnUmukYhtdkGGC1ZVEUb0ve5REGF7NNJ4Q9ehCUabtQKtSVFOMbFTXgJlFb0DQIg==}
+ /file-type/18.2.1:
+ resolution: {integrity: sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==}
engines: {node: '>=14.16'}
dependencies:
readable-web-to-node-stream: 3.0.2
@@ -6381,7 +6379,7 @@ packages:
/filename-reserved-regex/3.0.0:
resolution: {integrity: sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dev: true
+ dev: false
/filenamify/5.1.1:
resolution: {integrity: sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==}
@@ -6390,7 +6388,7 @@ packages:
filename-reserved-regex: 3.0.0
strip-outer: 2.0.0
trim-repeated: 2.0.0
- dev: true
+ dev: false
/fill-range/4.0.0:
resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==}
@@ -6445,7 +6443,7 @@ packages:
engines: {node: '>=12'}
dependencies:
semver-regex: 4.0.5
- dev: true
+ dev: false
/findup-sync/2.0.0:
resolution: {integrity: sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==}
@@ -6501,7 +6499,6 @@ packages:
/flatten/1.0.3:
resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==}
- deprecated: flatten is deprecated in favor of utility frameworks such as lodash.
dev: false
/fluent-ffmpeg/2.1.2:
@@ -6519,7 +6516,7 @@ packages:
readable-stream: 2.3.7
dev: false
- /follow-redirects/1.15.2_debug@4.3.4:
+ /follow-redirects/1.15.2:
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
engines: {node: '>=4.0'}
peerDependencies:
@@ -6527,8 +6524,6 @@ packages:
peerDependenciesMeta:
debug:
optional: true
- dependencies:
- debug: 4.3.4
/for-each/0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@@ -6768,14 +6763,13 @@ packages:
/get-stream/3.0.0:
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
engines: {node: '>=4'}
- dev: true
+ dev: false
/get-stream/5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
dependencies:
pump: 3.0.0
- dev: true
/get-stream/6.0.1:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
@@ -6877,17 +6871,6 @@ packages:
once: 1.4.0
path-is-absolute: 1.0.1
- /glob/8.0.3:
- resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==}
- engines: {node: '>=12'}
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 5.1.2
- once: 1.4.0
- dev: false
-
/glob/8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
@@ -6982,7 +6965,7 @@ packages:
lowercase-keys: 2.0.0
p-cancelable: 2.1.1
responselike: 2.0.1
- dev: true
+ dev: false
/got/12.5.3:
resolution: {integrity: sha512-8wKnb9MGU8IPGRIo+/ukTy9XLJBwDiCpIf5TVzQ9Cpol50eMTpBq2GAuDsuDIz7hTYmZgMgC1e9ydr6kSDWs3w==}
@@ -7015,7 +6998,6 @@ packages:
/gulp-cli/2.3.0:
resolution: {integrity: sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==}
engines: {node: '>= 0.10'}
- hasBin: true
dependencies:
ansi-colors: 1.1.0
archy: 1.0.0
@@ -7078,7 +7060,6 @@ packages:
/gulp/4.0.2:
resolution: {integrity: sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==}
engines: {node: '>= 0.10'}
- hasBin: true
dependencies:
glob-watcher: 5.0.5
gulp-cli: 2.3.0
@@ -7100,6 +7081,19 @@ packages:
engines: {node: '>=0.8.0'}
dev: false
+ /happy-dom/8.7.0:
+ resolution: {integrity: sha512-F/mH5l8aQwlfeByB0nU6Lg7a0FBax/nPCYNYg8tn/abdKCmiIJH+gU/5MVysf5XoM6KjJsvkbIaXAmS/8HxXLA==}
+ dependencies:
+ css.escape: 1.5.1
+ he: 1.2.0
+ node-fetch: 2.6.7
+ webidl-conversions: 7.0.0
+ whatwg-encoding: 2.0.0
+ whatwg-mimetype: 3.0.0
+ transitivePeerDependencies:
+ - encoding
+ dev: false
+
/har-schema/2.0.0:
resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
engines: {node: '>=4'}
@@ -7108,7 +7102,6 @@ packages:
/har-validator/5.1.5:
resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
engines: {node: '>=6'}
- deprecated: this library is no longer supported
dependencies:
ajv: 6.12.6
har-schema: 2.0.0
@@ -7201,8 +7194,6 @@ packages:
/he/1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
- hasBin: true
- dev: true
/hexoid/1.0.0:
resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==}
@@ -7258,6 +7249,7 @@ packages:
/http-cache-semantics/4.1.0:
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
+ dev: false
/http-errors/2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
@@ -7305,7 +7297,7 @@ packages:
dependencies:
quick-lru: 5.1.1
resolve-alpn: 1.2.1
- dev: true
+ dev: false
/http2-wrapper/2.2.0:
resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==}
@@ -7409,7 +7401,6 @@ packages:
/import-local/3.1.0:
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
engines: {node: '>=8'}
- hasBin: true
dependencies:
pkg-dir: 4.2.0
resolve-cwd: 3.0.0
@@ -7455,7 +7446,6 @@ packages:
/install-artifact-from-github/1.3.2:
resolution: {integrity: sha512-yCFcLvqk0yQdxx0uJz4t9Z3adDMLAYrcGYv546uRXCSvxE+GqNYhhz/KmrGcUKGI/gVLR9n/e/zM9jX/+ASMJQ==}
- hasBin: true
dev: false
/internal-slot/1.0.3:
@@ -7628,7 +7618,6 @@ packages:
/is-ci/3.0.1:
resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
- hasBin: true
dependencies:
ci-info: 3.7.1
dev: true
@@ -7800,6 +7789,7 @@ packages:
/is-plain-obj/1.1.0:
resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
engines: {node: '>=0.10.0'}
+ dev: false
/is-plain-object/2.0.4:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
@@ -7844,7 +7834,7 @@ packages:
/is-stream/1.1.0:
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
engines: {node: '>=0.10.0'}
- dev: true
+ dev: false
/is-stream/2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
@@ -8017,7 +8007,6 @@ packages:
/jake/10.8.5:
resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==}
engines: {node: '>=10'}
- hasBin: true
dependencies:
async: 3.2.4
chalk: 4.1.2
@@ -8025,43 +8014,43 @@ packages:
minimatch: 3.1.2
dev: false
- /jest-changed-files/29.4.2:
- resolution: {integrity: sha512-Qdd+AXdqD16PQa+VsWJpxR3kN0JyOCX1iugQfx5nUgAsI4gwsKviXkpclxOK9ZnwaY2IQVHz+771eAvqeOlfuw==}
+ /jest-changed-files/29.4.3:
+ resolution: {integrity: sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
execa: 5.1.1
p-limit: 3.1.0
dev: true
- /jest-circus/29.4.2:
- resolution: {integrity: sha512-wW3ztp6a2P5c1yOc1Cfrt5ozJ7neWmqeXm/4SYiqcSriyisgq63bwFj1NuRdSR5iqS0CMEYwSZd89ZA47W9zUg==}
+ /jest-circus/29.4.3:
+ resolution: {integrity: sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.4.2
- '@jest/expect': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/environment': 29.4.3
+ '@jest/expect': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
chalk: 4.1.2
co: 4.6.0
dedent: 0.7.0
is-generator-fn: 2.1.0
- jest-each: 29.4.2
- jest-matcher-utils: 29.4.2
- jest-message-util: 29.4.2
- jest-runtime: 29.4.2
- jest-snapshot: 29.4.2
- jest-util: 29.4.2
+ jest-each: 29.4.3
+ jest-matcher-utils: 29.4.3
+ jest-message-util: 29.4.3
+ jest-runtime: 29.4.3
+ jest-snapshot: 29.4.3
+ jest-util: 29.4.3
p-limit: 3.1.0
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
slash: 3.0.0
stack-utils: 2.0.6
transitivePeerDependencies:
- supports-color
dev: true
- /jest-cli/29.4.2_@types+node@18.13.0:
- resolution: {integrity: sha512-b+eGUtXq/K2v7SH3QcJvFvaUaCDS1/YAZBYz0m28Q/Ppyr+1qNaHmVYikOrbHVbZqYQs2IeI3p76uy6BWbXq8Q==}
+ /jest-cli/29.4.3_@types+node@18.14.0:
+ resolution: {integrity: sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies:
@@ -8070,16 +8059,16 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/core': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/types': 29.4.2
+ '@jest/core': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/types': 29.4.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.10
import-local: 3.1.0
- jest-config: 29.4.2_@types+node@18.13.0
- jest-util: 29.4.2
- jest-validate: 29.4.2
+ jest-config: 29.4.3_@types+node@18.14.0
+ jest-util: 29.4.3
+ jest-validate: 29.4.3
prompts: 2.4.2
yargs: 17.6.2
transitivePeerDependencies:
@@ -8088,8 +8077,8 @@ packages:
- ts-node
dev: true
- /jest-config/29.4.2_@types+node@18.13.0:
- resolution: {integrity: sha512-919CtnXic52YM0zW4C1QxjG6aNueX1kBGthuMtvFtRTAxhKfJmiXC9qwHmi6o2josjbDz8QlWyY55F1SIVmCWA==}
+ /jest-config/29.4.3_@types+node@18.14.0:
+ resolution: {integrity: sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@types/node': '*'
@@ -8101,26 +8090,26 @@ packages:
optional: true
dependencies:
'@babel/core': 7.20.12
- '@jest/test-sequencer': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
- babel-jest: 29.4.2_@babel+core@7.20.12
+ '@jest/test-sequencer': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
+ babel-jest: 29.4.3_@babel+core@7.20.12
chalk: 4.1.2
ci-info: 3.7.1
deepmerge: 4.2.2
glob: 7.2.3
graceful-fs: 4.2.10
- jest-circus: 29.4.2
- jest-environment-node: 29.4.2
- jest-get-type: 29.4.2
- jest-regex-util: 29.4.2
- jest-resolve: 29.4.2
- jest-runner: 29.4.2
- jest-util: 29.4.2
- jest-validate: 29.4.2
+ jest-circus: 29.4.3
+ jest-environment-node: 29.4.3
+ jest-get-type: 29.4.3
+ jest-regex-util: 29.4.3
+ jest-resolve: 29.4.3
+ jest-runner: 29.4.3
+ jest-util: 29.4.3
+ jest-validate: 29.4.3
micromatch: 4.0.5
parse-json: 5.2.0
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
slash: 3.0.0
strip-json-comments: 3.1.1
transitivePeerDependencies:
@@ -8132,39 +8121,49 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
chalk: 4.1.2
- diff-sequences: 29.4.2
- jest-get-type: 29.4.2
- pretty-format: 29.4.2
+ diff-sequences: 29.4.3
+ jest-get-type: 29.4.3
+ pretty-format: 29.4.3
dev: true
- /jest-docblock/29.4.2:
- resolution: {integrity: sha512-dV2JdahgClL34Y5vLrAHde3nF3yo2jKRH+GIYJuCpfqwEJZcikzeafVTGAjbOfKPG17ez9iWXwUYp7yefeCRag==}
+ /jest-diff/29.4.3:
+ resolution: {integrity: sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ chalk: 4.1.2
+ diff-sequences: 29.4.3
+ jest-get-type: 29.4.3
+ pretty-format: 29.4.3
+ dev: true
+
+ /jest-docblock/29.4.3:
+ resolution: {integrity: sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
detect-newline: 3.1.0
dev: true
- /jest-each/29.4.2:
- resolution: {integrity: sha512-trvKZb0JYiCndc55V1Yh0Luqi7AsAdDWpV+mKT/5vkpnnFQfuQACV72IoRV161aAr6kAVIBpmYzwhBzm34vQkA==}
+ /jest-each/29.4.3:
+ resolution: {integrity: sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
chalk: 4.1.2
- jest-get-type: 29.4.2
- jest-util: 29.4.2
- pretty-format: 29.4.2
+ jest-get-type: 29.4.3
+ jest-util: 29.4.3
+ pretty-format: 29.4.3
dev: true
- /jest-environment-node/29.4.2:
- resolution: {integrity: sha512-MLPrqUcOnNBc8zTOfqBbxtoa8/Ee8tZ7UFW7hRDQSUT+NGsvS96wlbHGTf+EFAT9KC3VNb7fWEM6oyvmxtE/9w==}
+ /jest-environment-node/29.4.3:
+ resolution: {integrity: sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.4.2
- '@jest/fake-timers': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
- jest-mock: 29.4.2
- jest-util: 29.4.2
+ '@jest/environment': 29.4.3
+ '@jest/fake-timers': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
+ jest-mock: 29.4.3
+ jest-util: 29.4.3
dev: true
/jest-get-type/29.2.0:
@@ -8177,31 +8176,36 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
- /jest-haste-map/29.4.2:
- resolution: {integrity: sha512-WkUgo26LN5UHPknkezrBzr7lUtV1OpGsp+NfXbBwHztsFruS3gz+AMTTBcEklvi8uPzpISzYjdKXYZQJXBnfvw==}
+ /jest-get-type/29.4.3:
+ resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dev: true
+
+ /jest-haste-map/29.4.3:
+ resolution: {integrity: sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
'@types/graceful-fs': 4.1.6
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.10
- jest-regex-util: 29.4.2
- jest-util: 29.4.2
- jest-worker: 29.4.2
+ jest-regex-util: 29.4.3
+ jest-util: 29.4.3
+ jest-worker: 29.4.3
micromatch: 4.0.5
walker: 1.0.8
optionalDependencies:
fsevents: 2.3.2
dev: true
- /jest-leak-detector/29.4.2:
- resolution: {integrity: sha512-Wa62HuRJmWXtX9F00nUpWlrbaH5axeYCdyRsOs/+Rb1Vb6+qWTlB5rKwCCRKtorM7owNwKsyJ8NRDUcZ8ghYUA==}
+ /jest-leak-detector/29.4.3:
+ resolution: {integrity: sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- jest-get-type: 29.4.2
- pretty-format: 29.4.2
+ jest-get-type: 29.4.3
+ pretty-format: 29.4.3
dev: true
/jest-matcher-utils/29.3.1:
@@ -8211,17 +8215,17 @@ packages:
chalk: 4.1.2
jest-diff: 29.4.2
jest-get-type: 29.4.2
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
dev: true
- /jest-matcher-utils/29.4.2:
- resolution: {integrity: sha512-EZaAQy2je6Uqkrm6frnxBIdaWtSYFoR8SVb2sNLAtldswlR/29JAgx+hy67llT3+hXBaLB0zAm5UfeqerioZyg==}
+ /jest-matcher-utils/29.4.3:
+ resolution: {integrity: sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
chalk: 4.1.2
- jest-diff: 29.4.2
- jest-get-type: 29.4.2
- pretty-format: 29.4.2
+ jest-diff: 29.4.3
+ jest-get-type: 29.4.3
+ pretty-format: 29.4.3
dev: true
/jest-message-util/29.3.1:
@@ -8229,41 +8233,41 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/code-frame': 7.18.6
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
'@types/stack-utils': 2.0.1
chalk: 4.1.2
graceful-fs: 4.2.10
micromatch: 4.0.5
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
slash: 3.0.0
stack-utils: 2.0.6
dev: true
- /jest-message-util/29.4.2:
- resolution: {integrity: sha512-SElcuN4s6PNKpOEtTInjOAA8QvItu0iugkXqhYyguRvQoXapg5gN+9RQxLAkakChZA7Y26j6yUCsFWN+hlKD6g==}
+ /jest-message-util/29.4.3:
+ resolution: {integrity: sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/code-frame': 7.18.6
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
'@types/stack-utils': 2.0.1
chalk: 4.1.2
graceful-fs: 4.2.10
micromatch: 4.0.5
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
slash: 3.0.0
stack-utils: 2.0.6
dev: true
- /jest-mock/29.4.2:
- resolution: {integrity: sha512-x1FSd4Gvx2yIahdaIKoBjwji6XpboDunSJ95RpntGrYulI1ByuYQCKN/P7hvk09JB74IonU3IPLdkutEWYt++g==}
+ /jest-mock/29.4.3:
+ resolution: {integrity: sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
- jest-util: 29.4.2
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
+ jest-util: 29.4.3
dev: true
- /jest-pnp-resolver/1.2.3_jest-resolve@29.4.2:
+ /jest-pnp-resolver/1.2.3_jest-resolve@29.4.3:
resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
engines: {node: '>=6'}
peerDependencies:
@@ -8272,101 +8276,100 @@ packages:
jest-resolve:
optional: true
dependencies:
- jest-resolve: 29.4.2
+ jest-resolve: 29.4.3
dev: true
- /jest-regex-util/29.4.2:
- resolution: {integrity: sha512-XYZXOqUl1y31H6VLMrrUL1ZhXuiymLKPz0BO1kEeR5xER9Tv86RZrjTm74g5l9bPJQXA/hyLdaVPN/sdqfteig==}
+ /jest-regex-util/29.4.3:
+ resolution: {integrity: sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
- /jest-resolve-dependencies/29.4.2:
- resolution: {integrity: sha512-6pL4ptFw62rjdrPk7rRpzJYgcRqRZNsZTF1VxVTZMishbO6ObyWvX57yHOaNGgKoADtAHRFYdHQUEvYMJATbDg==}
+ /jest-resolve-dependencies/29.4.3:
+ resolution: {integrity: sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- jest-regex-util: 29.4.2
- jest-snapshot: 29.4.2
+ jest-regex-util: 29.4.3
+ jest-snapshot: 29.4.3
transitivePeerDependencies:
- supports-color
dev: true
- /jest-resolve/29.4.2:
- resolution: {integrity: sha512-RtKWW0mbR3I4UdkOrW7552IFGLYQ5AF9YrzD0FnIOkDu0rAMlA5/Y1+r7lhCAP4nXSBTaE7ueeqj6IOwZpgoqw==}
+ /jest-resolve/29.4.3:
+ resolution: {integrity: sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
chalk: 4.1.2
graceful-fs: 4.2.10
- jest-haste-map: 29.4.2
- jest-pnp-resolver: 1.2.3_jest-resolve@29.4.2
- jest-util: 29.4.2
- jest-validate: 29.4.2
+ jest-haste-map: 29.4.3
+ jest-pnp-resolver: 1.2.3_jest-resolve@29.4.3
+ jest-util: 29.4.3
+ jest-validate: 29.4.3
resolve: 1.22.1
resolve.exports: 2.0.0
slash: 3.0.0
dev: true
- /jest-runner/29.4.2:
- resolution: {integrity: sha512-wqwt0drm7JGjwdH+x1XgAl+TFPH7poowMguPQINYxaukCqlczAcNLJiK+OLxUxQAEWMdy+e6nHZlFHO5s7EuRg==}
+ /jest-runner/29.4.3:
+ resolution: {integrity: sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/console': 29.4.2
- '@jest/environment': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/transform': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/console': 29.4.3
+ '@jest/environment': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/transform': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.10
- jest-docblock: 29.4.2
- jest-environment-node: 29.4.2
- jest-haste-map: 29.4.2
- jest-leak-detector: 29.4.2
- jest-message-util: 29.4.2
- jest-resolve: 29.4.2
- jest-runtime: 29.4.2
- jest-util: 29.4.2
- jest-watcher: 29.4.2
- jest-worker: 29.4.2
+ jest-docblock: 29.4.3
+ jest-environment-node: 29.4.3
+ jest-haste-map: 29.4.3
+ jest-leak-detector: 29.4.3
+ jest-message-util: 29.4.3
+ jest-resolve: 29.4.3
+ jest-runtime: 29.4.3
+ jest-util: 29.4.3
+ jest-watcher: 29.4.3
+ jest-worker: 29.4.3
p-limit: 3.1.0
source-map-support: 0.5.13
transitivePeerDependencies:
- supports-color
dev: true
- /jest-runtime/29.4.2:
- resolution: {integrity: sha512-3fque9vtpLzGuxT9eZqhxi+9EylKK/ESfhClv4P7Y9sqJPs58LjVhTt8jaMp/pRO38agll1CkSu9z9ieTQeRrw==}
+ /jest-runtime/29.4.3:
+ resolution: {integrity: sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.4.2
- '@jest/fake-timers': 29.4.2
- '@jest/globals': 29.4.2
- '@jest/source-map': 29.4.2
- '@jest/test-result': 29.4.2
- '@jest/transform': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/environment': 29.4.3
+ '@jest/fake-timers': 29.4.3
+ '@jest/globals': 29.4.3
+ '@jest/source-map': 29.4.3
+ '@jest/test-result': 29.4.3
+ '@jest/transform': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
chalk: 4.1.2
cjs-module-lexer: 1.2.2
collect-v8-coverage: 1.0.1
glob: 7.2.3
graceful-fs: 4.2.10
- jest-haste-map: 29.4.2
- jest-message-util: 29.4.2
- jest-mock: 29.4.2
- jest-regex-util: 29.4.2
- jest-resolve: 29.4.2
- jest-snapshot: 29.4.2
- jest-util: 29.4.2
- semver: 7.3.8
+ jest-haste-map: 29.4.3
+ jest-message-util: 29.4.3
+ jest-mock: 29.4.3
+ jest-regex-util: 29.4.3
+ jest-resolve: 29.4.3
+ jest-snapshot: 29.4.3
+ jest-util: 29.4.3
slash: 3.0.0
strip-bom: 4.0.0
transitivePeerDependencies:
- supports-color
dev: true
- /jest-snapshot/29.4.2:
- resolution: {integrity: sha512-PdfubrSNN5KwroyMH158R23tWcAXJyx4pvSvWls1dHoLCaUhGul9rsL3uVjtqzRpkxlkMavQjGuWG1newPgmkw==}
+ /jest-snapshot/29.4.3:
+ resolution: {integrity: sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/core': 7.20.12
@@ -8375,23 +8378,23 @@ packages:
'@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12
'@babel/traverse': 7.20.12
'@babel/types': 7.20.7
- '@jest/expect-utils': 29.4.2
- '@jest/transform': 29.4.2
- '@jest/types': 29.4.2
+ '@jest/expect-utils': 29.4.3
+ '@jest/transform': 29.4.3
+ '@jest/types': 29.4.3
'@types/babel__traverse': 7.18.3
'@types/prettier': 2.7.2
babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12
chalk: 4.1.2
- expect: 29.4.2
+ expect: 29.4.3
graceful-fs: 4.2.10
- jest-diff: 29.4.2
- jest-get-type: 29.4.2
- jest-haste-map: 29.4.2
- jest-matcher-utils: 29.4.2
- jest-message-util: 29.4.2
- jest-util: 29.4.2
+ jest-diff: 29.4.3
+ jest-get-type: 29.4.3
+ jest-haste-map: 29.4.3
+ jest-matcher-utils: 29.4.3
+ jest-message-util: 29.4.3
+ jest-util: 29.4.3
natural-compare: 1.4.0
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
semver: 7.3.8
transitivePeerDependencies:
- supports-color
@@ -8401,52 +8404,64 @@ packages:
resolution: {integrity: sha512-wKnm6XpJgzMUSRFB7YF48CuwdzuDIHenVuoIb1PLuJ6F+uErZsuDkU+EiExkChf6473XcawBrSfDSnXl+/YG4g==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
+ chalk: 4.1.2
+ ci-info: 3.7.1
+ graceful-fs: 4.2.10
+ picomatch: 2.3.1
+ dev: true
+
+ /jest-util/29.4.3:
+ resolution: {integrity: sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
chalk: 4.1.2
ci-info: 3.7.1
graceful-fs: 4.2.10
picomatch: 2.3.1
dev: true
- /jest-validate/29.4.2:
- resolution: {integrity: sha512-tto7YKGPJyFbhcKhIDFq8B5od+eVWD/ySZ9Tvcp/NGCvYA4RQbuzhbwYWtIjMT5W5zA2W0eBJwu4HVw34d5G6Q==}
+ /jest-validate/29.4.3:
+ resolution: {integrity: sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.4.2
+ '@jest/types': 29.4.3
camelcase: 6.3.0
chalk: 4.1.2
- jest-get-type: 29.4.2
+ jest-get-type: 29.4.3
leven: 3.1.0
- pretty-format: 29.4.2
+ pretty-format: 29.4.3
dev: true
- /jest-watcher/29.4.2:
- resolution: {integrity: sha512-onddLujSoGiMJt+tKutehIidABa175i/Ays+QvKxCqBwp7fvxP3ZhKsrIdOodt71dKxqk4sc0LN41mWLGIK44w==}
+ /jest-watcher/29.4.3:
+ resolution: {integrity: sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/test-result': 29.4.2
- '@jest/types': 29.4.2
- '@types/node': 18.13.0
+ '@jest/test-result': 29.4.3
+ '@jest/types': 29.4.3
+ '@types/node': 18.14.0
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
- jest-util: 29.4.2
+ jest-util: 29.4.3
string-length: 4.0.2
dev: true
- /jest-worker/29.4.2:
- resolution: {integrity: sha512-VIuZA2hZmFyRbchsUCHEehoSf2HEl0YVF8SDJqtPnKorAaBuh42V8QsLnde0XP5F6TyCynGPEGgBOn3Fc+wZGw==}
+ /jest-worker/29.4.3:
+ resolution: {integrity: sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@types/node': 18.13.0
- jest-util: 29.4.2
+ '@types/node': 18.14.0
+ jest-util: 29.4.3
merge-stream: 2.0.0
supports-color: 8.1.1
dev: true
- /jest/29.4.2_@types+node@18.13.0:
- resolution: {integrity: sha512-+5hLd260vNIHu+7ZgMIooSpKl7Jp5pHKb51e73AJU3owd5dEo/RfVwHbA/na3C/eozrt3hJOLGf96c7EWwIAzg==}
+ /jest/29.4.3_@types+node@18.14.0:
+ resolution: {integrity: sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies:
@@ -8455,10 +8470,10 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/core': 29.4.2
- '@jest/types': 29.4.2
+ '@jest/core': 29.4.3
+ '@jest/types': 29.4.3
import-local: 3.1.0
- jest-cli: 29.4.2_@types+node@18.13.0
+ jest-cli: 29.4.3_@types+node@18.14.0
transitivePeerDependencies:
- '@types/node'
- supports-color
@@ -8511,7 +8526,6 @@ packages:
/js-yaml/3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
- hasBin: true
dependencies:
argparse: 1.0.10
esprima: 4.0.1
@@ -8519,7 +8533,6 @@ packages:
/js-yaml/3.7.0:
resolution: {integrity: sha512-eIlkGty7HGmntbV6P/ZlAsoncFLGsNoM27lkTzS+oneY/EiNhj+geqD9ezg/ip+SW6Var0BJU2JtV0vEUZpWVQ==}
- hasBin: true
dependencies:
argparse: 1.0.10
esprima: 2.7.3
@@ -8527,7 +8540,6 @@ packages:
/js-yaml/4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
- hasBin: true
dependencies:
argparse: 2.0.1
@@ -8576,7 +8588,7 @@ packages:
whatwg-encoding: 2.0.0
whatwg-mimetype: 3.0.0
whatwg-url: 11.0.0
- ws: 8.12.0
+ ws: 8.12.1
xml-name-validator: 4.0.0
transitivePeerDependencies:
- bufferutil
@@ -8587,11 +8599,11 @@ packages:
/jsesc/2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'}
- hasBin: true
dev: true
/json-buffer/3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: false
/json-parse-even-better-errors/2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
@@ -8614,7 +8626,6 @@ packages:
/json5/1.0.1:
resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==}
- hasBin: true
dependencies:
minimist: 1.2.7
dev: true
@@ -8622,7 +8633,6 @@ packages:
/json5/2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
- hasBin: true
/jsonc-parser/3.2.0:
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
@@ -8686,6 +8696,10 @@ packages:
resolution: {integrity: sha512-emiQ05haY9CRj1Ho/LiuCqr/+8RgJuWdiHYNglIg2Qjfz0n+pnUq9I2QHplXuOMO2EnAW1oCGC1++aU5VoWSlw==}
dev: false
+ /jssha/3.3.0:
+ resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
+ dev: false
+
/jstransformer/1.0.0:
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
dependencies:
@@ -8716,6 +8730,7 @@ packages:
resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==}
dependencies:
json-buffer: 3.0.1
+ dev: false
/kind-of/3.2.2:
resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
@@ -8970,7 +8985,7 @@ packages:
/lowercase-keys/2.0.0:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'}
- dev: true
+ dev: false
/lowercase-keys/3.0.0:
resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
@@ -8982,7 +8997,7 @@ packages:
dependencies:
pseudomap: 1.0.2
yallist: 2.1.2
- dev: true
+ dev: false
/lru-cache/5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -9090,8 +9105,8 @@ packages:
resolution: {integrity: sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==}
dev: false
- /matter-js/0.18.0:
- resolution: {integrity: sha512-/ZVem4WygUnbmo/iE4oHZpZS97btfBtYy5Iwn1396vUZU7YhgVEN8J4UWwfZwY1ZqoTYlPgjvSw9WXauuXL0mg==}
+ /matter-js/0.19.0:
+ resolution: {integrity: sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ==}
dev: false
/merge-stream/2.0.0:
@@ -9148,7 +9163,6 @@ packages:
/mime/3.0.0:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'}
- hasBin: true
dev: false
/mimic-fn/2.1.0:
@@ -9163,11 +9177,12 @@ packages:
/mimic-response/1.0.1:
resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
engines: {node: '>=4'}
- dev: true
+ dev: false
/mimic-response/3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
+ dev: false
/mimic-response/4.0.0:
resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==}
@@ -9189,6 +9204,13 @@ packages:
dependencies:
brace-expansion: 2.0.1
+ /minimatch/6.2.0:
+ resolution: {integrity: sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
/minimist/1.2.7:
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
@@ -9290,7 +9312,6 @@ packages:
/mkdirp/0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
- hasBin: true
dependencies:
minimist: 1.2.7
dev: false
@@ -9298,7 +9319,6 @@ packages:
/mkdirp/1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
- hasBin: true
dev: false
/mnemonist/0.39.5:
@@ -9324,7 +9344,6 @@ packages:
/msgpackr-extract/2.2.0:
resolution: {integrity: sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==}
- hasBin: true
requiresBuild: true
dependencies:
node-gyp-build-optional-packages: 5.0.3
@@ -9342,8 +9361,8 @@ packages:
optionalDependencies:
msgpackr-extract: 2.2.0
- /muggle-string/0.1.0:
- resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==}
+ /muggle-string/0.2.2:
+ resolution: {integrity: sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==}
dev: true
/multi-integer-range/3.0.0:
@@ -9375,7 +9394,6 @@ packages:
/nanoid/3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
/nanomatch/1.2.13:
resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==}
@@ -9438,7 +9456,6 @@ packages:
/needle/2.9.1:
resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==}
engines: {node: '>= 4.4.x'}
- hasBin: true
dependencies:
debug: 3.2.7
iconv-lite: 0.4.24
@@ -9506,18 +9523,15 @@ packages:
/node-gyp-build-optional-packages/5.0.3:
resolution: {integrity: sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==}
- hasBin: true
optional: true
/node-gyp-build/4.6.0:
resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
- hasBin: true
dev: false
/node-gyp/9.3.1:
resolution: {integrity: sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==}
engines: {node: ^12.13 || ^14.13 || >=16}
- hasBin: true
dependencies:
env-paths: 2.2.1
glob: 7.2.3
@@ -9554,7 +9568,6 @@ packages:
/nopt/5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
engines: {node: '>=6'}
- hasBin: true
dependencies:
abbrev: 1.1.1
dev: false
@@ -9563,7 +9576,6 @@ packages:
/nopt/6.0.0:
resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
- hasBin: true
dependencies:
abbrev: 1.1.1
dev: false
@@ -9606,7 +9618,7 @@ packages:
/normalize-url/6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
- dev: true
+ dev: false
/normalize-url/8.0.0:
resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==}
@@ -9625,7 +9637,7 @@ packages:
engines: {node: '>=4'}
dependencies:
path-key: 2.0.1
- dev: true
+ dev: false
/npm-run-path/4.0.1:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
@@ -9815,7 +9827,6 @@ packages:
/opentype.js/0.4.11:
resolution: {integrity: sha512-GthxucX/6aftfLdeU5Ho7o7zmQcC8uVtqdcelVq12X++ndxwBZG8Xb5rFEKT7nEcWDD2P1x+TNuJ70jtj1Mbpw==}
- hasBin: true
dev: false
/optionator/0.8.3:
@@ -9853,7 +9864,7 @@ packages:
engines: {node: '>=4'}
dependencies:
arch: 2.2.0
- dev: true
+ dev: false
/os-locale/1.4.0:
resolution: {integrity: sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==}
@@ -9870,10 +9881,16 @@ packages:
resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==}
dev: true
+ /otpauth/9.0.2:
+ resolution: {integrity: sha512-0TzpkJYg24VvIK3/K91HKpTtMlwm73UoThhcGY8fZsXcwHDrqf008rfdOjj3NnQuyuT11+vHyyO//qRzi6OZ9A==}
+ dependencies:
+ jssha: 3.3.0
+ dev: false
+
/p-cancelable/2.1.1:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
- dev: true
+ dev: false
/p-cancelable/3.0.0:
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
@@ -9883,6 +9900,7 @@ packages:
/p-finally/1.0.0:
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
engines: {node: '>=4'}
+ dev: false
/p-limit/2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
@@ -10049,7 +10067,7 @@ packages:
/path-key/2.0.1:
resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
engines: {node: '>=4'}
- dev: true
+ dev: false
/path-key/3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
@@ -10101,6 +10119,7 @@ packages:
/peek-readable/5.0.0:
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
engines: {node: '>=14.16'}
+ dev: false
/pend/1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@@ -10208,7 +10227,6 @@ packages:
/pino/8.8.0:
resolution: {integrity: sha512-cF8iGYeu2ODg2gIwgAHcPrtR63ILJz3f7gkogaHC/TXVVXxZgInmNYiIpDYEwgEkxZti2Se6P2W2DxlBIZe6eQ==}
- hasBin: true
dependencies:
atomic-sleep: 1.0.0
fast-redact: 3.1.2
@@ -10524,7 +10542,6 @@ packages:
/prebuild-install/7.1.1:
resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==}
engines: {node: '>=10'}
- hasBin: true
dependencies:
detect-libc: 2.0.1
expand-template: 2.0.3
@@ -10569,11 +10586,11 @@ packages:
react-is: 18.2.0
dev: true
- /pretty-format/29.4.2:
- resolution: {integrity: sha512-qKlHR8yFVCbcEWba0H0TOC8dnLlO4vPlyEjRPw31FZ2Rupy9nLa8ZLbYny8gWEl8CkEhJqAE6IzdNELTBVcBEg==}
+ /pretty-format/29.4.3:
+ resolution: {integrity: sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/schemas': 29.4.2
+ '@jest/schemas': 29.4.3
ansi-styles: 5.2.0
react-is: 18.2.0
dev: true
@@ -10685,14 +10702,13 @@ packages:
/ps-tree/1.2.0:
resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
engines: {node: '>= 0.10'}
- hasBin: true
dependencies:
event-stream: 3.3.4
dev: true
/pseudomap/1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
- dev: true
+ dev: false
/psl/1.9.0:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
@@ -10834,7 +10850,6 @@ packages:
/qrcode/1.5.1:
resolution: {integrity: sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg==}
engines: {node: '>=10.13.0'}
- hasBin: true
dependencies:
dijkstrajs: 1.0.2
encode-utf8: 1.0.3
@@ -10865,13 +10880,11 @@ packages:
/querystring/0.2.0:
resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==}
engines: {node: '>=0.4.x'}
- deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
dev: false
/querystring/0.2.1:
resolution: {integrity: sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==}
engines: {node: '>=0.4.x'}
- deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
dev: false
/querystringify/2.2.0:
@@ -10892,6 +10905,7 @@ packages:
/quick-lru/5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
+ dev: false
/random-seed/0.3.0:
resolution: {integrity: sha512-y13xtn3kcTlLub3HKWXxJNeC2qK4mB59evwZ5EkeRlolx+Bp2ztF7LbcZmyCnOqlHQrLnfuNbi1sVmm9lPDlDA==}
@@ -10914,7 +10928,6 @@ packages:
/rc/1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
- hasBin: true
dependencies:
deep-extend: 0.6.0
ini: 1.3.8
@@ -10990,6 +11003,7 @@ packages:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
+ dev: false
/readable-stream/4.3.0:
resolution: {integrity: sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==}
@@ -11006,6 +11020,7 @@ packages:
engines: {node: '>=8'}
dependencies:
readable-stream: 3.6.0
+ dev: false
/readdir-glob/1.1.2:
resolution: {integrity: sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==}
@@ -11185,7 +11200,6 @@ packages:
/request/2.88.2:
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
engines: {node: '>= 6'}
- deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
dependencies:
aws-sign2: 0.7.0
aws4: 1.12.0
@@ -11231,6 +11245,7 @@ packages:
/resolve-alpn/1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
+ dev: false
/resolve-cwd/3.0.0:
resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
@@ -11266,7 +11281,6 @@ packages:
/resolve-url/0.2.1:
resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
- deprecated: https://github.com/lydell/resolve-url#deprecated
dev: false
/resolve.exports/2.0.0:
@@ -11276,7 +11290,6 @@ packages:
/resolve/1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
- hasBin: true
dependencies:
is-core-module: 2.11.0
path-parse: 1.0.7
@@ -11286,7 +11299,7 @@ packages:
resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==}
dependencies:
lowercase-keys: 2.0.0
- dev: true
+ dev: false
/responselike/3.0.0:
resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==}
@@ -11327,14 +11340,12 @@ packages:
/rimraf/2.7.1:
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
- hasBin: true
dependencies:
glob: 7.2.3
dev: false
/rimraf/3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
- hasBin: true
dependencies:
glob: 7.2.3
@@ -11345,10 +11356,9 @@ packages:
seedrandom: 2.4.2
dev: false
- /rollup/3.14.0:
- resolution: {integrity: sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q==}
+ /rollup/3.17.2:
+ resolution: {integrity: sha512-qMNZdlQPCkWodrAZ3qnJtvCAl4vpQ8q77uEujVCCbC/6CLB7Lcmvjq7HyiOSnf4fxTT9XgsE36oLHJBH49xjqA==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
- hasBin: true
optionalDependencies:
fsevents: 2.3.2
dev: false
@@ -11413,8 +11423,8 @@ packages:
/safer-buffer/2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- /sanitize-html/2.9.0:
- resolution: {integrity: sha512-KY1hpSbqFNcpoLf+nP7iStbP5JfQZ2Nd19ZEE7qFsQqRdp+sO5yX/e5+HoG9puFAcSTEpzQuihfKUltDcLlQjg==}
+ /sanitize-html/2.10.0:
+ resolution: {integrity: sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==}
dependencies:
deepmerge: 4.2.2
escape-string-regexp: 4.0.0
@@ -11424,10 +11434,9 @@ packages:
postcss: 8.4.21
dev: false
- /sass/1.58.0:
- resolution: {integrity: sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==}
+ /sass/1.58.3:
+ resolution: {integrity: sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==}
engines: {node: '>=12.0.0'}
- hasBin: true
dependencies:
chokidar: 3.5.3
immutable: 4.2.2
@@ -11471,28 +11480,25 @@ packages:
/semver-regex/4.0.5:
resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==}
engines: {node: '>=12'}
- dev: true
+ dev: false
/semver-truncate/2.0.0:
resolution: {integrity: sha512-Rh266MLDYNeML5h90ttdMwfXe1+Nc4LAWd9X1KdJe8pPHP4kFmvLZALtsMNHNdvTyQygbEC0D59sIz47DIaq8w==}
engines: {node: '>=8'}
dependencies:
semver: 6.3.0
- dev: true
+ dev: false
/semver/5.7.1:
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
- hasBin: true
dev: false
/semver/6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
- hasBin: true
/semver/7.3.8:
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
engines: {node: '>=10'}
- hasBin: true
dependencies:
lru-cache: 6.0.0
@@ -11524,7 +11530,6 @@ packages:
/sha.js/2.4.11:
resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==}
- hasBin: true
dependencies:
inherits: 2.0.4
safe-buffer: 5.2.1
@@ -11550,7 +11555,7 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
shebang-regex: 1.0.0
- dev: true
+ dev: false
/shebang-command/2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
@@ -11561,7 +11566,7 @@ packages:
/shebang-regex/1.0.0:
resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
engines: {node: '>=0.10.0'}
- dev: true
+ dev: false
/shebang-regex/3.0.0:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
@@ -11694,13 +11699,14 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
sort-keys: 1.1.2
- dev: true
+ dev: false
/sort-keys/1.1.2:
resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==}
engines: {node: '>=0.10.0'}
dependencies:
is-plain-obj: 1.1.0
+ dev: false
/sortablejs/1.14.0:
resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
@@ -11712,7 +11718,6 @@ packages:
/source-map-resolve/0.5.3:
resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==}
- deprecated: See https://github.com/lydell/source-map-resolve#deprecated
dependencies:
atob: 2.1.2
decode-uri-component: 0.2.2
@@ -11737,7 +11742,6 @@ packages:
/source-map-url/0.4.1:
resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==}
- deprecated: See https://github.com/lydell/source-map-url#deprecated
dev: false
/source-map/0.5.7:
@@ -11752,11 +11756,10 @@ packages:
/source-map/0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
- dev: true
+ dev: false
/sourcemap-codec/1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
- deprecated: Please use @jridgewell/sourcemap-codec instead
/sparkles/1.0.1:
resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==}
@@ -11785,13 +11788,6 @@ packages:
resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==}
dev: false
- /speakeasy/2.0.0:
- resolution: {integrity: sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==}
- engines: {node: '>= 0.10.0'}
- dependencies:
- base32.js: 0.0.1
- dev: false
-
/split-string/3.1.0:
resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==}
engines: {node: '>=0.10.0'}
@@ -11820,7 +11816,6 @@ packages:
/sshpk/1.17.0:
resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==}
engines: {node: '>=0.10.0'}
- hasBin: true
dependencies:
asn1: 0.2.6
assert-plus: 1.0.0
@@ -11853,10 +11848,9 @@ packages:
/standard-as-callback/2.1.0:
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
- /start-server-and-test/1.15.3:
- resolution: {integrity: sha512-4GqkqghvUR9cJ8buvtgkyT0AHgVwCJ5EN8eDEhe9grTChGwWUxGm2nqfSeE9+0PZkLRdFqcwTwxVHe1y3ViutQ==}
+ /start-server-and-test/1.15.4:
+ resolution: {integrity: sha512-ucQtp5+UCr0m4aHlY+aEV2JSYNTiMZKdSKK/bsIr6AlmwAWDYDnV7uGlWWEtWa7T4XvRI5cPYcPcQgeLqpz+Tg==}
engines: {node: '>=6'}
- hasBin: true
dependencies:
arg: 5.0.2
bluebird: 3.7.2
@@ -11978,6 +11972,7 @@ packages:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
dependencies:
safe-buffer: 5.2.1
+ dev: false
/stringz/2.1.0:
resolution: {integrity: sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==}
@@ -12017,7 +12012,7 @@ packages:
/strip-eof/1.0.0:
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
engines: {node: '>=0.10.0'}
- dev: true
+ dev: false
/strip-final-newline/2.0.0:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
@@ -12041,7 +12036,7 @@ packages:
/strip-outer/2.0.0:
resolution: {integrity: sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dev: true
+ dev: false
/strnum/1.0.5:
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
@@ -12053,6 +12048,7 @@ packages:
dependencies:
'@tokenizer/token': 0.3.0
peek-readable: 5.0.0
+ dev: false
/supports-color/2.0.0:
resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
@@ -12100,8 +12096,6 @@ packages:
/svgo/0.7.2:
resolution: {integrity: sha512-jT/g9FFMoe9lu2IT6HtAxTA7RR2XOrmcrmCtGnyB/+GQnV6ZjNn+KOHZbZ35yL81+1F/aB6OeEsJztzBQ2EEwA==}
engines: {node: '>=0.10.0'}
- deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x.
- hasBin: true
dependencies:
coa: 1.0.4
colors: 1.1.2
@@ -12116,11 +12110,10 @@ packages:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
dev: false
- /systeminformation/5.17.8:
- resolution: {integrity: sha512-kMQsCOFQXqEjoDWKpYkC+ezJImrOnyTL3FZnYDZdWLTZcMW7Gomdp8zH9ztGlSo2L1iCAQXZ8HlV1bI8/Ts64g==}
+ /systeminformation/5.17.9:
+ resolution: {integrity: sha512-inxwRLI/4qpx4o85R54/zdhNagdBGBgs0la7Vl3qBorRVKRDk0nNsDTCGzG4lOITsw1gl7LRWeG4Zsp1pC8nfg==}
engines: {node: '>=8.0.0'}
os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
- hasBin: true
dev: false
/syuilo-password-strength/0.0.1:
@@ -12176,7 +12169,6 @@ packages:
/terser/5.16.1:
resolution: {integrity: sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==}
engines: {node: '>=10'}
- hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.2
acorn: 8.8.1
@@ -12358,6 +12350,7 @@ packages:
dependencies:
'@tokenizer/token': 0.3.0
ieee754: 1.2.1
+ dev: false
/tough-cookie/2.5.0:
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
@@ -12399,11 +12392,10 @@ packages:
engines: {node: '>=12'}
dependencies:
escape-string-regexp: 5.0.0
- dev: true
+ dev: false
/tsc-alias/1.8.2:
resolution: {integrity: sha512-ukBkcNekOgwtnSWYLD5QsMX3yQWg7JviAs8zg3qJGgu4LGtY3tsV4G6vnqvOXIDkbC+XL9vbhObWSpRA5/6wbg==}
- hasBin: true
dependencies:
chokidar: 3.5.3
commander: 9.5.0
@@ -12594,7 +12586,6 @@ packages:
/typescript/4.9.5:
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
engines: {node: '>=4.2.0'}
- hasBin: true
/uid/2.0.1:
resolution: {integrity: sha512-PF+1AnZgycpAIEmNtjxGBVmKbZAQguaa4pBUq6KNaGEcpzZ2klCNZLM34tsjp76maN00TttiiUf6zkIBpJQm2A==}
@@ -12605,7 +12596,6 @@ packages:
/ulid/2.3.0:
resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==}
- hasBin: true
dev: false
/unbox-primitive/1.0.2:
@@ -12754,7 +12744,6 @@ packages:
/urix/0.1.0:
resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
- deprecated: Please see https://github.com/lydell/urix#deprecated
dev: false
/url-parse/1.5.10:
@@ -12807,22 +12796,17 @@ packages:
/uuid/3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
- deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
- hasBin: true
dev: false
/uuid/8.0.0:
resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==}
- hasBin: true
dev: false
/uuid/8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
- hasBin: true
/uuid/9.0.0:
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
- hasBin: true
dev: false
/v8-to-istanbul/9.0.1:
@@ -12928,8 +12912,8 @@ packages:
replace-ext: 1.0.1
dev: false
- /vite/4.1.1_gyrp4zacqcjjrmgvdzgac5epyy:
- resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==}
+ /vite/4.1.2_hlkwzk2izwsolfmdrejei4vrty:
+ resolution: {integrity: sha512-MWDb9Rfy3DI8omDQySbMK93nQqStwbsQWejXRY2EBzEWKmLAXWb1mkI9Yw2IJrc+oCvPCI1Os5xSSIBYY6DEAw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:
@@ -12953,12 +12937,12 @@ packages:
terser:
optional: true
dependencies:
- '@types/node': 18.13.0
+ '@types/node': 18.14.0
esbuild: 0.16.17
postcss: 8.4.21
resolve: 1.22.1
- rollup: 3.14.0
- sass: 1.58.0
+ rollup: 3.17.2
+ sass: 1.58.3
optionalDependencies:
fsevents: 2.3.2
dev: false
@@ -12968,14 +12952,14 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
- /vue-eslint-parser/9.1.0_eslint@8.33.0:
+ /vue-eslint-parser/9.1.0_eslint@8.34.0:
resolution: {integrity: sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==}
engines: {node: ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '>=6.0.0'
dependencies:
debug: 4.3.4
- eslint: 8.33.0
+ eslint: 8.34.0
eslint-scope: 7.1.1
eslint-visitor-keys: 3.3.0
espree: 9.4.1
@@ -13009,14 +12993,14 @@ packages:
he: 1.2.0
dev: true
- /vue-tsc/1.0.24_typescript@4.9.5:
- resolution: {integrity: sha512-mmU1s5SAqE1nByQAiQnao9oU4vX+mSdsgI8H57SfKH6UVzq/jP9+Dbi2GaV+0b4Cn361d2ln8m6xeU60ApiEXg==}
+ /vue-tsc/1.1.4_typescript@4.9.5:
+ resolution: {integrity: sha512-CMG8KZsBBPyulYie05XxJCfq/yAPiB/uMMeHmog09aLm2Kml82C6tUSRgQz8ujM4JoCrpDqVCd9G0NuM9aLt1g==}
hasBin: true
peerDependencies:
typescript: '*'
dependencies:
- '@volar/vue-language-core': 1.0.24
- '@volar/vue-typescript': 1.0.24
+ '@volar/vue-language-core': 1.1.4
+ '@volar/vue-typescript': 1.1.4
typescript: 4.9.5
dev: true
@@ -13056,7 +13040,6 @@ packages:
/wait-on/7.0.1_debug@4.3.4:
resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==}
engines: {node: '>=12.0.0'}
- hasBin: true
dependencies:
axios: 0.27.2_debug@4.3.4
joi: 17.7.0
@@ -13076,7 +13059,6 @@ packages:
/web-push/3.5.0:
resolution: {integrity: sha512-JC0V9hzKTqlDYJ+LTZUXtW7B175qwwaqzbbMSWDxHWxZvd3xY0C2rcotMGDavub2nAAFw+sXTsqR65/KY2A5AQ==}
engines: {node: '>= 6'}
- hasBin: true
dependencies:
asn1.js: 5.4.1
http_ece: 1.1.0
@@ -13177,14 +13159,13 @@ packages:
/which/1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
- hasBin: true
dependencies:
isexe: 2.0.0
+ dev: false
/which/2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
- hasBin: true
dependencies:
isexe: 2.0.0
@@ -13243,8 +13224,8 @@ packages:
signal-exit: 3.0.7
dev: true
- /ws/8.12.0:
- resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==}
+ /ws/8.12.1:
+ resolution: {integrity: sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
@@ -13262,7 +13243,6 @@ packages:
/xml-js/1.6.11:
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
- hasBin: true
dependencies:
sax: 1.2.4
dev: false
@@ -13323,7 +13303,7 @@ packages:
/yallist/2.1.2:
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
- dev: true
+ dev: false
/yallist/3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
@@ -13445,8 +13425,8 @@ packages:
version: 2.2.1-misskey.3
dev: false
- github.com/misskey-dev/summaly/5684f116c92f1fd122badc7aee062494bdb43b36:
- resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/5684f116c92f1fd122badc7aee062494bdb43b36}
+ github.com/misskey-dev/summaly/51f3870e1ff5e0b22102e804112b10cb72f3c494:
+ resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/51f3870e1ff5e0b22102e804112b10cb72f3c494}
name: summaly
version: 3.0.4
dependencies: