Compare commits

..

107 Commits

Author SHA1 Message Date
943a1940e2 Merge branch 'develop' 2021-07-23 22:43:47 +09:00
15d166e30e 12.84.2 2021-07-23 22:43:34 +09:00
83619fda98 revert vue to 3.1.x 2021-07-23 22:43:24 +09:00
12913a16fd Merge branch 'develop' 2021-07-23 21:37:09 +09:00
e23ad7833d 12.84.1 2021-07-23 21:36:32 +09:00
38aa760b57 update vue 2021-07-23 21:36:30 +09:00
acb9244205 Merge branch 'develop' 2021-07-20 12:11:07 +09:00
3182606e99 12.84.0 2021-07-20 12:10:49 +09:00
7cc8646ad3 Update vue 2021-07-20 12:10:03 +09:00
e793fced61 New Crowdin updates (#7567)
* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations follow.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations follow.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations reaction.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations mute.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations timelines.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations keyboard-shortcut.md (Indonesian)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations timelines.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations stream.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Chinese Simplified)
2021-07-20 12:09:39 +09:00
248edb5dfd 🎨 2021-07-19 23:48:22 +09:00
9414a944b7 Tweak design 2021-07-19 23:31:41 +09:00
756b8a2a29 Make thickness of clock hands configuable 2021-07-19 23:31:27 +09:00
f142ed91fb Implement radio type for form dialog 2021-07-19 23:30:45 +09:00
6aef54a9e0 Improve component stability 2021-07-19 23:30:12 +09:00
f1c9e596e8 アイコンを四角で表示するオプション 2021-07-19 15:11:28 +09:00
862ddde0db Tweak style 2021-07-19 13:04:32 +09:00
ee5a060762 Fix stickyTop calculation 2021-07-19 13:00:29 +09:00
42d293ee60 Classic UI 2021-07-19 11:36:35 +09:00
04e27e160e 認証の修正 (#7597)
* authenticateのキャッシュを廃止

* 凍結ユーザーがサインイン出来てしまうのを修正

* 凍結ユーザーはストリーミング接続出来ないように

* 他人のアクセストークンはrevoke出来ないように, 正常削除を待機するように

* ユーザー/アクセストークンを無効化したらストリーミングを切断するように

* Revert TODO

* ストリーミングterminateは、ユーザー削除後に行うように

* signinでsuspendは別のエラーにする

* トークン再生成後のストリーミング切断は少し待つように

* サスペンド後のストリーミング切断はローカルユーザーのみに
2021-07-18 19:57:53 +09:00
62dede02ea API AuthenticateでDB接続エラーなどが発生するとログアウトさせられてしまうのを修正 Fix #7603 (#7604) 2021-07-18 00:53:16 +09:00
6d1d7b5366 Improve type 2021-07-17 15:43:07 +09:00
55e5c12441 Update deps 2021-07-17 13:43:09 +09:00
0b34503c8a Update check-hit-antenna.ts 2021-07-16 19:43:15 +09:00
dc69490e3a Refactoring 2021-07-15 20:45:32 +09:00
1c241776a6 Improve email notification 2021-07-15 20:35:43 +09:00
6812b895e7 Revert "Resolve #6811"
This reverts commit 558d288e7b.
2021-07-14 00:13:23 +09:00
ab439d0ed6 Clean up 2021-07-14 00:12:34 +09:00
c7a2c368d4 Custom CSS 2021-07-14 00:11:05 +09:00
2047860e71 Use unisonReload 2021-07-13 23:30:36 +09:00
1dbe03b210 refactor 2021-07-13 23:30:20 +09:00
b59a19c144 Fix #7576 2021-07-13 23:30:12 +09:00
558d288e7b Resolve #6811 2021-07-12 02:56:33 +09:00
e24c8b6878 Fix video (#7594) 2021-07-10 23:19:56 +09:00
1772af9583 AP Actorの修正 (#7573)
* AP Actorの修正

* Add ActivityPub test

* Fix person

* Test

* ap test

* Revert "Test"

This reverts commit 3c493eff4e89f94fd33f25189ba3bc96ef4366b3.

* Test comment

* fix

* fix

* Update inbox

* indent

* nl

* indent

* TODO

* Fix inbox

* Update test
2021-07-10 23:14:57 +09:00
cb42f94d9c Rich welcome content (#7588)
* Add rich content (polls, media) to the welcome page notes

* Add a simple scrolling animation to welcome page
2021-07-10 02:55:12 +09:00
38474c7316 mfm.jsが更新されたのでもうこのresolutionsはいらない (#7581) 2021-07-09 01:09:02 +09:00
49febe1764 Resolve #7165 2021-07-09 01:07:55 +09:00
65addc8206 refactoring 2021-07-01 00:50:19 +09:00
28f7e48dc6 improve type 2021-06-30 23:33:50 +09:00
d97fc9ce4e カスタム絵文字インポート時もemojiAddedイベントを発行するように 2021-06-23 13:42:02 +09:00
f26aeee819 Update theme.vue 2021-06-14 22:58:43 +09:00
c071467b6a テストがうごかないのを修正 (#7566)
* startServer

* typeorm 0.2.32

* Fix: chartのテストがテストの並び順によっては正しく初期化されない

* initTestDb
2021-06-12 22:40:17 +09:00
334ca01092 Update resolutions (#7572) 2021-06-12 22:32:44 +09:00
c122ec2e79 Update CONTRIBUTING.md (#7570) 2021-06-11 12:19:48 +09:00
d04014f875 Merge branch 'develop' 2021-06-10 14:03:28 +09:00
e1247b3e45 12.83.0 2021-06-10 14:03:19 +09:00
8b9c445fef New Crowdin updates (#7554)
* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations api.md (Korean)

* New translations mfm.md (Korean)

* New translations api.md (Korean)

* New translations timelines.md (Spanish)

* New translations timelines.md (Spanish)

* New translations timelines.md (Spanish)

* New translations theme.md (Spanish)

* New translations ja-JP.yml (Chinese Simplified)

* New translations theme.md (Spanish)

* New translations theme.md (Spanish)

* New translations theme.md (Spanish)

* New translations theme.md (Spanish)

* New translations theme.md (Spanish)

* New translations theme.md (Spanish)

* New translations stream.md (Spanish)

* New translations stream.md (Spanish)

* New translations stream.md (Spanish)

* New translations stream.md (Spanish)
2021-06-10 14:01:09 +09:00
a65eb502d2 fix api response definition 2021-06-08 14:26:52 +09:00
55c549a9f8 Remove entity descriptions
#6627
2021-06-08 14:24:21 +09:00
56600ba1df refactor type 2021-06-08 14:14:58 +09:00
6b312f755e Remove endpoint descriptions
#6627
2021-06-08 14:09:32 +09:00
d6267f797d 外部リンクアイコンが表示されない問題を修正 2021-06-08 12:19:55 +09:00
a2b8097b4b 歓迎ページでバナー画像が表示されない問題を修正 (#7559)
* 歓迎ページでバナー画像が表示されない問題

* revert

* 背景画像設定オプションを追加
2021-06-08 12:17:17 +09:00
22bbee1fa3 Update deps 2021-06-08 11:40:08 +09:00
fa1b38394c Updated divisions to math.div (#7549)
* Updated divisions to math.div on Reversi (game.board.vue)

* Update src/client/pages/reversi/game.board.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* Oops. Forgot to put it all through parenthesis

* Imported sass:math

* Fixes on drive.vue

* Forgot the stupid comma

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-06-05 14:57:52 +09:00
441790be2d Fix resync-remote-user (#7556)
* Fix resync-remote-user

* tune
2021-06-05 14:55:41 +09:00
5d66bb8794 ランダムにテストがコケるのを修正 (#7553)
* Test shutdown

* Revert "Test shutdown"

This reverts commit 85182e7dd196cdd9ecb46cfb50adaabd04c5ba60.

* Skip beforeShutdown in test

* Wait shutdown in test

* Revert "Skip beforeShutdown in test"

This reverts commit 79c33ab53615e8fa4820d2abfc2494cba55c441c.

* Revert "Revert "Skip beforeShutdown in test""

This reverts commit 3423133a137c79b64f3ff6ef9dbe433a441a47b0.
2021-06-05 14:54:07 +09:00
a5cdc9a1f4 Add missing migrations (#7552) 2021-06-04 20:40:47 +09:00
a5a2f9d01e Update misskey.js 2021-06-01 19:17:25 +09:00
89fb727f61 Update type.ts 2021-06-01 19:17:17 +09:00
929e545514 Merge branch 'develop' 2021-05-31 13:06:40 +09:00
3e7a87f75a 12.82.0 2021-05-31 13:06:25 +09:00
caf40e40fb Supports Array ActivityStreams type (#7536)
* Supports Array type

* Fix

* Fix Service to Note

* Update type.ts

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-05-31 13:04:13 +09:00
b608f63a1a New Crowdin updates (#7527)
* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Korean)
2021-05-31 12:02:13 +09:00
dc44d9a0a8 fix 2021-05-31 12:02:02 +09:00
bb926dd301 fix bug 2021-05-31 11:05:37 +09:00
79cb836483 Update deps 2021-05-31 11:05:34 +09:00
f1c4e4a10e fix style 2021-05-31 10:35:12 +09:00
798aedfc0f Supports Emoji 13.1 (#7539)
* Supports Emoji 13.1

* Fix regex
2021-05-30 20:52:39 +09:00
1077c2a637 🎨 2021-05-30 16:42:22 +09:00
cbe689607c Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-05-30 16:27:00 +09:00
948b70cb0f fix typo
Resolve #7540
2021-05-30 16:26:52 +09:00
0263539202 Fix remote drive expire (#7543) 2021-05-30 13:48:23 +09:00
52e54cf0dc refactor 2021-05-30 10:05:25 +09:00
24e7eeca0f fix local emoji detection
https://github.com/misskey-dev/misskey/pull/7526#discussion_r641886612
2021-05-30 10:05:12 +09:00
d76345264d fix bug 2021-05-28 22:57:04 +09:00
0eb115bf7e Resolve #7538 2021-05-28 22:53:00 +09:00
30d2a1d8b6 fix bug 2021-05-28 22:52:38 +09:00
857c88e8d6 fix type 2021-05-28 22:52:30 +09:00
ffb9646ce9 Add image description support (#7518)
* recieve image descriptions under the name property

* fix other components

* use comment for alt and title

* allow editing of file comment

* allow editing of file comment in note dialog

* federate note comments

* use file instead of this

* backend should accept comment on update

* update now actually accepts comment

* allow multiline descriptions

* image should also have description attached

* Update locales/ja-JP.yml

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>

* Use custom component with side-by-side image

* improve usability on mobile devices

* revert changes

* Update post-form-attaches.vue

* Update drive.file.vue

* Update media-caption.vue

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-05-28 09:38:09 +09:00
db3724cf33 improve types 2021-05-28 09:34:42 +09:00
466c083233 カスタム絵文字をproxyに通すように (#7526) 2021-05-27 22:40:48 +09:00
ae2267220b wip #7533 2021-05-27 17:15:08 +09:00
c92744c3d3 Create SECURITY.md 2021-05-24 05:50:45 +09:00
35f075b887 🎨 2021-05-23 21:28:41 +09:00
6cc4edc5e8 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-05-23 21:14:44 +09:00
c06091f78a Update README.md 2021-05-23 21:14:29 +09:00
f85399e355 Add Indonesian to index language (#7528)
Co-authored-by: Sandy Nicko Mac Corzeta <sandynicko@windowslive.com>
2021-05-23 18:57:33 +09:00
47aaf04481 Fix search-by-tag (#7531)
* Fix search-by-tag

* Revert "Fix search-by-tag"

This reverts commit c971d1d5d82f2d8b58fdec76e42f4404339ab83a.

* Fix typo

* Remove unused var

* インジェクションは[]を返すように
2021-05-23 18:57:12 +09:00
7063a6925f fix: Safariでもモーダルのぼかし効果が効くようにした (#7530)
https://github.com/misskey-dev/misskey/issues/7529
2021-05-23 18:55:21 +09:00
3cd04c4b81 Fix agent type (#7532) 2021-05-23 13:07:11 +09:00
942c802431 Merge branch 'develop' 2021-05-21 17:28:39 +09:00
e6754eb880 12.81.2 2021-05-21 17:28:19 +09:00
70d02cf1be Merge branch 'develop' 2021-05-21 17:27:47 +09:00
ef646b9576 12.81.1 2021-05-21 17:27:17 +09:00
ecd541873b Update node version 2021-05-21 17:27:09 +09:00
5d10642e07 New Crowdin updates (#7511)
* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Polish)

* New translations timelines.md (Polish)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations aiscript.md (Indonesian)

* New translations aiscript.md (Indonesian)

* New translations api.md (Indonesian)

* New translations api.md (Indonesian)

* New translations custom-emoji.md (Indonesian)

* New translations timelines.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations follow.md (Indonesian)

* New translations timelines.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations create-plugin.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations theme.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations stream.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations deck.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations theme.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations keyboard-shortcut.md (Indonesian)

* New translations pages.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations theme.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations reversi-bot.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Indonesian)
2021-05-21 17:20:45 +09:00
da34acd35f Resolve #6563 (#7524)
* Resolve #6563

* Update note.ts

* Update generate-visibility-query.ts
2021-05-21 14:13:03 +09:00
0108b8bfe3 Update deps 2021-05-20 12:27:50 +09:00
b16c3798a4 Fix Announce/Delete AP deliver (#7517)
* Fix Announce/Delete AP deliver

* Revert "Fix Announce/Delete AP deliver"

This reverts commit 0292c5196df48f67bb7914e925560ba69e2b2980.

* localOnlyのDeleteをdeliverしないように

* null Activityに対するUndoはdeliverしないように
2021-05-19 16:15:01 +09:00
4b33c42da7 Add queue timeout (#7519) 2021-05-19 16:12:31 +09:00
961b3177d5 Fix Agent type, httpでもDNSキャッシュ (#7520) 2021-05-19 16:11:47 +09:00
7dc85a624e Update preloaded JSON-LD (#7521) 2021-05-19 16:10:43 +09:00
bfd215542b @contextをちゃんと付ける (#7522) 2021-05-19 16:00:08 +09:00
d752275730 fix bug 2021-05-14 11:04:21 +09:00
be7e389bb5 Revert "fix bug"
This reverts commit 5b250c15f8.
2021-05-14 10:49:54 +09:00
473 changed files with 7542 additions and 4691 deletions

View File

@ -2,6 +2,6 @@
"extension": ["ts","js","cjs","mjs"],
"require": ["ts-node/register", "tsconfig-paths/register"],
"slow": 1000,
"timeout": 30000,
"timeout": 35000,
"exit": true
}

View File

@ -1 +1 @@
v16.0.0
v16.2.0

View File

@ -28,12 +28,7 @@ If your language is not listed in Crowdin, please open an issue.
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
## Internationalization (i18n)
Misskey uses the Vue.js plugin [Vue I18n](https://github.com/kazupon/vue-i18n).
Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/introduction.html .
## Documentation
* Documents for contributors are located in [`/docs`](/docs).
* Documents for instance admins are located in [`/docs`](/docs).
* Documents for end users are located in [`/src/docs`](/src/docs).
@ -41,8 +36,8 @@ Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/intr
* Test codes are located in [`/test`](/test).
## Continuous integration
Misskey uses CircleCI for executing automated tests.
Configuration files are located in [`/.circleci`](/.circleci).
Misskey uses GitHub Actions for executing automated tests.
Configuration files are located in [`/.github/workflows`](/.github/workflows).
## Adding MisskeyRoom items
* Use English for material, object and texture names.

View File

@ -6,10 +6,6 @@ And is distributed under The GNU Affero General Public License Version 3, you sh
Misskey includes several third-party Open-Source softwares.
Unicode emoji regular expressions by Twitter, Inc.
License: MIT
https://github.com/twitter/twemoji-parser/blob/master/LICENSE.md
Emoji keywords for Unicode 11 and below by Mu-An Chiou
License: MIT
https://github.com/muan/emojilib/blob/master/LICENSE

View File

@ -1,4 +1,4 @@
FROM node:16.0.0-alpine3.13 AS base
FROM node:16.2.0-alpine3.13 AS base
ENV NODE_ENV=production

View File

@ -99,6 +99,11 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
To receive updates of this repo, follow [@repo@misskey.io](https://misskey.io/@repo) on fediverse.
Related projects
----------------------------------------------------------------
- [misskey.js](https://github.com/misskey-dev/misskey.js) - Misskey SDK for JavaScript
- [mfm.js](https://github.com/misskey-dev/mfm.js) - MFM parser
:heart: Backers
----------------------------------------------------------------
<!-- PATREON_START -->

9
SECURITY.md Normal file
View File

@ -0,0 +1,9 @@
# Reporting Security Issues
If you discover a security issue in Misskey, please report it by sending an
email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
This will allow us to assess the risk, and make a fix available before we add a
bug report to the GitHub repository.
Thanks for helping make Misskey safe for everyone.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

View File

@ -4,7 +4,7 @@
import * as fs from 'fs';
import * as gulp from 'gulp';
import * as rimraf from 'rimraf';
import rimraf from 'rimraf';
const replace = require('gulp-replace');
const terser = require('gulp-terser');
const cssnano = require('gulp-cssnano');

View File

@ -259,8 +259,6 @@ monthX: "{month}"
yearX: "{year}"
pages: "الصفحات"
integration: "دمج"
connectSerice: "أوصل"
disconnectSerice: "قطع الاتصال"
enableLocalTimeline: "تفعيل الخيط المحلي"
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
disablingTimelinesInfo: "سيتمكن المسؤولون ومن تعديل دائمًا و من الوصول إلى جميع المخططات الزمنية ، حتى إذا لم يتم تمكينها."
@ -387,7 +385,6 @@ updateRemoteUser: "تحديث المعلومات عن المستخدم البع
deleteAllFiles: "حذف كافة الملفات"
userSuspended: "تم تعليق هذا المستخدم."
userSilenced: "تم إسكات هذا المستخدم."
sidebar: "الشريط الجانبي"
addItem: "إضافة عنصر"
rooms: "الغرفة"
relays: "المُرَحلات"
@ -432,6 +429,7 @@ user: "المستخدمون"
administration: "إدارة "
expiration: "ينتهي استطلاع الرأي في"
middle: "متوسط"
global: "الشامل"
_email:
_follow:
title: "يتابعك"
@ -444,9 +442,7 @@ _reversi:
total: "المجموع"
_channel:
featured: "المتداوَلة"
_sidebar:
full: "كامل"
icon: "الصورة الرمزية"
_menuDisplay:
hide: "إخفاء"
_theme:
explore: "استكشف قوالب المظهر"

View File

@ -269,8 +269,6 @@ monthX: "{month}"
yearX: "{year}"
pages: "Stránky"
integration: "Integrace"
connectSerice: "Připojit"
disconnectSerice: "Odpojit"
enableLocalTimeline: "Povolit lokální čas"
enableGlobalTimeline: "Povolit globální čas"
registration: "Registrace"
@ -392,7 +390,6 @@ script: "Skript"
deleteAllFiles: "Smazat všechny soubory"
deleteAllFilesConfirm: "Jste si jistí že chcete smazat všechny soubory?"
userSuspended: "Tomuto uživateli byl pozastaven účet."
sidebar: "Postranní panel"
addItem: "Přidat položku"
rooms: "Místnost"
inboxUrl: "Inbox URL"
@ -411,8 +408,6 @@ _mfm:
search: "Vyhledávání"
_reversi:
total: "Celkem"
_sidebar:
icon: "Avatar"
_theme:
keys:
mention: "Zmínění"

View File

@ -279,6 +279,7 @@ emptyDrive: "Drive ist leer"
emptyFolder: "Der Ordner ist leer"
unableToDelete: "Nicht löschbar"
inputNewFileName: "Gib einen neuen Dateinamen ein"
inputNewDescription: "Gib eine neue Beschreibung ein"
inputNewFolderName: "Gib einen neuen Ordnernamen ein"
circularReferenceFolder: "Der Zielordner ist ein Unterorder des Ordners, den du verschieben möchtest."
hasChildFilesOrFolders: "Dieser Ordner kann nicht gelöscht werden, da er nicht leer ist."
@ -310,8 +311,8 @@ monthX: "{month}"
yearX: "{year}"
pages: "Seiten"
integration: "Integration"
connectSerice: "Verbinden"
disconnectSerice: "Trennen"
connectService: "Verbinden"
disconnectService: "Trennen"
enableLocalTimeline: "Lokale Chronik aktivieren"
enableGlobalTimeline: "Globale Chronik aktivieren"
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer anderer Instanzen"
inMb: "In Megabytes"
iconUrl: "Icon-URL"
bannerUrl: "Banner-URL"
backgroundImageUrl: "Hintergrundbild-URL"
basicInfo: "Basisdaten"
pinnedUsers: "Angepinnte Benutzer"
pinnedUsersDescription: "Gib einen Benutzernamen pro Zeile ein. Diese werden im \"Erkunden\" Tab angezeigt."
@ -526,7 +528,7 @@ removeAllFollowing: "Allen gefolgten Benutzern entfolgen"
removeAllFollowingDescription: "Allen Benutzerkonten von {host} entfolgen. Bitte führe dies durch, falls diese Instanz nicht mehr existiert."
userSuspended: "Dieser Benutzer wurde gesperrt."
userSilenced: "Dieser Benutzer wurde instanzweit stummgeschaltet."
sidebar: "Seitenleiste"
menu: "Menü"
divider: "Trenner"
addItem: "Element hinzufügen"
rooms: "Raum"
@ -546,6 +548,8 @@ disablePlayer: "Video-Player schließen"
expandTweet: "Tweet ausklappen"
themeEditor: "Farbthemen-Editor"
description: "Beschreibung"
describeFile: "Beschreibung hinzufügen"
enterFileDescription: "Beschreibung eingeben"
author: "Autor"
leaveConfirm: "Es gibt unspeicherte Änderungen. Möchtest du diese verwerfen?"
manage: "Verwaltung"
@ -731,9 +735,11 @@ active: "Aktiv"
offline: "Offline"
notRecommended: "Nicht empfohlen"
botProtection: "Bot-Schutz"
instanceBlocking: "Blockierte Instanzen"
selectAccount: "Benutzerkonto auswählen"
enabled: "Aktiviert"
disabled: "Deaktiviert"
quickAction: "Schnellaktionen"
user: "Benutzer"
administration: "Verwaltung"
accounts: "Benutzerkonten"
@ -755,6 +761,10 @@ middle: "Mittel"
low: "Niedrig"
emailNotConfiguredWarning: "Keine Email-Adresse hinterlegt"
ratio: "Verhältnis"
customCss: "Benutzerdefiniertes CSS"
customCssWarn: "Verwende diese Einstellung nur, wenn du weißt, was sie tut. Ungültige Eingaben können dazu führen, dass der Client nicht mehr normal funktioniert."
global: "Global"
squareAvatars: "Profilbilder quadratisch anzeigen"
_ad:
back: "Zurück"
reduceFrequencyOfThisAd: "Diese Werbung weniger anzeigen"
@ -904,9 +914,10 @@ _channel:
following: "Gefolgt"
usersCount: "{n} Teilnehmer"
notesCount: "{n} Notizen"
_sidebar:
full: "Voll"
icon: "Symbole"
_menuDisplay:
sideFull: "Horizontal"
sideIcon: "Horizontal (Icons)"
top: "Oben"
hide: "Ausblenden"
_wordMute:
muteWords: "Wort stummschalten"

View File

@ -279,6 +279,7 @@ emptyDrive: "The drive is empty"
emptyFolder: "This folder is empty"
unableToDelete: "Unable to delete"
inputNewFileName: "Enter a new filename"
inputNewDescription: "Enter new caption"
inputNewFolderName: "Enter a new folder name"
circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
@ -310,8 +311,8 @@ monthX: "{month}"
yearX: "{year} /"
pages: "Pages"
integration: "Integration"
connectSerice: "Connect"
disconnectSerice: "Disconnect"
connectService: "Connect"
disconnectService: "Disconnect"
enableLocalTimeline: "Enable local timeline"
enableGlobalTimeline: "Enable global timeline"
disablingTimelinesInfo: "Admins and Mods will always have access to all timelines, even if they are not enabled."
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Drive capacity per remote user"
inMb: "In megabytes"
iconUrl: "Icon URL"
bannerUrl: "Banner image URL"
backgroundImageUrl: "Background image URL"
basicInfo: "Basic info"
pinnedUsers: "Pinned user"
pinnedUsersDescription: "List one username per line. Users listed here will be pinned under \"Explore\" tab."
@ -526,7 +528,7 @@ removeAllFollowing: "Withhold All Followings"
removeAllFollowingDescription: "Unfollow all accounts from {host}. Please run this if the instance no longer exists."
userSuspended: "This user has been suspended."
userSilenced: "This user has been silenced."
sidebar: "Sidebar"
menu: "Menu"
divider: "Divider"
addItem: "Add Item"
rooms: "Room"
@ -546,6 +548,8 @@ disablePlayer: "Close video player"
expandTweet: "Expand tweet"
themeEditor: "Theme editor"
description: "Description"
describeFile: "Add caption"
enterFileDescription: "Enter caption"
author: "Author"
leaveConfirm: "There are unsaved changes. Do you want to discard them?"
manage: "Management"
@ -757,6 +761,10 @@ middle: "Medium"
low: "Low"
emailNotConfiguredWarning: "Email address not set"
ratio: "Ratio"
customCss: "Custom CSS"
customCssWarn: "This setting should only be used if you know what it does. Entering improper values may cause the client to stop functioning normally."
global: "Global"
squareAvatars: "Display squared avatars"
_ad:
back: "Back"
reduceFrequencyOfThisAd: "Show this ad less"
@ -906,9 +914,10 @@ _channel:
following: "Followed"
usersCount: "{n} Participants"
notesCount: "{n} Notes"
_sidebar:
full: "Full"
icon: "Icons"
_menuDisplay:
sideFull: "Horizontal"
sideIcon: "Horizontal (Icons)"
top: "Top"
hide: "Hide"
_wordMute:
muteWords: "Word to mute"

337
locales/eo-UY.yml Normal file
View File

@ -0,0 +1,337 @@
---
_lang_: "Esperanto"
headlineMisskey: "Reto ligiĝas per notoj"
introMisskey: "Bonvenon! Miskejo estas malferma kodaの分散型マイクロブログサービスです。\nBonvolu Krei「noto」、いま起こっていることを共有したり、あなたについて皆に発信しよう📡\n「 reaktigoj 」機能で、皆のnotojに素早く反応を追加することもできます👍\n新しい世界を探検しよう🚀"
monthAndDay: "{day}-a/{month}"
search: "Serĉi"
notifications: "Sciigoj"
username: "Uzantonomo"
password: "Pasvorto"
forgotPassword: "Ĉu vi forgesis pasvorton?"
fetchingAsApObject: "Informpetado de fediverso..."
ok: "Okej"
gotIt: "Mi konprenas!"
cancel: "Nuligi"
enterUsername: "Entajpu uzantonomon"
renotedBy: "Renotigojn faras {user}"
noNotes: "Neniu noto!"
noNotifications: "Vi ne havas sciigojn."
instance: "Ekzemplo"
settings: "Agordoj"
basicSettings: "Ĝeneralaj agordoj"
otherSettings: "Aliaj agordoj"
openInWindow: "Malfermi en nova fenestro"
profile: "Profilo"
timeline: "Tempolinio"
login: "Ensaluti"
loggingIn: "Ensalutado..."
logout: "Elsaluti"
signup: "Krei konton"
uploading: "Alŝutado..."
save: "Konservi"
users: "Uzanto"
addUser: "Aldoni uzanton"
favorite: "Preferi"
favorites: "Preferataj"
unfavorite: "Malpreferi"
favorited: "Aldonita al preferatoj"
alreadyFavorited: "Jame aldonita al preferatoj"
cantFavorite: "Ne aldonita al preferatoj"
pin: "Alpingli sur la profilo"
unpin: "Depingli"
copyContent: "Kopii enhavon"
copyLink: "Kopii ligilon"
delete: "Forviŝi"
deleteAndEdit: "Forviŝi kaj redakti"
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forviŝi la noton? La reaktigoj, renotigoj, kaj respondoj ankaŭ forigiĝos."
addToList: "Aldoni al listo"
sendMessage: "Sendi mesaĝon"
copyUsername: "Kopii uzantonomon"
searchUser: "Serĉi uzanton"
reply: "Respondi"
loadMore: "Vidu plu"
showMore: "Vidi plu"
youGotNewFollower: "Vi estas eksekvita."
mention: "Mencioj"
mentions: "Mencioj"
directNotes: "Senperaj notoj"
importAndExport: "Importaĵo / Eksportaĵo"
import: "Importi"
export: "Eksporti"
files: "Dosieroj"
download: "Elŝuti"
driveFileDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la dosieron \"{name}\"? La notoj kun la aldonaĵo ankaŭ forviŝiĝos."
unfollowConfirm: "Ĉu vi certas, ke vi volas ne plu sekvi {name}?"
lists: "Listoj"
noLists: "Neniu listo"
note: "Elsendi noto"
notes: "Notoj"
following: "Sekvi"
followers: "Sekvantoj"
followsYou: "Sekvas vin"
createList: "Kreii liston"
error: "Eraro"
somethingHappened: "Problemo okazis."
retry: "Reprovi"
enterListName: "Entajpu nomon de la listo"
privacy: "Privateco"
follow: "Sekvi"
followRequest: "Peti eksekvi"
followRequests: "Eksekvopetoj"
unfollow: "Ne plu sekvi"
renote: "Renotici"
unrenote: "Forigi renotici"
cantRenote: "Tiu noto estas renototebla."
cantReRenote: "Renotigo ne estas renotigebla."
quote: "Citi"
pinnedNote: "Pinglita noto"
pinned: "Alpingli sur la profilo"
you: "Vi"
clickToShow: "Klaku por malkaŝu"
sensitive: "Enhavo ne estas deca por laborejo (NSFW)"
add: "Aldoni"
reaction: "Reagoj"
enterFileName: "Entajpu dosiernomon"
mute: "Silentigi"
unmute: "Malsilentigi"
block: "Bloki"
unblock: "Malbloki"
suspend: "Flostigi"
unsuspend: "Fandi"
blockConfirm: "Ĉu vi certas ke vi volas bloki la uzanton?"
unblockConfirm: "Ĉu vi certas ke vi volas malbloki la uzanton?"
suspendConfirm: "Ĉu vi certas ke vi volas frostigi la uzanton?"
unsuspendConfirm: "Ĉu vi certas ke vi volas fandi la uzanton?"
selectList: "Elekti liston"
emojiUrl: "Retadreso de la emoĵio"
flagAsBot: "Tiu uzanto estas roboto"
flagAsCat: "Tiu uzanto estas kato"
addAccount: "Aldoni konton"
showOnRemote: "Vidi sur la transa ekzemplo"
general: "Ĝenerala"
searchWith: "Serĉi: {q}"
youHaveNoLists: "Vi ne havas listojn."
followConfirm: "Ĉu vi certas, ke vi volas sekvi {name}'n?"
selectUser: "Elekti uzanton"
annotation: "Komentarioj"
federation: "Fediverso"
instances: "Ekzemplo"
blockThisInstance: "Bloki tiu ekzemplo"
disk: "Diskilo"
blockedInstances: "Blokitaj ekzemploj"
muteAndBlock: "Silentitaj / Blokitaj"
mutedUsers: "Silentigitaj uzantoj"
blockedUsers: "Blokitaj uzantoj"
noUsers: "Sen uzantoj"
editProfile: "Redakti profilon"
noteDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la noton?"
pinLimitExceeded: "Vi ne plu povas alpingli noton."
noCustomEmojis: "Neniu emoĵio"
federating: "Konfederado"
blocked: "Blokita"
subscribing: "Abonita"
notResponding: "Alvokato ne disponeblas"
instanceFollowing: "Sekvi ekzemplon"
instanceFollowers: "Sekvantoj de la ekzemplo"
instanceUsers: "Uzantoj de la ekzemplo"
changePassword: "Ŝanĝi pasvorton"
currentPassword: "Aktuala pasvorto"
newPassword: "Nova pasvorto"
newPasswordRetype: "Reentajpu la novan pasvorton"
attachFile: "Aldoni dosieron"
more: "Plu!"
usernameOrUserId: "Uzantonomo aŭ ID de uzanto"
noSuchUser: "Neniuj uzantoj trovitaj."
remove: "Forviŝi"
removed: "Forviŝis"
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
deleteAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
messaging: "Babilejoj"
upload: "Alŝuti"
fromDrive: "De la diskilo"
fromUrl: "De retadreso"
uploadFromUrl: "Aldoni de retadreso"
uploadFromUrlDescription: "Retadreso de la dosiero kiun vi volu alŝuti"
games: "Ludoj sur Miskejo"
messageRead: "Legita"
startMessaging: "Komenci babiladon"
tos: "Kondiĉoj de Uzado"
start: "Komenciĝi"
home: "Ĉefpaĝo"
drive: "Diskilo"
fileName: "Dosiernomo"
selectFile: "Elekti dosieron"
selectFiles: "Elekti dosieron"
renameFile: "Renomigi dosieron"
deleteFolder: "Forviŝi dosierujon"
addFile: "Aldoni dosieron"
emptyDrive: "La diskilo enhavas neniun."
unableToDelete: "Ne forigebla"
inputNewFileName: "Entajpu nova dosiernomon"
hasChildFilesOrFolders: "La dosierujo estas neforviŝebla pro tio, ke ĝi enhavas dosieron."
copyUrl: "Kopii retadreson"
nsfw: "Enhavo ne estas deca por laborejo (NSFW)"
instanceName: "Nomo de la ekzemplo"
connectService: "Konekti"
disconnectService: "Farkonektiĝi"
driveCapacityPerLocalAccount: "Volumo po unu loka-uzanto"
driveCapacityPerRemoteAccount: "Volumo po unu transa uzanto"
pinnedUsers: "Alpinglita uzanto"
pinnedNotes: "Pinglita noto"
withFileAntenna: "Nur kun aldonaĵo"
notesAndReplies: "Kun respondoj"
withFiles: "Kun aldonaĵo"
silenceConfirm: "Ĉu vi certas ke vi volas silentigi la uzanton?"
unsilenceConfirm: "Ĉu vi certas ke vi volas malsilentigi la uzanton?"
userList: "Listoj"
aboutMisskey: "Pri Miskejo"
passwordLessLogin: "Ensaluti sen pasvorto"
resetPassword: "Restarigi pasvorton"
newPasswordIs: "La nova pasvorto estas {password}."
inputMessageHere: "Entajpu masaĝo tie ĉi"
noteOf: "Noto de {user}"
newMessageExists: "Vi ricevis novan mesaĝon."
onlyOneFileCanBeAttached: "Vi povas aldoni nur unu dosieron po unu mesaĝo."
uiLanguage: "Lingvo de la interfaco"
noFollowRequests: "Vi ne havas eksekvopetojn."
local: "Loka"
remote: "Transa"
hideThisNote: "Kaŝi tiun noton"
deleteAllFiles: "Forvisi ĉiujn dosierojn"
deleteAllFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn viajn dosierojn?"
invisibleNote: "Malpublika noto"
emailServer: "Retpoŝta servilo"
email: "Retpoŝto"
emailAddress: "Retpoŝtadreso"
smtpUser: "Uzantonomo"
smtpPass: "Pasvorto"
userSaysSomething: "{name} parolis ion"
database: "Datumbazo"
channel: "Kanalo"
fileIdOrUrl: "Dosirero ID aŭ retadreso"
send: "Sendi"
i18nInfo: "Tradukojn de Misskey en diversaj lingvoj faras volontuloj. Vi povus kunlabori en tradukado sur {link}, se vi volus."
driveFilesCount: "Numero de dosieroj en la diskilo"
onlineUsersCount: "{n} uzanto(j) estas surkonektita"
nUsers: "{n} uzanto(j)"
emailNotification: "Sciigoj per retpoŝto"
publish: "Publikigi"
inChannelSearch: "Serĉi en kanalo"
typingUsers: "{users} estas entajpanta(j)..."
online: "Surkonektita"
offline: "Forkonektita"
instanceBlocking: "Ekzempla blokado"
user: "Uzanto"
_gallery:
liked: "Ŝatitaj notoj"
_email:
_follow:
title: "Vi estas eksekvita."
_receiveFollowRequest:
title: "Vi ricevis eksekvopeton."
_aboutMisskey:
about: "Misskey estas malferma koda programo evoluigata far syuilo ekde la 2014."
source: "Fontkodo"
translation: "Traduki Misskey'on"
_mfm:
mention: "Mencioj"
url: "Retadreso"
blockCode: "Kodo (Ujo)"
blockMath: "Formulo (Ujo)"
quote: "Citi"
search: "Serĉi"
_instanceTicker:
none: "Ne montri"
remote: "Montri al transaj uzantoj"
_channel:
create: "Krei kanalon"
edit: "Redakti kanalon"
following: "Sekvaton"
_theme:
keys:
mention: "Mencioj"
renote: "Renotici"
_sfx:
note: "Nova noto"
notification: "Sciigoj"
chat: "Babilejoj"
channel: "Kanala sciigoj"
_tutorial:
title: "Uzado de Miskejo"
_permissions:
"read:blocks": "Vidi la listo de la uzantoj kiun vi blokis."
"read:drive": "Vidi dosierojn en la diskilo"
"read:channels": "Legi kanalon"
_widgets:
notifications: "Sciigoj"
timeline: "Tempolinio"
federation: "Fediverso"
onlineUsers: "Surkonektita uzanto"
_cw:
show: "Vidu plu"
files: "{count} dosiero(j)"
_visibility:
publicDescription: "Via noto aperiĝos sur konfederacia tempolinio"
home: "Ĉefpaĝo"
homeDescription: "Elsendi nur sur hejma tempolinio"
followers: "Sekvantoj"
followersDescription: "Elsendi nur al sekvantoj de mi"
localOnly: "Nur loka"
localOnlyDescription: "Nelegabla al transaj uzantoj"
_postForm:
channelPlaceholder: "Elsendi sur la kanalo"
_profile:
username: "Uzantonomo"
_exportOrImport:
followingList: "Sekvi"
muteList: "Silentigi"
blockingList: "Blokado"
userLists: "Listoj"
_timelines:
home: "Hejmo"
local: "Loka"
social: "Hejmo kaj loka"
_rooms:
_furnitures:
server: "Servilo"
_pages:
content: "Blokado de paĝo"
url: "Retadreso de la paĝo"
chooseBlock: "Aldoni blokado"
script:
categories:
list: "Listoj"
blocks:
_join:
arg1: "Listoj"
_randomPick:
arg1: "Listoj"
_dailyRandomPick:
arg1: "Listoj"
_seedRandomPick:
arg2: "Listoj"
pick: "Elekti de la listo"
_pick:
arg1: "Listoj"
_listLen:
arg1: "Listoj"
types:
array: "Listoj"
_notification:
fileUploaded: "La dosiero sukcese alŝutiĝis."
youWereFollowed: "Vi estas eksekvita."
youReceivedFollowRequest: "Vi ricevis eksekvopeton."
yourFollowRequestAccepted: "Via eksekvopeto estas akceptita."
_types:
follow: "Sekvi"
mention: "Mencioj"
renote: "Renotici"
quote: "Citi"
reaction: "Reagoj"
receiveFollowRequest: "Eksekvopeto ricevita"
_deck:
_columns:
notifications: "Sciigoj"
tl: "Tempolinio"
list: "Listoj"
mentions: "Mencioj"

View File

@ -309,8 +309,6 @@ monthX: "Mes {month}"
yearX: "Año {year}"
pages: "Páginas"
integration: "Integración"
connectSerice: "Conectarse"
disconnectSerice: "Desconectarse"
enableLocalTimeline: "Habilitar linea de tiempo local"
enableGlobalTimeline: "Habilitar linea de tiempo global"
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia el administrador y los moderadores pueden seguir usándolos"
@ -525,7 +523,6 @@ removeAllFollowing: "Retener todos los siguientes"
removeAllFollowingDescription: "Cancelar todos los siguientes del servidor {host}. Ejecutar en caso de que esta instancia haya dejado de existir"
userSuspended: "Este usuario ha sido suspendido."
userSilenced: "Este usuario ha sido silenciado."
sidebar: "Barra lateral"
divider: "Divisor"
addItem: "Agregar elemento"
rooms: "Cuartos"
@ -667,6 +664,7 @@ user: "Usuarios"
administration: "Administrar"
expiration: "Termina el"
middle: "Mediano"
global: "Global"
_ad:
back: "Deseleccionar"
_gallery:
@ -746,9 +744,7 @@ _channel:
following: "Siguiendo"
usersCount: "{n} participantes"
notesCount: "{n} notas"
_sidebar:
full: "Completo"
icon: "Avatar"
_menuDisplay:
hide: "Ocultar"
_wordMute:
muteWords: "Palabras que silenciar"

View File

@ -279,6 +279,7 @@ emptyDrive: "Le Drive est vide"
emptyFolder: "Le dossier est vide"
unableToDelete: "Suppression impossible"
inputNewFileName: "Entrez un nouveau nom de fichier"
inputNewDescription: "Veuillez entrer une nouvelle description"
inputNewFolderName: "Entrez un nouveau nom de dossier"
circularReferenceFolder: "Le dossier de destination est un sous-dossier du dossier que vous souhaitez déplacer."
hasChildFilesOrFolders: "Impossible de supprimer ce dossier car il n'est pas vide."
@ -310,8 +311,8 @@ monthX: "{month}"
yearX: "{year}"
pages: "Pages"
integration: "Intégrations"
connectSerice: "Connecter"
disconnectSerice: "Déconnecter"
connectService: "Connexion"
disconnectService: "Déconnexion"
enableLocalTimeline: "Activer le fil local"
enableGlobalTimeline: "Activer le fil global"
disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s et les modérateur·rice·s pourront toujours y accéder."
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant"
inMb: "en mégaoctets"
iconUrl: "URL de l'icône"
bannerUrl: "URL de limage de la bannière"
backgroundImageUrl: "URL de l'image d'arrière-plan"
basicInfo: "Informations basiques"
pinnedUsers: "Utilisateur·rice épinglé·e"
pinnedUsersDescription: "Listez les utilisateur·rice·s que vous souhaitez voir épinglé·e·s sur la page \"Découvrir\", un·e par ligne."
@ -526,7 +528,6 @@ removeAllFollowing: "Retenir tous les abonnements"
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action uniquement si linstance nexiste plus."
userSuspended: "Cet·te utilisateur·rice a été suspendu·e."
userSilenced: "Cette utilisateur·trice a été mis·e en sourdine."
sidebar: "Barre latérale"
divider: "Séparateur"
addItem: "Ajouter un élément"
rooms: "Chambre"
@ -546,6 +547,8 @@ disablePlayer: "Fermer le lecteur vidéo"
expandTweet: "Étendre le tweet"
themeEditor: "Éditeur de thèmes"
description: "Description"
describeFile: "Ajouter une description d'image"
enterFileDescription: "Saisissez une description"
author: "Auteur·rice"
leaveConfirm: "Vous avez des modifications non-sauvegardées. Voulez-vous les ignorer ?"
manage: "Gestion"
@ -757,6 +760,7 @@ middle: "Moyen"
low: "Basse"
emailNotConfiguredWarning: "Vous n'avez pas configuré d'adresse e-mail."
ratio: "Ratio"
global: "Global"
_ad:
back: "Retour"
reduceFrequencyOfThisAd: "Voir cette publicité moins souvent"
@ -906,9 +910,7 @@ _channel:
following: "Abonné·e"
usersCount: "{n} Participant·e·s"
notesCount: "{n} Notes"
_sidebar:
full: "Complet"
icon: "Icônes"
_menuDisplay:
hide: "Masquer"
_wordMute:
muteWords: "Mots à filtrer"

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@ const languages = [
'en-US',
'es-ES',
'fr-FR',
'id-ID',
'ja-JP',
'ja-KS',
'kab-KAB',

View File

@ -274,6 +274,7 @@ emptyDrive: "Il Drive è vuoto"
emptyFolder: "La cartella è vuota"
unableToDelete: "Eliminazione impossibile"
inputNewFileName: "Inserisci nome del nuovo file"
inputNewDescription: "Inserisci una nuova descrizione"
inputNewFolderName: "Inserisci nome della nuova cartella"
circularReferenceFolder: "La cartella di destinazione è una sottocartella della cartella che vuoi spostare."
hasChildFilesOrFolders: "Impossibile eliminare la cartella perché non è vuota"
@ -305,8 +306,8 @@ monthX: "{month}"
yearX: "{year}"
pages: "Pagine"
integration: "App collegate"
connectSerice: "Connetti"
disconnectSerice: "Disconnetti"
connectService: "Connessione"
disconnectService: "Disconnessione "
enableLocalTimeline: "Abilita Timeline locale"
enableGlobalTimeline: "Abilita Timeline federata"
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e i moderatori potranno sempre accederci."
@ -513,7 +514,6 @@ removeAllFollowing: "Cancella tutti i follows"
removeAllFollowingDescription: "Cancella tutti i follows del server {host}. Per favore, esegui se, ad esempio, l'istanza non esiste più."
userSuspended: "L'utente è sospes@."
userSilenced: "L'utente è silenziat@."
sidebar: "Barra laterale"
divider: "Linea di separazione"
addItem: "Aggiungi elemento"
rooms: "Camera"
@ -533,6 +533,8 @@ disablePlayer: "Chiudi lettore video"
expandTweet: "Espandi tweet"
themeEditor: "Editor di temi"
description: "Descrizione"
describeFile: "Aggiungi una descrizione d'immagine"
enterFileDescription: "Inserisci descrizione"
author: "Autore"
leaveConfirm: "Ci sono delle modifiche ancora non salvate. Vuoi cancellarle?"
manage: "Gestione"
@ -738,6 +740,7 @@ middle: "Media"
low: "Bassa"
emailNotConfiguredWarning: "Non hai impostato nessun indirizzo e-mail."
ratio: "Rapporto"
global: "Federata"
_ad:
back: "Indietro"
reduceFrequencyOfThisAd: "Visualizza questa pubblicità meno spesso"
@ -822,9 +825,7 @@ _channel:
following: "Seguiti"
usersCount: "{n} partecipanti"
notesCount: "{n} note"
_sidebar:
full: "Intera"
icon: "Icone"
_menuDisplay:
hide: "Nascondere"
_wordMute:
muteWords: "Parole da filtrare"

View File

@ -279,6 +279,7 @@ emptyDrive: "ドライブは空です"
emptyFolder: "フォルダーは空です"
unableToDelete: "削除できません"
inputNewFileName: "新しいファイル名を入力してください"
inputNewDescription: "新しいキャプションを入力してください"
inputNewFolderName: "新しいフォルダ名を入力してください"
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
hasChildFilesOrFolders: "このフォルダは空でないため、削除できません。"
@ -310,8 +311,8 @@ monthX: "{month}月"
yearX: "{year}年"
pages: "ページ"
integration: "連携"
connectSerice: "接続する"
disconnectSerice: "切断する"
connectService: "接続する"
disconnectService: "切断する"
enableLocalTimeline: "ローカルタイムラインを有効にする"
enableGlobalTimeline: "グローバルタイムラインを有効にする"
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのド
inMb: "メガバイト単位"
iconUrl: "アイコン画像のURL (faviconなど)"
bannerUrl: "バナー画像のURL"
backgroundImageUrl: "背景画像のURL"
basicInfo: "基本情報"
pinnedUsers: "ピン留めユーザー"
pinnedUsersDescription: "「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。"
@ -526,7 +528,7 @@ removeAllFollowing: "フォローを全解除"
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
userSuspended: "このユーザーは凍結されています。"
userSilenced: "このユーザーはサイレンスされています。"
sidebar: "サイドバー"
menu: "メニュー"
divider: "分割線"
addItem: "項目を追加"
rooms: "ルーム"
@ -546,6 +548,8 @@ disablePlayer: "プレイヤーを閉じる"
expandTweet: "ツイートを展開する"
themeEditor: "テーマエディター"
description: "説明"
describeFile: "キャプションを付ける"
enterFileDescription: "キャプションを入力"
author: "作者"
leaveConfirm: "未保存の変更があります。破棄しますか?"
manage: "管理"
@ -757,6 +761,10 @@ middle: "中"
low: "低"
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
ratio: "比率"
customCss: "カスタムCSS"
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
global: "グローバル"
squareAvatars: "アイコンを四角形で表示"
_ad:
back: "戻る"
@ -920,9 +928,10 @@ _channel:
usersCount: "{n}人が参加中"
notesCount: "{n}投稿があります"
_sidebar:
full: "フル"
icon: "アイコン"
_menuDisplay:
sideFull: ""
sideIcon: "横(アイコン)"
top: "上部"
hide: "隠す"
_wordMute:

View File

@ -308,8 +308,6 @@ monthX: "{month}月"
yearX: "{year}年"
pages: "ページ"
integration: "連携"
connectSerice: "つなぐ"
disconnectSerice: "切ってまう"
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
@ -513,7 +511,6 @@ removeAllFollowing: "フォローを全解除"
removeAllFollowingDescription: "{host}からのフォローをすべて解除するで。そのインスタンスが消えて無くなった時とかには便利な機能やで。"
userSuspended: "このユーザーは...凍結されとる。"
userSilenced: "このユーザーは...サイレンスされとる。"
sidebar: "サイドバー"
divider: "分割線"
rooms: "ルーム"
relays: "リレー"
@ -649,6 +646,7 @@ memo: "メモ"
high: "高い"
middle: "中"
low: "低い"
global: "グローバル"
_ad:
back: "戻る"
_gallery:
@ -733,9 +731,7 @@ _channel:
removeBanner: "バナーを削除"
featured: "トレンド"
notesCount: "{n}こ投稿があるで"
_sidebar:
full: "フル"
icon: "アイコン"
_menuDisplay:
hide: "隠す"
_wordMute:
soft: "ソフト"

1
locales/jbo-EN.yml Normal file
View File

@ -0,0 +1 @@
---

View File

@ -279,6 +279,7 @@ emptyDrive: "드라이브가 비어 있습니다"
emptyFolder: "폴더가 비어 있습니다"
unableToDelete: "삭제할 수 없습니다"
inputNewFileName: "바꿀 파일명을 입력해 주세요"
inputNewDescription: "새 캡션을 입력해 주세요"
inputNewFolderName: "바꿀 폴더명을 입력해 주세요"
circularReferenceFolder: "지정한 폴더가 이동할 폴더의 하위 폴더입니다."
hasChildFilesOrFolders: "이 폴더는 비어있지 않기 때문에 삭제할 수 없습니다."
@ -310,8 +311,8 @@ monthX: "{month}월"
yearX: "{year}년"
pages: "페이지"
integration: "연동"
connectSerice: "접속"
disconnectSerice: "연결 끊기"
connectService: "계정 연동"
disconnectService: "계정 연동 해제"
enableLocalTimeline: "로컬 타임라인 활성화"
enableGlobalTimeline: "글로벌 타임라인 활성화"
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "리모트 유저 한 명당 드라이브 용량"
inMb: "메가바이트 단위"
iconUrl: "아이콘 URL"
bannerUrl: "배너 이미지 URL"
backgroundImageUrl: "배경 이미지 URL"
basicInfo: "기본 정보"
pinnedUsers: "고정된 유저"
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
@ -526,7 +528,6 @@ removeAllFollowing: "모든 팔로잉 해제"
removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요."
userSuspended: "이 계정은 정지된 상태입니다."
userSilenced: "이 계정은 사일런스된 상태입니다."
sidebar: "사이드바"
divider: "구분선"
addItem: "항목 추가"
rooms: "방"
@ -546,6 +547,8 @@ disablePlayer: "플레이어 닫기"
expandTweet: "트윗 확장하기"
themeEditor: "테마 에디터"
description: "설명"
describeFile: "캡션 추가"
enterFileDescription: "캡션 입력"
author: "작성자"
leaveConfirm: "저장하지 않은 변경사항이 있습니다. 취소하시겠습니까?"
manage: "관리"
@ -757,6 +760,7 @@ middle: "보통"
low: "낮음"
emailNotConfiguredWarning: "메일 주소가 설정되어 있지 않습니다."
ratio: "비율"
global: "글로벌"
_ad:
back: "뒤로"
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
@ -906,9 +910,7 @@ _channel:
following: "팔로잉"
usersCount: "{n}명 참여 중"
notesCount: "{n}노트"
_sidebar:
full: "전체"
icon: "아이콘"
_menuDisplay:
hide: "숨기기"
_wordMute:
muteWords: "뮤트할 단어"

View File

@ -1,2 +1,3 @@
---
_lang_: "Nederlands"
headlineMisskey: "Netwerk verbonden door notities"

View File

@ -7,6 +7,7 @@ search: "Szukaj"
notifications: "Powiadomienia"
username: "Nazwa użytkownika"
password: "Hasło"
forgotPassword: "Nie pamiętam hasła"
fetchingAsApObject: "Pobieranie z Fediwersum…"
ok: "OK"
gotIt: "Rozumiem!"
@ -65,6 +66,7 @@ download: "Pobierz"
driveFileDeleteConfirm: "Czy chcesz usunąć plik \"{name}\"? Zniknie również notatka, do której dołączony jest ten plik."
unfollowConfirm: "Czy na pewno chcesz przestać obserwować {name}?"
exportRequested: "Zażądałeś eksportu. Może to zająć trochę czasu. Po zakończeniu eksportu zostanie on dodany do Twoich \"dysków\"."
importRequested: "Zażądano importu. Może to zająć chwilę."
lists: "Listy"
noLists: "Nie masz żadnych list"
note: "Utwórz wpis"
@ -133,9 +135,11 @@ settingGuide: "Proponowana konfiguracja"
cacheRemoteFiles: "Przechowuj zdalne pliki w pamięci podręcznej"
cacheRemoteFilesDescription: "Gdy ta opcja jest wyłączona, zdalne pliki są ładowane bezpośrednio ze zdalnych instancji. Wyłączenie the opcji zmniejszy użycie powierzchni dyskowej, ale zwiększy transfer, ponieważ miniaturki nie będą generowane."
flagAsBot: "To konto jest botem"
flagAsBotDescription: "Jeżeli ten kanał jest kontrolowany przez jakiś program, ustaw tę opcję. Jeżeli włączona, będzie działać jako flaga informująca innych programistów, aby zapobiegać nieskończonej interakcji z różnymi botami i dostosowywać wewnętrzne systemy Misskey, traktując konto jako bota."
flagAsCat: "To konto jest kotem"
flagAsCatDescription: "Przełącz tę opcję, aby konto było oznaczone jako kot."
autoAcceptFollowed: "Automatycznie przyjmuj prośby o możliwość obserwacji od użytkowników, których obserwujesz"
addAccount: "Dodaj konto"
loginFailed: "Nie udało się zalogować"
showOnRemote: "Zobacz na zdalnej instancji"
general: "Ogólne"
@ -179,6 +183,7 @@ clearQueueConfirmTitle: "Czy na pewno chcesz wyczyścić kolejkę?"
clearCachedFiles: "Wyczyść pamięć podręczną"
clearCachedFilesConfirm: "Czy na pewno chcesz usunąć wszystkie zdalne pliki z pamięci podręcznej?"
blockedInstances: "Zablokowane instancje"
blockedInstancesDescription: "Wypisz nazwy hostów instancji, które powinny zostać zablokowane. Wypisane instancje nie będą mogły dłużej komunikować się z tą instancją."
muteAndBlock: "Wycisz / Zablokuj"
mutedUsers: "Wyciszeni użytkownicy"
blockedUsers: "Zablokowani użytkownicy"
@ -271,6 +276,7 @@ emptyDrive: "Dysk jest pusty"
emptyFolder: "Ten katalog jest pusty"
unableToDelete: "Nie można usunąć"
inputNewFileName: "Wprowadź nową nazwę pliku"
inputNewDescription: "Proszę wpisać nowy napis"
inputNewFolderName: "Wprowadź nową nazwę katalogu"
circularReferenceFolder: "Katalog docelowy jest podkatalogiem katalogu, który chcesz przenieść."
hasChildFilesOrFolders: "Ponieważ ten katalog nie jest pusty, nie może być usunięty."
@ -291,16 +297,17 @@ reject: "Odrzuć"
normal: "Normalny"
instanceName: "Nazwa instancji"
instanceDescription: "Opis instancji"
maintainerName: "Administrator"
maintainerEmail: "E-mail administratora"
tosUrl: "Adres URL regulaminu"
thisYear: "Rok"
thisMonth: "Miesiąc"
today: "Dziś"
dayX: "{day}"
monthX: "{month}"
yearX: "{year}"
pages: "Strony"
integration: "Integracja"
connectSerice: "Połącz"
disconnectSerice: "Rozłącz"
enableLocalTimeline: "Włącz lokalną oś czasu"
enableGlobalTimeline: "Włącz globalną oś czasu"
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone."
@ -332,6 +339,7 @@ manageAntennas: "Zarządzaj Antenami"
name: "Nazwa"
antennaSource: "Źródło Anteny"
antennaExcludeKeywords: "Wykluczone słowa kluczowe"
notifyAntenna: "Powiadamiaj o nowych wpisach"
withFileAntenna: "Filtruj tylko wpisy z załączonym plikiem"
enableServiceworker: "Włącz ServiceWorker"
antennaUsersDescription: "Wypisz po jednej nazwie użytkownika w linii"
@ -358,6 +366,7 @@ administrator: "Admin"
token: "Token"
twoStepAuthentication: "Uwierzytelnianie dwuskładnikowe"
moderator: "Moderator"
nUsersMentioned: "{n} wspomnianych użytkowników"
securityKey: "Klucz bezpieczeństwa"
securityKeyName: "Nazwa klucza"
registerSecurityKey: "Zarejestruj klucz bezpieczeństwa"
@ -397,6 +406,7 @@ retype: "Wprowadź ponownie"
noteOf: "Wpisy {user}"
inviteToGroup: "Zaproś do grupy"
maxNoteTextLength: "Limit znaków dla wpisów"
quoteAttached: "Zacytowano"
quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
noMessagesYet: "Nie napisano jeszcze wiadomości"
newMessageExists: "Masz nową wiadomość"
@ -419,6 +429,7 @@ 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}"
@ -432,6 +443,7 @@ category: "Kategoria"
tags: "Tagi"
docSource: "Źródło tego dokumentu"
createAccount: "Utwórz konto"
existingAccount: "Istniejące konto"
regenerate: "Wygeneruj ponownie"
fontSize: "Rozmiar czcionki"
noFollowRequests: "Nie masz żadnych oczekujących próśb o możliwość obserwacji"
@ -453,6 +465,8 @@ showFeaturedNotesInTimeline: "Pokazuj wyróżnione wpisy w osi czasu"
objectStorage: "Pamięć obiektowa"
useObjectStorage: "Używaj pamięci obiektowej"
objectStorageBaseUrl: "Podstawowy URL"
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Podaj nazwę „wiadra” używaną przez konfigurowaną usługę."
objectStoragePrefix: "Prefiks"
objectStoragePrefixDesc: "Pliki będą przechowywane w katalogu z tym prefiksem."
objectStorageEndpoint: "Punkt końcowy"
@ -499,7 +513,6 @@ deleteAllFilesConfirm: "Czy na pewno chcesz usunąć wszystkie pliki?"
removeAllFollowingDescription: "Przestań obserwować wszystkie konta z {host}. Wykonaj to, jeżeli instancja już nie istnieje."
userSuspended: "To konto zostało zawieszone."
userSilenced: "Ten użytkownik został wyciszony."
sidebar: "Pasek boczny"
divider: "Rozdzielacz"
addItem: "Dodaj element"
rooms: "Pokój"
@ -519,6 +532,8 @@ disablePlayer: "Zamknij odtwarzacz wideo"
expandTweet: "Rozwiń tweet"
themeEditor: "Edytor motywu"
description: "Opis"
describeFile: "dodaj podpis"
enterFileDescription: "Wprowadź napis"
author: "Autor"
leaveConfirm: "Są niezapisane zmiany. Czy chcesz je odrzucić?"
manage: "Zarządzanie"
@ -540,6 +555,7 @@ pluginTokenRequestedDescription: "Ta wtyczka będzie mogła korzystać z ustawio
notificationType: "Rodzaj powiadomień"
edit: "Edytuj"
useStarForReactionFallback: "Użyj ★ jako zapasowego emoji, gdy emoji reakcji jest nieznane"
emailServer: "Serwer poczty e-mail"
enableEmail: "Włącz dostarczanie wiadomości e-mail"
emailConfigInfo: "Wykorzystywany do potwierdzenia adresu e-mail w trakcie rejestracji, lub gdy zapomnisz hasła"
email: "Adres e-mail"
@ -552,6 +568,7 @@ smtpPass: "Hasło"
emptyToDisableSmtpAuth: "Pozostaw adres e-mail i hasło puste, aby wyłączyć weryfikację SMTP"
smtpSecureInfo: "Wyłącz, jeżeli używasz STARTTLS"
testEmail: "Przetestuj dostarczanie wiadomości e-mail"
wordMute: "Wyciszenie słowa"
userSaysSomething: "{name} powiedział(-a) coś"
makeActive: "Aktywuj"
display: "Wyświetlanie"
@ -622,6 +639,7 @@ emailVerified: "Adres e-mail został potwierdzony"
noteFavoritesCount: "Liczba polubionych wpisów"
pageLikesCount: "Liczba otrzymanych polubień stron"
pageLikedCount: "Liczba polubionych stron"
reversiCount: "Liczba rozgrywek Reversi"
contact: "Kontakt"
useSystemFont: "Używaj domyślnej czcionki systemu"
experimentalFeatures: "Eksperymentalne funkcje"
@ -630,6 +648,7 @@ makeExplorable: "Pokazuj konto na stronie „Eksploruj”"
makeExplorableDescription: "Jeżeli wyłączysz tę opcję, Twoje konto nie będzie wyświetlać się w sekcji „Eksploruj”."
showGapBetweenNotesInTimeline: "Pokazuj odstęp między wpisami na osi czasu."
duplicate: "Duplikuj"
left: "Lewo"
center: "Wyśsrodkuj"
wide: "Szerokie"
narrow: "Wąskie"
@ -639,26 +658,108 @@ clearCache: "Wyczyść pamięć podręczną"
onlineUsersCount: "{n} osób jest online"
nUsers: "{n} użytkowników"
nNotes: "{n} wpisów"
sendErrorReports: "Wyślij raporty o błędach"
myTheme: "Mój motyw"
backgroundColor: "Tło"
accentColor: "Akcent"
textColor: "Tekst"
saveAs: "Zapisz jako…"
advanced: "Zaawansowane"
value: "Wartość"
createdAt: "Utworzono"
updatedAt: "Zaktualizowano"
saveConfirm: "Zapisać zmiany?"
deleteConfirm: "Na pewno usunąć?"
invalidValue: "Nieprawidłowa wartość."
registry: "Rejestr"
closeAccount: "Zamknij konto"
currentVersion: "Bieżąca wersja"
latestVersion: "Najnowsza wersja"
youAreRunningUpToDateClient: "Korzystasz z najnowszej wersji klienta."
newVersionOfClientAvailable: "Nowsza wersja klienta jest dostępna."
usageAmount: "Użycie"
capacity: "Pojemność"
inUse: "Użyto"
editCode: "Edytuj kod"
apply: "Zastosuj"
receiveAnnouncementFromInstance: "Otrzymuj powiadomienia e-mail z tej instancji"
emailNotification: "Powiadomienia e-mail"
publish: "Publikuj"
inChannelSearch: "Szukaj na kanale"
useReactionPickerForContextMenu: "Otwórz wybornik reakcji prawym kliknięciem"
typingUsers: "{users} pisze(-ą)..."
jumpToSpecifiedDate: "Przejdź do określonej daty"
showingPastTimeline: "Obecnie wyświetla starą oś czasu"
clear: "Wróć"
markAllAsRead: "Oznacz wszystkie jako przeczytane"
goBack: "Wróć"
unlikeConfirm: "Na pewno chcesz usunąć polubienie?"
fullView: "Pełny widok"
quitFullView: "Opuść pełny widok"
addDescription: "Dodaj opis"
info: "Informacje"
userInfo: "Informacje o użykowniku"
unknown: "Nieznane"
onlineStatus: "Status online"
hideOnlineStatus: "Ukryj status online"
hideOnlineStatusDescription: "Ukrywanie statusu online ogranicza wygody niektórych funkcji, tj. wyszukiwanie"
online: "Online"
active: "Aktywny"
offline: "Offline"
notRecommended: "Nie zalecane"
botProtection: "Zabezpieczenie przed botami"
instanceBlocking: "Zablokowane instancje"
selectAccount: "Wybierz konto"
enabled: "Właczono"
disabled: "Wyłączono"
quickAction: "Szybkie działania"
user: "Użytkownicy"
administration: "Zarządzanie"
accounts: "Konta"
switch: "Przełącz"
noMaintainerInformationWarning: "Informacje o administratorze nie są skonfigurowane."
noBotProtectionWarning: "Zabezpieczenie przed botami nie jest skonfigurowane."
configure: "Skonfiguruj"
postToGallery: "Opublikuj w galerii"
gallery: "Galeria"
recentPosts: "Ostatnie wpisy"
popularPosts: "Popularne wpisy"
shareWithNote: "Udostępnij z wpisem"
ads: "Reklamy"
expiration: "Ankieta kończy się"
memo: "Notatki"
priority: "Priorytet"
high: "Wysoki"
middle: "Średnie"
low: "Niski"
emailNotConfiguredWarning: "Nie podano adresu e-mail"
ratio: "Stosunek"
global: "Globalna"
_ad:
back: "Wróć"
reduceFrequencyOfThisAd: "Pokazuj tę reklamę rzadziej"
_forgotPassword:
ifNoEmail: "Jeżeli nie podano adresu e-mail podczas rejestracji, skontaktuj się z administratorem zamiast tego."
contactAdmin: "Jeżeli Twoja instancja nie obsługuje adresów e-mail, skontaktuj się zamiast tego z administratorem, aby zresetować hasło."
_gallery:
my: "Moja galeria"
liked: "Polubione wpisy"
like: "Polub"
unlike: "Cofnij polubienie"
_email:
_follow:
title: "Zaobserwował(a) Cię"
_receiveFollowRequest:
title: "Otrzymano prośbę o możliwość obserwacji"
_plugin:
install: "Zainstaluj wtyczki"
installWarn: "Nie instaluj niezaufanych wtyczek."
manage: "Zarządzanie wtyczkami"
_registry:
scope: "Zakres"
key: "Klucz"
keys: "Klucz"
domain: "Domena"
createKey: "Utwórz klucz"
_aboutMisskey:
about: "Misskey jest oprogramowanie open source rozwijanym przez syuilo od 2014."
@ -708,6 +809,7 @@ _mfm:
x4Description: "Czyni treść jeszcze większą niż jeszcze większa."
blur: "Rozmycie"
font: "Czcionka"
fontDescription: "Wybiera czcionkę do wyświetlania treści."
_reversi:
reversi: "Reversi"
gameSettings: "Ustawienia gry"
@ -756,9 +858,7 @@ _channel:
following: "Śledzeni"
usersCount: "{n} uczestnicy"
notesCount: "{n} wpisy"
_sidebar:
full: "Pełne"
icon: "Awatar"
_menuDisplay:
hide: "Ukryj"
_wordMute:
muteWords: "Słowo do wyciszenia"
@ -972,16 +1072,21 @@ _profile:
username: "Nazwa użytkownika"
description: "Opis"
youCanIncludeHashtags: "Możesz umieścić hashtagi w swoim opisie."
metadata: "Dodatkowe informacje"
metadataEdit: "Edytuj dodatkowe informacje"
metadataDescription: "Możesz wyświetlać do czterech sekcji dodatkowych informacji na swoim profilu."
metadataLabel: "Etykieta"
metadataContent: "Treść"
changeAvatar: "Zmień awatar"
changeBanner: "Zmień baner"
_exportOrImport:
allNotes: "Wszystkie wpisy"
followingList: "Obserwowani"
muteList: "Wycisz"
blockingList: "Zablokuj"
userLists: "Listy"
_charts:
federationInstancesTotal: "Łącznie sfederowanych instancji"
usersTotal: "Łącznie # użytkowników"
activeUsers: "Aktywni użytkownicy"
_instanceCharts:
@ -996,6 +1101,7 @@ _instanceCharts:
_timelines:
home: "Strona główna"
local: "Lokalne"
social: "Społeczność"
global: "Globalna"
_rooms:
roomOf: "Pokój {user}"
@ -1366,6 +1472,8 @@ _deck:
swapRight: "Przesuń w prawo"
swapUp: "Zamień z powyższym"
swapDown: "Zamień z poniższym"
stackLeft: "Przypnij do lewej"
popRight: "Odepnij w prawo"
profile: "Profil"
_columns:
main: "Główna"

View File

@ -6,25 +6,72 @@ notifications: "Notificações"
username: "Nome de usuário"
password: "Senha"
ok: "OK"
gotIt: "Entendi"
cancel: "Cancelar"
enterUsername: "Digite o nome de usuário"
renotedBy: "Repostado por {user}"
noNotes: "Sem posts"
settings: "Configurações"
basicSettings: "Configurações básicas"
otherSettings: "Outras configurações"
profile: "Perfil"
timeline: "Timeline"
logout: "Sair"
users: "Usuários"
favorite: "Favoritar"
favorites: "Favoritar"
showMore: "Ver mais"
youGotNewFollower: "Você tem um novo seguidor"
followRequestAccepted: "Pedido de seguir aceito"
note: "Post"
notes: "Posts"
enterEmoji: "Inserir emoji"
renote: "Repostar"
renoted: "Repostado"
cantRenote: "Não pode repostar"
cantReRenote: "Não pode repostar este repost"
pinnedNote: "Post fixado"
sensitive: "Conteúdo sensível"
mute: "Silenciar"
unmute: "Dessilenciar"
settingGuide: "Guia de configuração"
instances: "Instância"
registeredAt: "Registrado em"
perHour: "por hora"
perDay: "por dia"
noUsers: "Sem usuários"
messageRead: "Lida"
lightThemes: "Tema claro"
darkThemes: "Tema escuro"
addFile: "Adicionar arquivo"
nsfw: "Conteúdo sensível"
monthX: "mês de {month}"
pinnedNotes: "Post fixado"
smtpUser: "Nome de usuário"
smtpPass: "Senha"
user: "Usuários"
_email:
_follow:
title: "Você tem um novo seguidor"
_mfm:
search: "Pesquisar"
_theme:
keys:
renote: "Repostar"
_sfx:
note: "Posts"
notification: "Notificações"
_widgets:
notifications: "Notificações"
timeline: "Timeline"
_profile:
username: "Nome de usuário"
_exportOrImport:
muteList: "Silenciar"
_notification:
youWereFollowed: "Você tem um novo seguidor"
_types:
renote: "Repostar"
_deck:
_columns:
notifications: "Notificações"

View File

@ -7,6 +7,7 @@ search: "Поиск"
notifications: "Уведомления"
username: "Имя пользователя"
password: "Пароль"
forgotPassword: "Пароль забыт"
fetchingAsApObject: "Приём с других сайтов"
ok: "Окей"
gotIt: "Ясно!"
@ -278,6 +279,7 @@ emptyDrive: "Диск пуст"
emptyFolder: "Папка пуста"
unableToDelete: "Удаление невозможно"
inputNewFileName: "Введите имя нового файла"
inputNewDescription: "Введите новую подпись"
inputNewFolderName: "Пожалуйста, введите новое имя папки!"
circularReferenceFolder: "Вы пытаетесь переместить папку внутрь себя."
hasChildFilesOrFolders: "Эта папка не пуста и не может быть удалена."
@ -309,8 +311,8 @@ monthX: "{month} месяц"
yearX: "{year} год"
pages: "Страницы"
integration: "Интеграция"
connectSerice: "Соединение"
disconnectSerice: "Отключение"
connectService: "Подключиться"
disconnectService: "Отключиться"
enableLocalTimeline: "Включить локальную ленту"
enableGlobalTimeline: "Включить глобальную ленту"
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам, даже если они отключены."
@ -324,6 +326,7 @@ driveCapacityPerRemoteAccount: "Объём диска на одного поль
inMb: "В мегабайтах"
iconUrl: "Ссылка на аватар"
bannerUrl: "Ссылка на изображение в шапке"
backgroundImageUrl: "Ссылка на фоновое изображение"
basicInfo: "Общая информация"
pinnedUsers: "Прикреплённый пользователь"
pinnedUsersDescription: "Перечислите по одному имени пользователя в строке. Пользователи, перечисленные здесь, будут привязаны к закладке \"Изучение\"."
@ -525,7 +528,6 @@ removeAllFollowing: "Удалить всех подписчиков"
removeAllFollowingDescription: "Отменить все подписки с домена {host}? Пожалуйста, применяйте это действие, если инстанс больше не существует."
userSuspended: "Эта учётная запись заморожена"
userSilenced: "Этот пользователь был заглушен"
sidebar: "Боковая панель"
divider: "Линия-разделитель"
addItem: "Добавить элемент"
rooms: "Комната"
@ -545,6 +547,8 @@ disablePlayer: "Выключить проигрыватель"
expandTweet: "Развернуть твит"
themeEditor: "Редактор темы оформления"
description: "Описание"
describeFile: "Добавить подпись"
enterFileDescription: "Введите подпись"
author: "Автор"
leaveConfirm: "Вы не сохранили изменения. Хотите выйти и потерять их?"
manage: "Управление"
@ -747,10 +751,23 @@ gallery: "Галерея"
recentPosts: "Недавние публикации"
popularPosts: "Популярные публикации"
shareWithNote: "Поделиться заметкой"
ads: "Реклама"
expiration: "Опрос длится"
memo: "Памятка"
priority: "Приоритет"
high: "Высокий"
middle: "Средне"
low: "Низкий"
emailNotConfiguredWarning: "Не указан адрес электронной почты"
ratio: "Соотношение"
global: "Всеобщая"
_ad:
back: "Выход"
reduceFrequencyOfThisAd: "Реже показывать эту рекламу"
_forgotPassword:
enterEmail: "Введите адрес электронной почты, который ввели при регистрации. На неё будет выслана ссылка для смены пароля."
ifNoEmail: "Если вы не ввели свой адрес электронной почты, свяжитесь с администратором ресурса, чтобы сменить пароль."
contactAdmin: "Здесь не используются адреса электронной почты, так что свяжитесь с администратором, чтобы поменять пароль."
_gallery:
my: "Личная"
liked: "Понравившееся"
@ -893,9 +910,7 @@ _channel:
following: "Подписки"
usersCount: "Участников: {n}"
notesCount: "Заметок: {n}"
_sidebar:
full: "Полностью"
icon: "Только значки"
_menuDisplay:
hide: "Спрятать"
_wordMute:
muteWords: "Скрыть слово"

View File

@ -307,8 +307,6 @@ monthX: "{month}"
yearX: "{year}"
pages: "Сторінки"
integration: "Інтеграція"
connectSerice: "Під’єднати"
disconnectSerice: "Відключитися"
enableLocalTimeline: "Увімкнути локальну стрічку"
enableGlobalTimeline: "Увімкнути глобальну стрічку"
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
@ -519,7 +517,6 @@ removeAllFollowing: "Скасувати всі підписки"
removeAllFollowingDescription: "Скасувати підписку на всі акаунти з {host}. Будь ласка, робіть це, якщо інстанс більше не існує."
userSuspended: "Обліковий запис заблокований."
userSilenced: "Обліковий запис приглушений."
sidebar: "Бокова панель"
divider: "Розділювач"
addItem: "Додати елемент"
rooms: "Кімнати"
@ -691,6 +688,7 @@ user: "Користувачі"
administration: "Управління"
expiration: "Опитування закінчується"
middle: "Середній"
global: "Глобальна"
_ad:
back: "Назад"
_gallery:
@ -818,9 +816,7 @@ _channel:
following: "Підписки"
usersCount: "{n} учасників"
notesCount: "{n} дописів"
_sidebar:
full: "Повна"
icon: "Аватар"
_menuDisplay:
hide: "Сховати"
_wordMute:
muteWords: "Заглушені слова"

View File

@ -1,13 +1,13 @@
---
_lang_: "中文(简体)"
headlineMisskey: "通过帖子连接在一起的网络"
introMisskey: "欢迎Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能可以让你快速地对大家的帖表达反馈👍\n来探索新的世界吧🚀"
introMisskey: "欢迎Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能可以让你快速地对大家的帖表达反馈👍\n来探索新的世界吧🚀"
monthAndDay: "{month}月 {day}日"
search: "搜索"
notifications: "通知"
username: "用户名"
password: "密码"
forgotPassword: "忘记密码"
forgotPassword: "重置密码"
fetchingAsApObject: "联合查询中"
ok: "OK"
gotIt: "我明白了"
@ -63,33 +63,33 @@ import: "导入"
export: "导出"
files: "文件"
download: "下载"
driveFileDeleteConfirm: "要删除「{name}」文件吗?附加此文件的帖子也会消失。"
driveFileDeleteConfirm: "要删除「{name}」文件吗?附加此文件的帖子也会被删除。"
unfollowConfirm: "要取消对{name}的关注吗?"
exportRequested: "导出请求已提交可能需要花一些时间导出的文件将保存到网盘中。"
importRequested: "导入请求已提交这可能需要花一点时间。"
exportRequested: "导出请求已提交,这可能需要花一些时间导出的文件将保存到网盘中。"
importRequested: "导入请求已提交这可能需要花一点时间。"
lists: "列表"
noLists: "列表为空"
note: "帖子"
notes: "帖子"
following: "关注中"
followers: "关注者"
followsYou: "关注你"
followsYou: "正在关注你"
createList: "创建列表"
manageLists: "管理列表"
error: "错误"
somethingHappened: "出现了问题"
somethingHappened: "出现了一些问题"
retry: "重试"
pageLoadError: "页面加载失败。"
pageLoadErrorDescription: "这通常是由于网络或浏览器缓存的原因。请清除缓存或等待片刻后重试。"
enterListName: "输入列表名称"
privacy: "隐私"
makeFollowManuallyApprove: "关注者请求需要批准"
makeFollowManuallyApprove: "关注者的关注请求需要批准"
defaultNoteVisibility: "默认可见性"
follow: "关注"
followRequest: "关注申请"
followRequests: "关注申请"
unfollow: "取消关注"
followRequestPending: "发送关注请"
followRequestPending: "发送关注请"
enterEmoji: "输入表情符号"
renote: "转发"
unrenote: "取消转发"
@ -106,7 +106,7 @@ add: "添加"
reaction: "回应"
reactionSettingDescription: "选择您想要置顶的回应。"
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
rememberNoteVisibility: "记录公开范围"
rememberNoteVisibility: "保存上次设置的可见性"
attachCancel: "删除附件"
markAsSensitive: "标记为敏感内容"
unmarkAsSensitive: "取消标记为敏感内容"
@ -134,11 +134,11 @@ addEmoji: "添加表情符号"
settingGuide: "推荐配置"
cacheRemoteFiles: "远程文件缓存"
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
flagAsBot: "这个账户是Bot"
flagAsBot: "这是一个机器人账号"
flagAsBotDescription: "如果此帐户由程序控制请启用此项。启用后此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为并让Misskey的内部系统将此帐户识别为机器人。"
flagAsCat: "这个账户是Cat"
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。"
autoAcceptFollowed: "自动允许关注"
flagAsCat: "这个账户是一只猫"
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。\n开启后会在您的头像上出现猫耳朵并将你的帖子中的「na」替换为「nya」日文同理。"
autoAcceptFollowed: "自动允许关注者的关注"
addAccount: "添加账户"
loginFailed: "登录失败"
showOnRemote: "转到所在实例显示"
@ -172,7 +172,7 @@ software: "软件"
version: "版本"
metadata: "元数据"
withNFiles: "{n}个文件"
monitor: "监视器"
monitor: "服务器状态"
jobQueue: "作业队列"
cpuAndMemory: "CPU和内存"
network: "网络"
@ -211,7 +211,7 @@ instanceFollowing: "关注实例"
instanceFollowers: "关注实例"
instanceUsers: "实例用户"
changePassword: "修改密码"
security: "安全"
security: "安全"
retypedNotMatch: "两次输入不一致!"
currentPassword: "现在的密码"
newPassword: "新密码"
@ -231,18 +231,18 @@ deleteAreYouSure: "要删掉「{x}」吗?"
resetAreYouSure: "恢复默认设置?"
saved: "已保存"
messaging: "聊天"
upload: "上传"
upload: "本地上传"
fromDrive: "从网盘中"
fromUrl: "从 URL"
uploadFromUrl: "从网址上传"
uploadFromUrlDescription: "要上传的文件的URL"
uploadFromUrlDescription: "输入文件的URL"
uploadFromUrlRequested: "请求上传"
uploadFromUrlMayTakeTime: "上传可能需要一些时间完成。"
explore: "发现"
games: "Misskey游戏"
messageRead: "已读"
noMoreHistory: "没有更多的历史记录"
startMessaging: "开始聊天"
startMessaging: "添加聊天"
nUsersRead: "{n}人已读"
agreeTo: "{0}人同意"
tos: "服务条款"
@ -260,8 +260,8 @@ themeForLightMode: "在浅色模式下使用的主题"
themeForDarkMode: "在深色模式下使用的主题"
light: "浅色"
dark: "深色"
lightThemes: "色主题"
darkThemes: "色主题"
lightThemes: "色主题"
darkThemes: "色主题"
syncDeviceDarkMode: "将深色模式与设备设置同步"
drive: "网盘"
fileName: "文件名称"
@ -275,23 +275,24 @@ createFolder: "创建文件夹"
renameFolder: "重命名文件夹"
deleteFolder: "删除文件夹"
addFile: "添加文件"
emptyDrive: "驱动器为空"
emptyFolder: "文件夹"
emptyDrive: "网盘中无文件"
emptyFolder: "文件夹中无文件"
unableToDelete: "无法删除"
inputNewFileName: "请输入新文件名"
inputNewFolderName: "请输入新文件名"
inputNewDescription: "请输入新标题"
inputNewFolderName: "请输入新文件夹名"
circularReferenceFolder: "目标文件夹是您要移动的文件夹的子文件夹。"
hasChildFilesOrFolders: "此文件夹不为空,无法删除。"
hasChildFilesOrFolders: "此文件夹中有文件,无法删除。"
copyUrl: "复制链接"
rename: "重命名"
avatar: "头像"
banner: "Banner"
banner: "横幅"
nsfw: "敏感内容"
whenServerDisconnected: "与服务器连接中断时"
disconnectedFromServer: "已服务器断开连接"
disconnectedFromServer: "已服务器断开连接"
reload: "重新加载"
doNothing: "什么都不做"
reloadConfirm: "确定要重新加载吗"
doNothing: "关闭弹窗"
reloadConfirm: "确定要重新加载吗"
watch: "关注"
unwatch: "取消关注"
accept: "允许"
@ -310,8 +311,8 @@ monthX: "{month}月"
yearX: "{year}年"
pages: "页面"
integration: "关联"
connectSerice: "连接"
disconnectSerice: "断开连接"
connectService: "连接"
disconnectService: "断开连接"
enableLocalTimeline: "启用本地时间线功能"
enableGlobalTimeline: "启用全局时间线"
disablingTimelinesInfo: "即使时间线功能被禁用,出于便利性的原因,管理员和数据图表也可以继续使用。"
@ -324,13 +325,14 @@ driveCapacityPerLocalAccount: "每个用户的网盘空间"
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
inMb: "以兆字节(MegaByte)为单位"
iconUrl: "图标URL"
bannerUrl: "Banner URL"
bannerUrl: "横幅URL"
backgroundImageUrl: "背景图URL"
basicInfo: "基本信息"
pinnedUsers: "置顶用户"
pinnedUsersDescription: "在「发现」页面中使用换行标记想要置顶的用户。"
pinnedPages: "固定页面"
pinnedPagesDescription: "输入您要固定到实例首页的页面路径,以换行符分隔。"
pinnedClipId: "置顶的片段ID"
pinnedClipId: "置顶的书签ID"
pinnedNotes: "已置顶的帖子"
hcaptcha: "hCaptcha"
enableHcaptcha: "启用 hCaptcha"
@ -348,13 +350,13 @@ antennaSource: "接收来源"
antennaKeywords: "包含关键字"
antennaExcludeKeywords: "排除关键字"
antennaKeywordsDescription: "使用空格分隔会产生AND规范并且使用换行符分隔会产生OR规范"
notifyAntenna: "通知新帖子"
notifyAntenna: "开启通知"
withFileAntenna: "仅带有附件的帖子"
enableServiceworker: "启用ServiceWorker"
antennaUsersDescription: "指定用户名,用换行符分隔"
caseSensitive: "区分大小写"
withReplies: "包括回复"
connectedTo: "您的账号已连到接以下社交账号"
connectedTo: "您的账号已连到接以下第三方账号"
notesAndReplies: "帖子与回复"
withFiles: "附件"
silence: "禁言"
@ -362,8 +364,8 @@ silenceConfirm: "确认要禁言吗?"
unsilence: "解除禁言"
unsilenceConfirm: "要解除禁言吗?"
popularUsers: "热门用户"
recentlyUpdatedUsers: "最近投稿用户"
recentlyRegisteredUsers: "最近登录用户"
recentlyUpdatedUsers: "最近投稿用户"
recentlyRegisteredUsers: "最近登录用户"
recentlyDiscoveredUsers: "最近发现的用户"
exploreUsersCount: "有{count}个用户"
exploreFediverse: "探索Fediverse"
@ -372,9 +374,9 @@ userList: "列表"
about: "关于"
aboutMisskey: "关于 Misskey"
administrator: "管理员"
token: "令牌"
token: "Token (令牌)"
twoStepAuthentication: "两步验证"
moderator: "版主"
moderator: "监察员"
nUsersMentioned: "{n} 被提到"
securityKey: "安全密钥"
securityKeyName: "密钥名称"
@ -416,7 +418,7 @@ noteOf: "{user}的帖子"
inviteToGroup: "群组邀请"
maxNoteTextLength: "帖子的字数限制"
quoteAttached: "已引用"
quoteQuestion: "是否将其作为引用附上"
quoteQuestion: "是否引用此链接内容"
noMessagesYet: "现在没有新的聊天"
newMessageExists: "新信息"
onlyOneFileCanBeAttached: "只能添加一个附件"
@ -440,9 +442,9 @@ tapSecurityKey: "轻触硬件安全密钥"
or: "或者"
language: "语言"
uiLanguage: "显示语言"
groupInvited: "群组招待"
groupInvited: "您有新的群组邀请"
aboutX: "关于 {x}"
useOsNativeEmojis: "使用OS原生表情符号"
useOsNativeEmojis: "使用系统的原生表情符号"
youHaveNoGroups: "没有群组"
joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
noHistory: "没有历史记录"
@ -458,7 +460,7 @@ regenerate: "重新生成"
fontSize: "字体大小"
noFollowRequests: "没有关注申请"
openImageInNewTab: "在新标签页中打开图片"
dashboard: "Dashboard"
dashboard: "管理面板"
local: "本地"
remote: "远程"
total: "总计"
@ -490,12 +492,12 @@ objectStorageUseProxy: "使用代理"
objectStorageUseProxyDesc: "如果您不使用代理进行API连接请将其关闭。"
objectStorageSetPublicRead: "上传时设置为public-read"
serverLogs: "服务器日志"
deleteAll: "删除全部"
showFixedPostForm: "在时间线顶部显示帖子表单"
deleteAll: "全部删除"
showFixedPostForm: "在时间线顶部显示发帖框"
newNoteRecived: "有新的帖子"
sounds: "音"
listen: "听"
none: ""
sounds: "提示音"
listen: "听"
none: ""
showInPage: "在页面中显示"
popout: "弹窗"
volume: "音量"
@ -507,15 +509,15 @@ recentUsed: "最近使用"
install: "安装"
uninstall: "卸载"
installedApps: "已授权的应用"
nothing: "没什么"
nothing: "没"
installedDate: "授权日期"
lastUsedDate: "最近使用"
state: "状态"
sort: "排序"
ascendingOrder: "升序"
descendingOrder: "降序"
scratchpad: "便签本"
scratchpadDescription: "便签本为AiScript提供了实验环境。您可以编写代码以与Misskey交互运行它并查看结果。"
scratchpad: "AiScript控制台"
scratchpadDescription: "AiScript控制台为AiScript提供了实验环境。您可以编写代码以与Misskey交互运行它并查看结果。"
output: "输出"
script: "脚本"
disablePagesScript: "禁用页面脚本"
@ -526,7 +528,7 @@ removeAllFollowing: "取消所有关注"
removeAllFollowingDescription: "取消{host}的所有关注者。当实例不存在时执行。"
userSuspended: "该用户已被冻结。"
userSilenced: "该用户已被禁言。"
sidebar: "侧边栏"
menu: "菜单"
divider: "分割线"
addItem: "添加项目"
rooms: "房间"
@ -543,9 +545,11 @@ poll: "调查问卷"
useCw: "隐藏内容"
enablePlayer: "打开播放器"
disablePlayer: "关闭播放器"
expandTweet: "展开贴文"
expandTweet: "展开帖子"
themeEditor: "主题编辑器"
description: "描述"
describeFile: "添加标题"
enterFileDescription: "输入标题"
author: "作者"
leaveConfirm: "存在未保存的更改。要放弃更改吗?"
manage: "管理"
@ -587,10 +591,10 @@ userSaysSomething: "{name}说了什么"
makeActive: "启用"
display: "显示"
copy: "复制"
metrics: "指标"
overview: "概述"
metrics: "服务器监控"
overview: "服务器概况"
logs: "日志"
delayed: "延迟"
delayed: "滞后"
database: "数据库"
channel: "频道"
create: "创建"
@ -623,17 +627,17 @@ random: "随机"
system: "系统"
switchUi: "切换界面"
desktop: "桌面"
clip: "片段"
clip: "书签"
createNew: "新建"
optional: "可选"
createNewClip: "新建片段"
createNewClip: "新建书签"
public: "公开"
i18nInfo: "Misskey已经被志愿者们翻译到了各种语言。如果你也有兴趣可以通过{link}帮助翻译。"
manageAccessTokens: "管理 Access Tokens"
accountInfo: "帐户信息"
notesCount: "贴文数量"
notesCount: "帖子数量"
repliesCount: "回复数量"
renotesCount: "转数量"
renotesCount: "转数量"
repliedCount: "回复数"
renotedCount: "转发数"
followingCount: "正在关注数量"
@ -644,9 +648,9 @@ pollVotesCount: "问卷调查的投票数"
pollVotedCount: "问卷调查的被投票数"
yes: "是"
no: "否"
driveFilesCount: "磁盘文件数"
driveUsage: "磁盘空间用量"
noCrawle: "拒绝搜索的索引"
driveFilesCount: "网盘的文件数"
driveUsage: "网盘的空间用量"
noCrawle: "拒绝搜索引擎的索引"
noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。"
lockedAccountInfo: "即使通过了关注请求,只要您不将帖子可见范围设置成“关注者”,任何人都可以看到您的帖子。"
alwaysMarkSensitive: "默认将媒体文件标记为敏感内容"
@ -661,7 +665,7 @@ pageLikedCount: "页面被点赞次数"
reversiCount: "黑白棋对战次数"
contact: "联系人"
useSystemFont: "使用系统默认字体"
clips: "片段"
clips: "书签"
experimentalFeatures: "实验性功能"
developer: "开发者"
makeExplorable: "使账号可见。"
@ -693,7 +697,7 @@ saveConfirm: "确定保存?"
deleteConfirm: "确定删除?"
invalidValue: "无效值。"
registry: "注册表"
closeAccount: "关闭账户"
closeAccount: "永久注销账户"
currentVersion: "当前版本"
latestVersion: "最新版本"
youAreRunningUpToDateClient: "您所使用的客户端已经是最新的。"
@ -757,13 +761,17 @@ middle: "中"
low: "低"
emailNotConfiguredWarning: "电子邮件地址未设置。"
ratio: "比率"
customCss: "自定义 CSS"
customCssWarn: "这些设置必须有相关的基础知识,不当的配置可能导致客户端无法正常使用!"
global: "全局"
squareAvatars: "显示方形头像图标"
_ad:
back: "返回"
reduceFrequencyOfThisAd: "减少此广告的频率"
_forgotPassword:
enterEmail: "请输入您用来注册帐户的电子邮地址密码重置链接将发送到该地址。"
ifNoEmail: "如果您没有使用电子邮件地址注册,请联系管理员。"
contactAdmin: "该实例不支持电子邮件。如果您想重设密码,请联系管理员。"
enterEmail: "请输入您验证账号时用的电子邮地址密码重置链接将发送至该邮箱上。"
ifNoEmail: "如果您没有使用电子邮件地址进行验证,请联系管理员。"
contactAdmin: "该实例不支持发送电子邮件。如果您想重设密码,请联系管理员。"
_gallery:
my: "我的图库"
liked: "喜欢的图片"
@ -773,7 +781,7 @@ _email:
_follow:
title: "你有新的关注者"
_receiveFollowRequest:
title: "收到关注请求"
title: "收到关注请求"
_plugin:
install: "安装插件"
installWarn: "请不要安装不可信的插件。"
@ -906,19 +914,20 @@ _channel:
following: "正在关注"
usersCount: "有{n}人参与"
notesCount: "有{n}个帖子"
_sidebar:
full: "全部"
icon: "图标"
_menuDisplay:
sideFull: "横向"
sideIcon: "横向(图标)"
top: "顶部"
hide: "隐藏"
_wordMute:
muteWords: "禁用词"
muteWordsDescription: "使用空格分隔表示AND逻辑使用换行符分隔表示OR逻辑。"
muteWordsDescription2: "将关键字用斜线括起来表示正则表达式。"
softDescription: "隐藏时间线中指定条件的帖。"
hardDescription: "防止将具有指定条件的帖添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
softDescription: "隐藏时间线中指定条件的帖。"
hardDescription: "防止将具有指定条件的帖添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
soft: "软屏蔽"
hard: "硬屏蔽"
mutedNotes: "被屏蔽的帖"
mutedNotes: "被屏蔽的帖"
_theme:
explore: "寻找主题"
install: "安装主题"
@ -944,8 +953,8 @@ _theme:
argument: "参数"
basedProp: "基于的属性名称"
alpha: "不透明度"
darken: "色"
lighten: "色"
darken: "色"
lighten: "色"
inputConstantName: "请输入常量名称"
importInfo: "您可以在此处粘贴主题代码,将其导入到编辑器中"
deleteConstantConfirm: "确定要删除常量{const}吗?"
@ -980,18 +989,18 @@ _theme:
cwBg: "CW 按钮背景"
cwFg: "CW 按钮文本"
cwHoverBg: "CW 按钮背景(悬停)"
toastBg: "吐司通知背景"
toastFg: "吐司通知文本"
toastBg: "Toast通知背景"
toastFg: "Toast通知文本"
buttonBg: "按钮背景"
buttonHoverBg: "按钮背景(悬停)"
inputBorder: "输入框边框"
listItemHoverBg: "下拉列表项目背景(悬停)"
driveFolderBg: "驱动器文件夹背景"
driveFolderBg: "网盘的文件夹背景"
wallpaperOverlay: "壁纸叠加层"
badge: "徽章"
messageBg: "聊天背景"
accentDarken: "强调色()"
accentLighten: "强调色()"
accentDarken: "强调色()"
accentLighten: "强调色()"
fgHighlighted: "高亮显示文本"
_sfx:
note: "帖子"
@ -1090,9 +1099,9 @@ _auth:
_antennaSources:
all: "所有帖子"
homeTimeline: "已关注用户的帖子"
users: "来自定用户的帖子"
userList: "来自特定清单中的帖子"
userGroup: "来自特定组中用户的帖子"
users: "来自定用户的帖子"
userList: "来自指定列表中的帖子"
userGroup: "来自指定群组中用户的帖子"
_weekday:
sunday: "星期日"
monday: "星期一"
@ -1118,7 +1127,7 @@ _widgets:
button: "按钮"
onlineUsers: "在线用户"
jobQueue: "作业队列"
serverMetric: "服务器指标"
serverMetric: "服务器监控"
aiscript: "AiScript控制台"
_cw:
hide: "隐藏"
@ -1131,7 +1140,7 @@ _poll:
noMore: "无法再添加更多了"
canMultipleVote: "允许多个投票"
expiration: "截止时间"
infinite: "无限期"
infinite: "不限时间"
at: "指定日期"
after: "指定时间"
deadlineDate: "截止日期"
@ -1170,7 +1179,7 @@ _postForm:
e: "请写下来吧"
f: "等待您的发布..."
_profile:
name: "称"
name: "称"
username: "用户名"
description: "个人简介"
youCanIncludeHashtags: "您可以包含一个哈希标签。"
@ -1283,7 +1292,7 @@ _rooms:
_pages:
newPage: "创建页面"
editPage: "编辑页面"
readPage: "查看"
readPage: "查看页面"
created: "页面已创建"
updated: "页面已更新"
deleted: "该页面已被删除"
@ -1596,7 +1605,7 @@ _notification:
reaction: "回应"
pollVote: "问卷调查被投票"
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "关注请求已接受"
followRequestAccepted: "关注请求已通过"
groupInvited: "加入群组邀请"
app: "关联应用的通知"
_deck:

View File

@ -1,19 +1,20 @@
---
_lang_: "繁體中文"
headlineMisskey: "貼文連繫網"
introMisskey: "歡迎! Misskey是一個開且去中心化的社群網。\n過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能對大家的貼文表達情感👍\n一起來探索這個新的世界吧🚀"
headlineMisskey: "貼文連繫網"
introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網。\n過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能對大家的貼文表達情感👍\n一起來探索這個新的世界吧🚀"
monthAndDay: "{month}月 {day}日"
search: "搜尋"
notifications: "通知"
username: "使用者名稱"
password: "密碼"
forgotPassword: "忘記密碼"
fetchingAsApObject: "從聯邦宇宙取得中..."
ok: "OK"
gotIt: "知道了"
cancel: "取消"
enterUsername: "輸入使用者名稱"
renotedBy: "{user} 轉了"
noNotes: "貼文不可用。"
renotedBy: "{user} 轉了"
noNotes: "貼文。"
noNotifications: "沒有通知"
instance: "實例"
settings: "設定"
@ -46,8 +47,8 @@ deleteAndEdit: "刪除並編輯"
deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有情感、轉發和回覆也將會消失。"
addToList: "加入至清單"
sendMessage: "發送訊息"
copyUsername: "複製用戶名"
searchUser: "搜尋用戶"
copyUsername: "複製使用者名稱"
searchUser: "搜尋使用者"
reply: "回覆"
loadMore: "載入更多"
showMore: "載入更多"
@ -92,9 +93,9 @@ followRequestPending: "追隨許可批准中"
enterEmoji: "輸入表情符號"
renote: "轉發"
unrenote: "取消轉發"
renoted: "轉成功"
renoted: "轉成功"
cantRenote: "無法轉發此貼文。"
cantReRenote: "無法轉之前已經轉過的內容。"
cantReRenote: "無法轉之前已經轉過的內容。"
quote: "引用"
pinnedNote: "已置頂的貼文"
pinned: "置頂"
@ -278,6 +279,7 @@ emptyDrive: "雲端硬碟為空"
emptyFolder: "資料夾為空"
unableToDelete: "無法刪除"
inputNewFileName: "輸入檔案名稱"
inputNewDescription: "請輸入新標題 "
inputNewFolderName: "輸入新資料夾的名稱"
circularReferenceFolder: "目標文件夾是您要移動的文件夾的子文件夾。"
hasChildFilesOrFolders: "此文件夾不是空的,無法刪除。"
@ -309,8 +311,8 @@ monthX: "{month}月"
yearX: "{year}年"
pages: "頁面"
integration: "整合"
connectSerice: "連線"
disconnectSerice: "中斷連線"
connectService: "己連結"
disconnectService: "己斷開 "
enableLocalTimeline: "開啟本地時間軸"
enableGlobalTimeline: "啟用公開時間軸"
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
@ -324,6 +326,7 @@ driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量"
inMb: "以Mbps為單位"
iconUrl: "圖像URL"
bannerUrl: "橫幅圖像URL"
backgroundImageUrl: "背景圖片的來源網址 "
basicInfo: "基本資訊"
pinnedUsers: "置頂用戶"
pinnedUsersDescription: "在「發現」頁面中使用換行標記想要置頂的使用者。"
@ -475,7 +478,9 @@ objectStorage: "Object Storage (物件儲存)"
useObjectStorage: "使用Object Storage"
objectStorageBaseUrl: "Base URL"
objectStorageBucket: "儲存空間Bucket"
objectStorageBucketDesc: "請指定您正在使用的服務的存儲桶名稱。 "
objectStoragePrefix: "前綴"
objectStoragePrefixDesc: "它存儲在此前綴目錄下。"
objectStorageEndpoint: "端點Endpoint"
objectStorageEndpointDesc: "如要使用AWS S3請留空。否則請依照你使用的服務商的說明書進行設定以'<host>'或 '<host>:<port>'的形式設定端點Endpoint。"
objectStorageRegion: "地域Region"
@ -518,7 +523,6 @@ removeAllFollowing: "解除所有追蹤"
removeAllFollowingDescription: "解除{host}所有的追蹤。在實例不再存在時執行。"
userSuspended: "該使用者已被停用"
userSilenced: "該用戶已被禁言。"
sidebar: "側邊列"
divider: "分割線"
addItem: "新增項目"
rooms: "房間"
@ -538,6 +542,8 @@ disablePlayer: "關閉播放器"
expandTweet: "展開推文"
themeEditor: "主題編輯器"
description: "描述"
describeFile: "添加標題 "
enterFileDescription: "輸入標題 "
author: "作者"
leaveConfirm: "有未保存的更改。要放棄嗎?"
manage: "管理"
@ -731,11 +737,31 @@ switch: "切換"
noMaintainerInformationWarning: "尚未設定管理員信息。"
noBotProtectionWarning: "尚未設定Bot防護。"
configure: "設定"
postToGallery: "發佈到相簿"
gallery: "相簿"
recentPosts: "最新貼文"
popularPosts: "熱門的貼文"
ads: "廣告"
expiration: "期限"
memo: "備忘錄"
priority: "優先級"
high: "高"
middle: "中"
low: "低"
emailNotConfiguredWarning: "沒有設定電子郵件地址"
ratio: "%"
global: "公開"
_ad:
back: "返回"
reduceFrequencyOfThisAd: "降低此廣告的頻率 "
_forgotPassword:
enterEmail: "請輸入您的帳戶註冊的電子郵件地址。 密碼重置連結將被發送到該電子郵件地址。"
ifNoEmail: "如果您還沒有註冊您的電子郵件地址,請聯繫管理員。 "
contactAdmin: "此實例不支持電子郵件,請聯繫您的管理員重置您的密碼。 "
_gallery:
my: "我的貼文"
liked: "喜歡的貼文"
like: "讚"
unlike: "收回喜歡"
_email:
_follow:
@ -776,6 +802,7 @@ _mfm:
url: "URL"
urlDescription: "可以展示URL位址。"
link: "鏈接"
linkDescription: "您可以將特定範圍的文章與 URL 相關聯。 "
bold: "粗體"
small: "縮小"
center: "置中"
@ -786,7 +813,9 @@ _mfm:
blockMath: "數學公式(方塊)"
quote: "引用"
emoji: "自訂表情符號"
emojiDescription: "您可以通過將自定義表情符號名稱括在冒號中來顯示自定義表情符號。 "
search: "搜尋"
searchDescription: "您可以顯示所輸入的搜索框。"
flip: "翻轉"
flipDescription: "將內容上下或左右翻轉。"
jelly: "動畫(果凍)"
@ -855,9 +884,7 @@ _channel:
following: "關注中"
usersCount: "有{n}人參與"
notesCount: "有{n}個貼文"
_sidebar:
full: "全部"
icon: "大頭貼"
_menuDisplay:
hide: "隱藏"
_wordMute:
muteWords: "加入靜音文字"
@ -879,17 +906,27 @@ _theme:
constant: "常數"
defaultValue: "預設值"
color: "顏色"
refProp: "查看屬性 "
key: "按鍵"
func: "函数"
funcKind: "功能類型"
argument: "參數"
basedProp: "要基於的屬性的名稱 "
alpha: "透明度"
darken: "暗度"
lighten: "亮度"
keys:
accent: "重點色彩"
bg: "背景"
fg: "文本"
focus: "聚焦"
indicator: "指標"
panel: "面板"
shadow: "陰影"
header: "標題"
navBg: "側邊欄的背景 "
navFg: "側邊欄的文字"
navHoverFg: "側邊欄文字(懸停) "
navActive: "側邊欄文本 (活動)"
navIndicator: "側邊欄指示符"
link: "鏈接"
@ -971,6 +1008,7 @@ _tutorial:
_2fa:
alreadyRegistered: "此設備已經被註冊過了"
registerDevice: "註冊裝置"
registerKey: "註冊鍵"
step1: "首先,在您的設備上安裝二步驗證程式,例如{a}或{b}。"
step2: "然後掃描螢幕上的QR code。"
_permissions:
@ -1040,6 +1078,7 @@ _widgets:
button: "按鈕"
onlineUsers: "線上的用戶"
jobQueue: "佇列"
serverMetric: "服務器指標 "
_cw:
hide: "隱藏"
show: "瀏覽更多"
@ -1053,6 +1092,7 @@ _poll:
expiration: "期限"
infinite: "無期限"
at: "結束時間"
after: "進度指定 "
deadlineDate: "截止日期"
deadlineTime: "小時"
duration: "時長"
@ -1067,6 +1107,7 @@ _poll:
remainingSeconds: "{s}秒後截止"
_visibility:
public: "公開"
publicDescription: "發布給所有用戶 "
home: "首頁"
followers: "追隨者"
specified: "指定使用者"
@ -1180,6 +1221,7 @@ _rooms:
cube: "立方體"
tv: "電視"
pinguin: "企鵝蠟像"
rubik-cube: "魔術方塊"
poster-h: "海報(橫向)"
poster-v: "海報(直向)"
sofa: " 沙發"
@ -1242,6 +1284,7 @@ _pages:
post: "發佈窗口"
_post:
text: "内容"
attachCanvasImage: "附加相簿圖像 "
canvasId: "畫布ID"
textInput: "插入字串"
_textInput:
@ -1266,6 +1309,7 @@ _pages:
note: "嵌式貼文"
_note:
id: "貼文ID"
idDescription: "您也可以粘貼筆記 URL 並進行設置。 "
detailed: "顯示詳細內容"
switch: "開關"
_switch:
@ -1282,12 +1326,15 @@ _pages:
colored: "彩色"
action: "按下按鈕後發生的行為"
_action:
dialog: "顯示對話框 "
_dialog:
content: "内容"
resetRandom: "重設亂數"
pushEvent: "發送事件"
_pushEvent:
event: "事件名稱"
message: "按下時顯示的消息 "
variable: "要發送的變數"
no-variable: "沒有"
callAiScript: "調用AiScript"
_callAiScript:
@ -1296,6 +1343,7 @@ _pages:
_radioButton:
name: "變數名稱"
title: "標題"
values: "由換行符分隔的選項"
default: "預設值"
script:
categories:
@ -1313,6 +1361,8 @@ _pages:
text: "字串"
multiLineText: "字串(多行)"
textList: "字串串列"
_textList:
info: "請分開每個換行符 "
strLen: "字串長度"
_strLen:
arg1: "字串"
@ -1323,6 +1373,8 @@ _pages:
strReplace: "替換字串"
_strReplace:
arg1: "字串"
arg2: "替換前"
arg3: "替換後"
strReverse: "倒轉字串"
_strReverse:
arg1: "字串"
@ -1389,6 +1441,7 @@ _pages:
_if:
arg1: "如果"
arg2: "如果"
arg3: "除此以外 "
not: "否"
_not:
arg1: "否"
@ -1399,13 +1452,17 @@ _pages:
_rannum:
arg1: "下限"
arg2: "上限"
randomPick: "從列表中隨機選擇 "
_randomPick:
arg1: "清單"
dailyRandom: "隨機(使用者每日變化 )"
_dailyRandom:
arg1: "機率"
dailyRannum: "亂數(使用者每日變化)"
_dailyRannum:
arg1: "下限"
arg2: "上限"
dailyRandomPick: "從列表中隨機選擇(使用者每日變化 "
_dailyRandomPick:
arg1: "清單"
seedRandom: "隨機抽選種子碼"
@ -1444,7 +1501,10 @@ _pages:
aiScriptVar: "AiScript的變數"
fn: "函数"
_fn:
slots: "欄位"
slots-info: "用換行符分隔每個欄位"
arg1: "輸出"
for: "重複 "
_for:
arg1: "重複次數"
arg2: "處理"
@ -1454,13 +1514,16 @@ _pages:
boolean: "標記"
array: "清單"
stringArray: "字串列表"
emptySlot: "空欄位"
enviromentVariables: "環境變數"
pageVariables: "頁面元素"
argVariables: "輸入欄位"
_relayStatus:
requesting: "等待核准"
accepted: "已通過核准"
rejected: "已拒絕"
_notification:
fileUploaded: "上傳檔案成功。"
youGotMention: "{name}提及到您"
youGotReply: "{name}回覆了您"
youGotQuote: "{name}引用了您"

View File

@ -0,0 +1,16 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class addNoteIndexes1621479946000 implements MigrationInterface {
name = 'addNoteIndexes1621479946000'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE INDEX "IDX_NOTE_MENTIONS" ON "note" USING gin ("mentions")`, undefined);
await queryRunner.query(`CREATE INDEX "IDX_NOTE_VISIBLE_USER_IDS" ON "note" USING gin ("visibleUserIds")`, undefined);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_NOTE_MENTIONS"`, undefined);
await queryRunner.query(`DROP INDEX "IDX_NOTE_VISIBLE_USER_IDS"`, undefined);
}
}

View File

@ -0,0 +1,13 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class userProfileDescriptionLength1622679304522 implements MigrationInterface {
name = 'userProfileDescriptionLength1622679304522';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(2048)`, undefined);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(1024)`, undefined);
}
}

View File

@ -0,0 +1,12 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class logMessageLength1622681548499 implements MigrationInterface {
name = 'logMessageLength1622681548499';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(2048)`, undefined);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(1024)`, undefined);
}
}

View File

@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.81.0",
"version": "12.84.2",
"codename": "indigo",
"repository": {
"type": "git",
@ -31,116 +31,114 @@
},
"resolutions": {
"chokidar": "^3.3.1",
"constantinople": "^4.0.1",
"jsonld/rdf-canonize/node-forge": "0.10.0",
"lodash": "^4.17.20"
"lodash": "^4.17.21"
},
"dependencies": {
"@babel/plugin-transform-runtime": "7.13.15",
"@babel/plugin-transform-runtime": "7.14.5",
"@elastic/elasticsearch": "7.11.0",
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
"@koa/router": "9.0.1",
"@sentry/browser": "5.29.2",
"@sentry/tracing": "5.29.2",
"@sinonjs/fake-timers": "7.0.5",
"@sinonjs/fake-timers": "7.1.2",
"@syuilo/aiscript": "0.11.1",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.15.1",
"@types/cbor": "5.0.1",
"@types/bull": "3.15.2",
"@types/cbor": "6.0.0",
"@types/dateformat": "3.0.1",
"@types/escape-regexp": "0.0.0",
"@types/glob": "7.1.3",
"@types/gulp": "4.0.8",
"@types/gulp-rename": "2.0.0",
"@types/is-url": "1.2.28",
"@types/js-yaml": "4.0.1",
"@types/jsdom": "16.2.10",
"@types/jsonld": "1.5.5",
"@types/katex": "0.11.0",
"@types/koa": "2.13.1",
"@types/koa-bodyparser": "4.3.0",
"@types/koa-cors": "0.0.0",
"@types/koa-favicon": "2.0.19",
"@types/glob": "7.1.4",
"@types/gulp": "4.0.9",
"@types/gulp-rename": "2.0.1",
"@types/is-url": "1.2.30",
"@types/js-yaml": "4.0.2",
"@types/jsdom": "16.2.13",
"@types/jsonld": "1.5.6",
"@types/katex": "0.11.1",
"@types/koa": "2.13.4",
"@types/koa-bodyparser": "4.3.2",
"@types/koa-cors": "0.0.1",
"@types/koa-favicon": "2.0.21",
"@types/koa-logger": "3.1.1",
"@types/koa-mount": "4.0.0",
"@types/koa-send": "4.1.2",
"@types/koa-views": "2.0.4",
"@types/koa__cors": "3.0.2",
"@types/koa__multer": "2.0.2",
"@types/koa__router": "8.0.4",
"@types/markdown-it": "12.0.1",
"@types/matter-js": "0.14.11",
"@types/mocha": "8.2.2",
"@types/node": "14.14.41",
"@types/node-fetch": "2.5.10",
"@types/nodemailer": "6.4.1",
"@types/koa-send": "4.1.3",
"@types/koa-views": "7.0.0",
"@types/koa__cors": "3.0.3",
"@types/koa__multer": "2.0.3",
"@types/koa__router": "8.0.7",
"@types/markdown-it": "12.0.3",
"@types/matter-js": "0.17.3",
"@types/mocha": "8.2.3",
"@types/node": "16.3.3",
"@types/node-fetch": "2.5.11",
"@types/nodemailer": "6.4.4",
"@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1",
"@types/parse5": "6.0.0",
"@types/parse5": "6.0.1",
"@types/parsimmon": "1.10.6",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/portscanner": "2.1.1",
"@types/pug": "2.0.5",
"@types/punycode": "2.1.0",
"@types/qrcode": "1.4.0",
"@types/qrcode": "1.4.1",
"@types/random-seed": "0.3.3",
"@types/ratelimiter": "3.4.1",
"@types/redis": "2.8.28",
"@types/rename": "1.0.2",
"@types/ratelimiter": "3.4.2",
"@types/redis": "2.8.31",
"@types/rename": "1.0.4",
"@types/request-stats": "3.0.0",
"@types/rimraf": "3.0.0",
"@types/rimraf": "3.0.1",
"@types/seedrandom": "2.4.28",
"@types/sharp": "0.28.0",
"@types/sinonjs__fake-timers": "6.0.2",
"@types/speakeasy": "2.0.5",
"@types/sharp": "0.28.4",
"@types/sinonjs__fake-timers": "6.0.3",
"@types/speakeasy": "2.0.6",
"@types/throttle-debounce": "2.1.0",
"@types/tinycolor2": "1.4.2",
"@types/tmp": "0.2.0",
"@types/uuid": "8.3.0",
"@types/web-push": "3.3.0",
"@types/tinycolor2": "1.4.3",
"@types/tmp": "0.2.1",
"@types/uuid": "8.3.1",
"@types/web-push": "3.3.2",
"@types/webpack": "5.28.0",
"@types/webpack-stream": "3.2.12",
"@types/websocket": "1.0.2",
"@types/ws": "7.4.1",
"@typescript-eslint/parser": "4.22.0",
"@vue/compiler-sfc": "3.0.11",
"@types/websocket": "1.0.3",
"@types/ws": "7.4.6",
"@typescript-eslint/parser": "4.28.3",
"@vue/compiler-sfc": "3.1.5",
"abort-controller": "3.0.0",
"apexcharts": "3.26.1",
"apexcharts": "3.27.2",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autosize": "4.0.4",
"autwh": "0.1.0",
"aws-sdk": "2.892.0",
"aws-sdk": "2.948.0",
"bcryptjs": "2.4.3",
"blurhash": "1.1.3",
"broadcast-channel": "3.5.3",
"bull": "3.22.3",
"broadcast-channel": "3.7.0",
"bull": "3.26.0",
"cafy": "15.2.1",
"cbor": "7.0.5",
"cbor": "7.0.6",
"chalk": "4.1.1",
"chart.js": "2.9.4",
"cli-highlight": "2.1.11",
"commander": "7.2.0",
"concurrently": "6.0.2",
"concurrently": "6.2.0",
"content-disposition": "0.5.3",
"core-js": "3.11.0",
"core-js": "3.15.2",
"crc-32": "1.2.0",
"css-loader": "5.2.4",
"cssnano": "5.0.1",
"css-loader": "6.0.0",
"cssnano": "5.0.6",
"dateformat": "4.5.1",
"diskusage": "1.1.3",
"escape-regexp": "0.0.1",
"eslint": "7.25.0",
"eslint-plugin-vue": "7.9.0",
"eslint": "7.30.0",
"eslint-plugin-vue": "7.13.0",
"eventemitter3": "4.0.7",
"feed": "4.2.2",
"file-type": "16.3.0",
"file-type": "16.5.1",
"fluent-ffmpeg": "2.1.2",
"glob": "7.1.6",
"glob": "7.1.7",
"got": "11.8.2",
"gulp": "4.0.2",
"gulp-cssnano": "2.1.3",
"gulp-rename": "2.0.0",
"gulp-replace": "1.1.1",
"gulp-replace": "1.1.3",
"gulp-terser": "2.0.1",
"gulp-tslint": "8.1.4",
"hard-source-webpack-plugin": "0.13.1",
@ -148,17 +146,17 @@
"http-proxy-agent": "4.0.1",
"http-signature": "1.3.5",
"https-proxy-agent": "5.0.0",
"idb-keyval": "5.0.5",
"idb-keyval": "5.0.6",
"insert-text-at-cursor": "0.3.0",
"is-root": "2.1.0",
"is-svg": "4.3.1",
"js-yaml": "4.1.0",
"jsdom": "16.5.3",
"jsdom": "16.6.0",
"json5": "2.2.0",
"json5-loader": "4.0.1",
"jsonld": "4.0.1",
"jsonld": "5.2.0",
"jsrsasign": "8.0.20",
"katex": "0.13.3",
"katex": "0.13.11",
"koa": "2.13.1",
"koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0",
@ -170,26 +168,27 @@
"koa-views": "7.0.1",
"langmap": "0.0.16",
"lookup-dns-cache": "2.1.0",
"markdown-it": "12.0.6",
"markdown-it": "12.1.0",
"markdown-it-anchor": "7.1.0",
"matter-js": "0.17.1",
"mfm-js": "0.16.3",
"mocha": "8.3.2",
"mfm-js": "0.19.0",
"misskey-js": "0.0.6",
"mocha": "8.4.0",
"moji": "0.5.1",
"ms": "2.1.3",
"multer": "1.4.2",
"nested-property": "4.0.0",
"node-fetch": "2.6.1",
"nodemailer": "6.5.0",
"nodemailer": "6.6.3",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
"parse5": "6.0.1",
"pg": "8.6.0",
"portscanner": "2.2.0",
"postcss": "8.2.12",
"postcss-loader": "5.2.0",
"prismjs": "1.23.0",
"probe-image-size": "7.1.0",
"postcss": "8.3.5",
"postcss-loader": "6.1.1",
"prismjs": "1.24.1",
"probe-image-size": "7.2.1",
"promise-limit": "2.7.0",
"promise-sequential": "1.1.1",
"pug": "3.0.2",
@ -198,7 +197,7 @@
"qrcode": "1.4.4",
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
"re2": "1.15.9",
"re2": "1.16.0",
"reconnecting-websocket": "4.4.0",
"redis": "3.1.2",
"redis-lock": "0.1.4",
@ -210,48 +209,49 @@
"rimraf": "3.0.2",
"rndstr": "1.0.0",
"s-age": "1.1.2",
"sass": "1.32.11",
"sass-loader": "11.0.1",
"sass": "1.35.2",
"sass-loader": "12.1.0",
"seedrandom": "3.0.5",
"sharp": "0.28.1",
"sharp": "0.28.3",
"speakeasy": "2.0.0",
"stringz": "2.1.0",
"style-loader": "2.0.0",
"style-loader": "3.1.0",
"summaly": "2.4.0",
"syslog-pro": "1.0.0",
"systeminformation": "5.6.12",
"systeminformation": "5.7.7",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.117.1",
"throttle-debounce": "3.0.1",
"tinycolor2": "1.4.2",
"tmp": "0.2.1",
"ts-loader": "9.1.1",
"ts-node": "9.1.1",
"tsc-alias": "1.2.10",
"tsconfig-paths": "3.9.0",
"ts-loader": "9.2.3",
"ts-node": "10.1.0",
"tsc-alias": "1.3.7",
"tsconfig-paths": "3.10.1",
"tslint": "6.1.3",
"tslint-sonarts": "1.9.0",
"twemoji-parser": "13.1.0",
"typeorm": "0.2.32",
"typescript": "4.2.4",
"typescript": "4.3.5",
"ulid": "2.3.0",
"uuid": "8.3.2",
"v-debounce": "0.1.2",
"vanilla-tilt": "1.7.0",
"vue": "3.0.11",
"vue": "3.1.5",
"vue-color": "2.8.1",
"vue-json-pretty": "1.7.1",
"vue-loader": "16.1.2",
"vue-json-pretty": "1.8.1",
"vue-loader": "16.3.1",
"vue-prism-editor": "2.0.0-alpha.2",
"vue-router": "4.0.5",
"vue-style-loader": "4.1.3",
"vue-svg-loader": "0.17.0-beta.2",
"vuedraggable": "4.0.1",
"web-push": "3.4.4",
"webpack": "5.35.1",
"webpack-cli": "4.6.0",
"web-push": "3.4.5",
"webpack": "5.45.1",
"webpack-cli": "4.7.2",
"websocket": "1.0.34",
"ws": "7.4.5",
"ws": "7.5.3",
"xev": "2.0.1"
},
"devDependencies": {

View File

@ -8,6 +8,8 @@ import { unisonReload } from '@client/scripts/unison-reload';
type Account = {
id: string;
token: string;
isModerator: boolean;
isAdmin: boolean;
};
const data = localStorage.getItem('account');
@ -45,7 +47,7 @@ function fetchAccount(token): Promise<Account> {
})
.then(res => {
// When failed to authenticate user
if (res.status !== 200 && res.status < 500) {
if (res.status >= 400 && res.status < 500) {
return signout();
}

View File

@ -5,7 +5,8 @@
:cy="5 - (Math.cos(angle) * (5 - graduationsPadding))"
:r="i % 5 == 0 ? 0.125 : 0.05"
:fill="i % 5 == 0 ? majorGraduationColor : minorGraduationColor"
:key="i"/>
:key="i"
/>
<line
:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
@ -13,7 +14,9 @@
:x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:stroke="sHandColor"
stroke-width="0.05"/>
:stroke-width="thickness / 2"
stroke-linecap="round"
/>
<line
:x1="5 - (Math.sin(mAngle) * (mHandLengthRatio * handsTailLength))"
@ -21,7 +24,9 @@
:x2="5 + (Math.sin(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
:stroke="mHandColor"
stroke-width="0.1"/>
:stroke-width="thickness"
stroke-linecap="round"
/>
<line
:x1="5 - (Math.sin(hAngle) * (hHandLengthRatio * handsTailLength))"
@ -29,16 +34,24 @@
:x2="5 + (Math.sin(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
:stroke="hHandColor"
stroke-width="0.1"/>
:stroke-width="thickness"
stroke-linecap="round"
/>
</svg>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import * as tinycolor from 'tinycolor2';
import * as os from '@client/os';
export default defineComponent({
props: {
thickness: {
type: Number,
default: 0.1
}
},
data() {
return {
now: new Date(),

View File

@ -1,11 +1,11 @@
<script lang="ts">
import { defineComponent, h, TransitionGroup } from 'vue';
import { defineComponent, h, PropType, TransitionGroup } from 'vue';
import MkAd from '@client/components/global/ad.vue';
export default defineComponent({
props: {
items: {
type: Array,
type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>,
required: true,
},
direction: {

View File

@ -87,6 +87,10 @@ export default defineComponent({
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash',
action: this.toggleSensitive
}, {
text: this.$ts.describeFile,
icon: 'fas fa-i-cursor',
action: this.describe
}, null, {
text: this.$ts.copyUrl,
icon: 'fas fa-link',
@ -150,6 +154,26 @@ export default defineComponent({
});
},
describe() {
os.popup(import('@client/components/media-caption.vue'), {
title: this.$ts.describeFile,
input: {
placeholder: this.$ts.inputNewDescription,
default: this.file.comment !== null ? this.file.comment : '',
},
image: this.file
}, {
done: result => {
if (!result || result.canceled) return;
let comment = result.result;
os.api('drive/files/update', {
fileId: this.file.id,
comment: comment.length == 0 ? null : comment
});
}
}, 'closed');
},
toggleSensitive() {
os.api('drive/files/update', {
fileId: this.file.id,

View File

@ -139,7 +139,7 @@ export default defineComponent({
});
}
this.connection = os.stream.useSharedConnection('drive');
this.connection = os.stream.useChannel('drive');
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
@ -301,7 +301,7 @@ export default defineComponent({
}
}).then(({ canceled, result: url }) => {
if (canceled) return;
os.api('drive/files/upload_from_url', {
os.api('drive/files/upload-from-url', {
url: url,
folderId: this.folder ? this.folder.id : undefined
});

View File

@ -1,5 +1,5 @@
<template>
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
</MkModal>
</template>

View File

@ -1,7 +1,5 @@
<template>
<div class="xfbouadm" v-if="meta" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }">
</div>
<div class="xfbouadm" v-if="meta" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }"></div>
</template>
<script lang="ts">

View File

@ -71,7 +71,7 @@ export default defineComponent({
},
mounted() {
this.connection = os.stream.useSharedConnection('main');
this.connection = os.stream.useChannel('main');
this.connection.on('follow', this.onFollowChange);
this.connection.on('unfollow', this.onFollowChange);

View File

@ -34,6 +34,10 @@
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
<option v-for="item in form[item].enum" :value="item.value" :key="item.value">{{ item.label }}</option>
</FormSelect>
<FormRadios v-else-if="form[item].type === 'radio'" v-model="values[item]">
<template #desc><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
<option v-for="item in form[item].options" :value="item.value" :key="item.value">{{ item.label }}</option>
</FormRadios>
<FormRange v-else-if="form[item].type === 'range'" v-model:value="values[item]" :min="form[item].mim" :max="form[item].max" :step="form[item].step">
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
@ -56,6 +60,7 @@ import FormSwitch from './form/switch.vue';
import FormSelect from './form/select.vue';
import FormRange from './form/range.vue';
import FormButton from './form/button.vue';
import FormRadios from './form/radios.vue';
export default defineComponent({
components: {
@ -67,6 +72,7 @@ export default defineComponent({
FormSelect,
FormRange,
FormButton,
FormRadios,
},
props: {

View File

@ -27,7 +27,10 @@ export default defineComponent({
},
render() {
const label = this.$slots.desc();
const options = this.$slots.default();
let options = this.$slots.default();
// なぜかFragmentになることがあるため
if (options.length === 1 && options[0].props == null) options = options[0].children;
return h('div', {
class: 'cnklmpwm _formItem'
@ -37,7 +40,7 @@ export default defineComponent({
}, label),
...options.map(option => h('button', {
class: '_button _formPanel _formClickable',
key: option.props.value,
key: option.key,
onClick: () => this.value = option.props.value,
}, [h('span', {
class: ['check', { checked: this.value === option.props.value }],

View File

@ -1,9 +1,9 @@
<template>
<span class="eiwwqkts _noSelect" :class="{ cat }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
<span class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
<img class="inner" :src="url" decoding="async"/>
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
</span>
<MkA class="eiwwqkts _noSelect" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
<MkA class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
<img class="inner" :src="url" decoding="async"/>
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
</MkA>
@ -81,28 +81,6 @@ export default defineComponent({
border-radius: 100%;
line-height: 16px;
&.cat {
&:before, &:after {
background: #df548f;
border: solid 4px currentColor;
box-sizing: border-box;
content: '';
display: inline-block;
height: 50%;
width: 50%;
}
&:before {
border-radius: 0 75% 75%;
transform: rotate(37.5deg) skew(30deg);
}
&:after {
border-radius: 75% 0 75% 75%;
transform: rotate(-37.5deg) skew(-30deg);
}
}
> .inner {
position: absolute;
bottom: 0;
@ -125,5 +103,35 @@ export default defineComponent({
width: 20%;
height: 20%;
}
&.square {
border-radius: 20%;
> .inner {
border-radius: 20%;
}
}
&.cat {
&:before, &:after {
background: #df548f;
border: solid 4px currentColor;
box-sizing: border-box;
content: '';
display: inline-block;
height: 50%;
width: 50%;
}
&:before {
border-radius: 0 75% 75%;
transform: rotate(37.5deg) skew(30deg);
}
&:after {
border-radius: 75% 0 75% 75%;
transform: rotate(-37.5deg) skew(-30deg);
}
}
}
</style>

View File

@ -2,7 +2,7 @@
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
<div class="xubzgfga">
<header>{{ image.name }}</header>
<img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/>
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
<footer>
<span>{{ image.type }}</span>
<span>{{ bytes(image.size) }}</span>

View File

@ -36,7 +36,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import MkModal from '@client/components/ui/modal.vue';
import { sidebarDef } from '@client/sidebar';
import { menuDef } from '@client/menu';
import { instanceName } from '@client/config';
export default defineComponent({
@ -48,7 +48,7 @@ export default defineComponent({
data() {
return {
menuDef: sidebarDef,
menuDef: menuDef,
items: [],
instanceName,
};

View File

@ -87,8 +87,6 @@ export default defineComponent({
> .icon {
padding-left: 2px;
font-size: .9em;
font-weight: 400;
font-style: normal;
}
}
</style>

View File

@ -0,0 +1,238 @@
<template>
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
<div class="container">
<div class="fullwidth top-caption">
<div class="mk-dialog">
<header v-if="title"><Mfm :text="title"/></header>
<textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
<div class="buttons" v-if="(showOkButton || showCancelButton)">
<MkButton inline @click="ok" primary>{{ $ts.ok }}</MkButton>
<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton>
</div>
</div>
</div>
<div class="hdrwpsaf fullwidth">
<header>{{ image.name }}</header>
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
<footer>
<span>{{ image.type }}</span>
<span>{{ bytes(image.size) }}</span>
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
</footer>
</div>
</div>
</MkModal>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MkModal from '@client/components/ui/modal.vue';
import MkButton from '@client/components/ui/button.vue';
import bytes from '@client/filters/bytes';
import number from '@client/filters/number';
export default defineComponent({
components: {
MkModal,
MkButton,
},
props: {
image: {
type: Object,
required: true,
},
title: {
type: String,
required: false
},
input: {
required: true
},
showOkButton: {
type: Boolean,
default: true
},
showCancelButton: {
type: Boolean,
default: true
},
cancelableByBgClick: {
type: Boolean,
default: true
},
},
emits: ['done', 'closed'],
data() {
return {
inputValue: this.input.default ? this.input.default : null
};
},
mounted() {
document.addEventListener('keydown', this.onKeydown);
},
beforeUnmount() {
document.removeEventListener('keydown', this.onKeydown);
},
methods: {
bytes,
number,
done(canceled, result?) {
this.$emit('done', { canceled, result });
this.$refs.modal.close();
},
async ok() {
if (!this.showOkButton) return;
const result = this.inputValue;
this.done(false, result);
},
cancel() {
this.done(true);
},
onBgClick() {
if (this.cancelableByBgClick) {
this.cancel();
}
},
onKeydown(e) {
if (e.which === 27) { // ESC
this.cancel();
}
},
onInputKeydown(e) {
if (e.which === 13) { // Enter
if (e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
this.ok();
}
}
}
}
});
</script>
<style lang="scss" scoped>
.container {
display: flex;
width: 100%;
height: 100%;
flex-direction: row;
}
@media (max-width: 850px) {
.container {
flex-direction: column;
}
.top-caption {
padding-bottom: 8px;
}
}
.fullwidth {
width: 100%;
margin: auto;
}
.mk-dialog {
position: relative;
padding: 32px;
min-width: 320px;
max-width: 480px;
box-sizing: border-box;
text-align: center;
background: var(--panel);
border-radius: var(--radius);
margin: auto;
> header {
margin: 0 0 8px 0;
font-weight: bold;
font-size: 20px;
}
> .buttons {
margin-top: 16px;
> * {
margin: 0 8px;
}
}
> textarea {
display: block;
box-sizing: border-box;
padding: 0 24px;
margin: 0;
width: 100%;
font-size: 16px;
border: none;
border-radius: 0;
background: transparent;
color: var(--fg);
font-family: inherit;
max-width: 100%;
min-width: 100%;
min-height: 90px;
&:focus {
outline: none;
}
&:disabled {
opacity: 0.5;
}
}
}
.hdrwpsaf {
display: flex;
flex-direction: column;
height: 100%;
> header,
> footer {
align-self: center;
display: inline-block;
padding: 6px 9px;
font-size: 90%;
background: rgba(0, 0, 0, 0.5);
border-radius: 6px;
color: #fff;
}
> header {
margin-bottom: 8px;
opacity: 0.9;
}
> img {
display: block;
flex: 1;
min-height: 0;
object-fit: contain;
width: 100%;
cursor: zoom-out;
image-orientation: from-image;
}
> footer {
margin-top: 8px;
opacity: 0.8;
> span + span {
margin-left: 0.5em;
padding-left: 0.5em;
border-left: solid 1px rgba(255, 255, 255, 0.5);
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="qjewsnkg" v-if="hide" @click="hide = false">
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/>
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
<div class="text">
<div>
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
@ -14,7 +14,7 @@
:title="image.name"
@click.prevent="onClick"
>
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/>
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
</a>
<i class="fas fa-eye-slash" @click="hide = true"></i>

View File

@ -9,7 +9,6 @@
<video
:poster="video.thumbnailUrl"
:title="video.name"
crossorigin="anonymous"
preload="none"
controls
>

View File

@ -109,7 +109,7 @@ export default defineComponent({
this.readObserver.observe(this.$el);
this.connection = os.stream.useSharedConnection('main');
this.connection = os.stream.useChannel('main');
this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el));
}
},

View File

@ -12,10 +12,10 @@
<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
</XList>
<button class="_buttonPrimary" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<MkButton primary style="margin: var(--margin) auto;" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
<template v-if="moreFetching"><MkLoading inline/></template>
</button>
</MkButton>
</div>
</transition>
</template>
@ -28,12 +28,14 @@ import XList from './date-separated-list.vue';
import XNote from './note.vue';
import { notificationTypes } from '../../types';
import * as os from '@client/os';
import MkButton from '@client/components/ui/button.vue';
export default defineComponent({
components: {
XNotification,
XList,
XNote,
MkButton,
},
mixins: [
@ -87,7 +89,7 @@ export default defineComponent({
},
mounted() {
this.connection = os.stream.useSharedConnection('main');
this.connection = os.stream.useChannel('main');
this.connection.on('notification', this.onNotification);
},

View File

@ -10,7 +10,7 @@
</span>
</li>
</ul>
<p>
<p v-if="!readOnly">
<span>{{ $t('_poll.totalVotes', { n: total }) }}</span>
<span> · </span>
<a v-if="!closed && !isVoted" @click="toggleShowResult">{{ showResult ? $ts._poll.vote : $ts._poll.showResult }}</a>
@ -31,6 +31,11 @@ export default defineComponent({
note: {
type: Object,
required: true
},
readOnly: {
type: Boolean,
required: false,
default: false,
}
},
data() {
@ -65,7 +70,7 @@ export default defineComponent({
}
},
created() {
this.showResult = this.isVoted;
this.showResult = this.readOnly || this.isVoted;
if (this.note.poll.expiresAt) {
const update = () => {
@ -83,7 +88,7 @@ export default defineComponent({
this.showResult = !this.showResult;
},
vote(id) {
if (this.closed || !this.poll.multiple && this.poll.choices.some(c => c.isVoted)) return;
if (this.readOnly || this.closed || !this.poll.multiple && this.poll.choices.some(c => c.isVoted)) return;
os.api('notes/polls/vote', {
noteId: this.note.id,
choice: id

View File

@ -89,6 +89,27 @@ export default defineComponent({
file.name = result;
});
},
async describe(file) {
os.popup(import("@client/components/media-caption.vue"), {
title: this.$ts.describeFile,
input: {
placeholder: this.$ts.inputNewDescription,
default: file.comment !== null ? file.comment : "",
},
image: file
}, {
done: result => {
if (!result || result.canceled) return;
let comment = result.result;
os.api('drive/files/update', {
fileId: file.id,
comment: comment.length == 0 ? null : comment
});
}
}, 'closed');
},
showFileMenu(file, ev: MouseEvent) {
if (this.menu) return;
this.menu = os.modalMenu([{
@ -99,6 +120,10 @@ export default defineComponent({
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
action: () => { this.toggleSensitive(file) }
}, {
text: this.$ts.describeFile,
icon: 'fas fa-i-cursor',
action: () => { this.describe(file) }
}, {
text: this.$ts.attachCancel,
icon: 'fas fa-times-circle',

View File

@ -61,7 +61,7 @@ import * as mfm from 'mfm-js';
import { host, url } from '@client/config';
import { erase, unique } from '../../prelude/array';
import { extractMentions } from '@/misc/extract-mentions';
import getAcct from '@/misc/acct/render';
import { getAcct } from '@/misc/acct';
import { formatTimeString } from '@/misc/format-time-string';
import { Autocomplete } from '@client/scripts/autocomplete';
import { noteVisibilities } from '../../types';

View File

@ -14,7 +14,7 @@ export default defineComponent({
class: 'pxhvhrfw',
}, options.map(option => withDirectives(h('button', {
class: ['_button', { active: this.value === option.props.value }],
key: option.props.value,
key: option.key,
disabled: this.value === option.props.value,
onClick: () => {
this.$emit('update:value', option.props.value);

View File

@ -92,33 +92,33 @@ export default defineComponent({
this.query = {
antennaId: this.antenna
};
this.connection = os.stream.connectToChannel('antenna', {
this.connection = os.stream.useChannel('antenna', {
antennaId: this.antenna
});
this.connection.on('note', prepend);
} else if (this.src == 'home') {
endpoint = 'notes/timeline';
this.connection = os.stream.useSharedConnection('homeTimeline');
this.connection = os.stream.useChannel('homeTimeline');
this.connection.on('note', prepend);
this.connection2 = os.stream.useSharedConnection('main');
this.connection2 = os.stream.useChannel('main');
this.connection2.on('follow', onChangeFollowing);
this.connection2.on('unfollow', onChangeFollowing);
} else if (this.src == 'local') {
endpoint = 'notes/local-timeline';
this.connection = os.stream.useSharedConnection('localTimeline');
this.connection = os.stream.useChannel('localTimeline');
this.connection.on('note', prepend);
} else if (this.src == 'social') {
endpoint = 'notes/hybrid-timeline';
this.connection = os.stream.useSharedConnection('hybridTimeline');
this.connection = os.stream.useChannel('hybridTimeline');
this.connection.on('note', prepend);
} else if (this.src == 'global') {
endpoint = 'notes/global-timeline';
this.connection = os.stream.useSharedConnection('globalTimeline');
this.connection = os.stream.useChannel('globalTimeline');
this.connection.on('note', prepend);
} else if (this.src == 'mentions') {
endpoint = 'notes/mentions';
this.connection = os.stream.useSharedConnection('main');
this.connection = os.stream.useChannel('main');
this.connection.on('mention', prepend);
} else if (this.src == 'directs') {
endpoint = 'notes/mentions';
@ -130,14 +130,14 @@ export default defineComponent({
prepend(note);
}
};
this.connection = os.stream.useSharedConnection('main');
this.connection = os.stream.useChannel('main');
this.connection.on('mention', onNote);
} else if (this.src == 'list') {
endpoint = 'notes/user-list-timeline';
this.query = {
listId: this.list
};
this.connection = os.stream.connectToChannel('userList', {
this.connection = os.stream.useChannel('userList', {
listId: this.list
});
this.connection.on('note', prepend);
@ -148,7 +148,7 @@ export default defineComponent({
this.query = {
channelId: this.channel
};
this.connection = os.stream.connectToChannel('channel', {
this.connection = os.stream.useChannel('channel', {
channelId: this.channel
});
this.connection.on('note', prepend);

View File

@ -191,6 +191,8 @@ export default defineComponent({
}
> .content {
--stickyTop: 0px;
&.omitted {
position: relative;
max-height: var(--maxHeight);

View File

@ -1,6 +1,6 @@
<template>
<transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? popup ? 500 : 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
<div v-show="manualShowing != null ? manualShowing : showing" class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div v-show="manualShowing != null ? manualShowing : showing" class="qzhlnise" :class="{ front }" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div class="bg _modalBg" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div>
<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content">
<slot></slot>
@ -41,6 +41,11 @@ export default defineComponent({
},
position: {
required: false
},
front: {
type: Boolean,
required: false,
default: false,
}
},
emits: ['opening', 'click', 'esc', 'close', 'closed'],
@ -224,14 +229,14 @@ export default defineComponent({
}
}
.mk-modal {
.qzhlnise {
> .bg {
z-index: 20000;
z-index: 10000;
}
> .content:not(.popup) {
position: fixed;
z-index: 20000;
z-index: 10000;
top: 0;
bottom: 0;
left: 0;
@ -263,11 +268,25 @@ export default defineComponent({
> .content.popup {
position: absolute;
z-index: 20000;
z-index: 10000;
&.fixed {
position: fixed;
}
}
&.front {
> .bg {
z-index: 20000;
}
> .content:not(.popup) {
z-index: 20000;
}
> .content.popup {
z-index: 20000;
}
}
}
</style>

View File

@ -23,14 +23,17 @@ export default defineComponent({
},
render() {
const label = this.$slots.desc();
const options = this.$slots.default();
let options = this.$slots.default();
// なぜかFragmentになることがあるため
if (options.length === 1 && options[0].props == null) options = options[0].children;
return h('div', {
class: 'novjtcto'
}, [
h('div', label),
...options.map(option => h(MkRadio, {
key: option.props.value,
key: option.key,
value: option.props.value,
modelValue: this.value,
'onUpdate:modelValue': value => this.value = value,

View File

@ -29,7 +29,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import MkFollowButton from './follow-button.vue';
import { userPage } from '../filters/user';

View File

@ -33,7 +33,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import MkFollowButton from './follow-button.vue';
import { userPage } from '../filters/user';
import * as os from '@client/os';

View File

@ -43,6 +43,7 @@ export default defineComponent({
props: {
widgets: {
type: Array,
required: true,
},
edit: {

View File

@ -6,7 +6,7 @@ export default {
const header = src.children[0];
const currentStickyTop = getComputedStyle(src).getPropertyValue('--stickyTop') || '0px';
src.style.setProperty('--stickyTop', `${parseInt(currentStickyTop) + header.offsetHeight}px`);
src.style.setProperty('--stickyTop', `calc(${currentStickyTop} + ${header.offsetHeight}px)`);
header.style.setProperty('--stickyTop', currentStickyTop);
header.style.position = 'sticky';
header.style.top = 'var(--stickyTop)';

View File

@ -1,4 +1,4 @@
import getAcct from '@/misc/acct/render';
import { getAcct } from '@/misc/acct';
import getUserName from '@/misc/get-user-name';
import { url } from '@client/config';

View File

@ -34,18 +34,6 @@ console.info(`Misskey v${version}`);
window.onerror = null;
window.onunhandledrejection = null;
// 後方互換性のため。
// TODO: そのうち消す
if ((typeof ColdDeviceStorage.get('lightTheme') === 'string') || (typeof ColdDeviceStorage.get('darkTheme') === 'string')) {
ColdDeviceStorage.set('lightTheme', require('@client/themes/l-light.json5'));
ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.json5'));
}
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://use.fontawesome.com/releases/v5.15.3/css/all.css';
document.head.appendChild(link);
// TODOここまで
if (_DEV_) {
console.warn('Development mode!!!');
@ -163,8 +151,6 @@ fetchInstance().then(() => {
initializeSw();
});
stream.init($i);
const app = createApp(await (
window.location.search === '?zen' ? import('@client/ui/zen.vue') :
!$i ? import('@client/ui/visitor.vue') :
@ -296,7 +282,7 @@ if ($i) {
}
}
const main = stream.useSharedConnection('main', 'System');
const main = stream.useChannel('main', null, 'System');
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
@ -358,10 +344,6 @@ if ($i) {
sound.play('channel');
});
main.on('readAllAnnouncements', () => {
updateAccount({ hasUnreadAnnouncement: false });
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {

View File

@ -1,26 +1,14 @@
import { computed, reactive } from 'vue';
import * as Misskey from 'misskey-js';
import { api } from './os';
// TODO: 他のタブと永続化されたstateを同期
export type Instance = {
emojis: {
category: string;
}[];
ads: {
id: string;
ratio: number;
place: string;
url: string;
imageUrl: string;
}[];
};
const data = localStorage.getItem('instance');
// TODO: instanceをリアクティブにするかは再考の余地あり
export const instance: Instance = reactive(data ? JSON.parse(data) : {
export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : {
// TODO: set default values
});

View File

@ -5,7 +5,7 @@ import { i18n } from '@client/i18n';
import { $i } from './account';
import { unisonReload } from '@client/scripts/unison-reload';
export const sidebarDef = {
export const menuDef = {
notifications: {
title: 'notifications',
icon: 'fas fa-bell',

View File

@ -3,16 +3,16 @@
import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
import { EventEmitter } from 'eventemitter3';
import insertTextAtCursor from 'insert-text-at-cursor';
import * as Misskey from 'misskey-js';
import * as Sentry from '@sentry/browser';
import Stream from '@client/scripts/stream';
import { apiUrl, debug } from '@client/config';
import { apiUrl, debug, url } from '@client/config';
import MkPostFormDialog from '@client/components/post-form-dialog.vue';
import MkWaitingDialog from '@client/components/waiting-dialog.vue';
import { resolve } from '@client/router';
import { $i } from '@client/account';
import { defaultStore } from '@client/store';
export const stream = markRaw(new Stream());
export const stream = markRaw(new Misskey.Stream(url, $i));
export const pendingApiRequestsCount = ref(0);
let apiRequestsCount = 0; // for debug
@ -20,7 +20,11 @@ export const apiRequests = ref([]); // for debug
export const windows = new Map();
export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) {
const apiClient = new Misskey.api.APIClient({
origin: url,
});
export const api = ((endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) => {
pendingApiRequestsCount.value++;
const onFinally = () => {
@ -56,7 +60,7 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
if (res.status === 200) {
resolve(body);
if (debug) {
log!.res = markRaw(body);
log!.res = markRaw(JSON.parse(JSON.stringify(body)));
log!.state = 'success';
}
} else if (res.status === 204) {
@ -90,17 +94,15 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
promise.then(onFinally, onFinally);
return promise;
}
}) as typeof apiClient.request;
export function apiWithDialog(
export const apiWithDialog = ((
endpoint: string,
data: Record<string, any> = {},
token?: string | null | undefined,
onSuccess?: (res: any) => void,
onFailure?: (e: Error) => void,
) {
) => {
const promise = api(endpoint, data, token);
promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => {
promiseDialog(promise, null, (e) => {
dialog({
type: 'error',
text: e.message + '\n' + (e as any).id,
@ -108,7 +110,7 @@ export function apiWithDialog(
});
return promise;
}
}) as typeof api;
export function promiseDialog<T extends Promise<any>>(
promise: T,

View File

@ -6,7 +6,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import * as os from '@client/os';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
export default defineComponent({
created() {

View File

@ -63,7 +63,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue';
import MkSelect from '@client/components/ui/select.vue';

View File

@ -90,7 +90,7 @@ export default defineComponent({
stats: null,
serverInfo: null,
connection: null,
queueConnection: os.stream.useSharedConnection('queueStats'),
queueConnection: os.stream.useChannel('queueStats'),
memUsage: 0,
chartCpuMem: null,
chartNet: null,
@ -121,7 +121,7 @@ export default defineComponent({
os.api('admin/server-info', {}).then(res => {
this.serverInfo = res;
this.connection = os.stream.useSharedConnection('serverStats');
this.connection = os.stream.useChannel('serverStats');
this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog);
this.connection.send('requestLog', {

View File

@ -92,6 +92,7 @@ export default defineComponent({
version,
url,
stats: null,
meta: null,
fetchStats: () => os.api('stats', {}),
fetchServerInfo: () => os.api('admin/server-info', {}),
fetchJobs: () => os.api('admin/queue/deliver-delayed', {}),

View File

@ -35,7 +35,7 @@ export default defineComponent({
title: this.$ts.jobQueue,
icon: 'fas fa-clipboard-list',
},
connection: os.stream.useSharedConnection('queueStats'),
connection: os.stream.useChannel('queueStats'),
}
},

View File

@ -19,6 +19,11 @@
<span>{{ $ts.bannerUrl }}</span>
</FormInput>
<FormInput v-model:value="backgroundImageUrl">
<template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.backgroundImageUrl }}</span>
</FormInput>
<FormInput v-model:value="tosUrl">
<template #prefix><i class="fas fa-link"></i></template>
<span>{{ $ts.tosUrl }}</span>
@ -88,6 +93,7 @@ export default defineComponent({
maintainerEmail: null,
iconUrl: null,
bannerUrl: null,
backgroundImageUrl: null,
maxNoteTextLength: 0,
enableLocalTimeline: false,
enableGlobalTimeline: false,
@ -106,6 +112,7 @@ export default defineComponent({
this.tosUrl = meta.tosUrl;
this.iconUrl = meta.iconUrl;
this.bannerUrl = meta.bannerUrl;
this.backgroundImageUrl = meta.backgroundImageUrl;
this.maintainerName = meta.maintainerName;
this.maintainerEmail = meta.maintainerEmail;
this.maxNoteTextLength = meta.maxNoteTextLength;
@ -120,6 +127,7 @@ export default defineComponent({
tosUrl: this.tosUrl,
iconUrl: this.iconUrl,
bannerUrl: this.bannerUrl,
backgroundImageUrl: this.backgroundImageUrl,
maintainerName: this.maintainerName,
maintainerEmail: this.maintainerEmail,
maxNoteTextLength: this.maxNoteTextLength,

View File

@ -38,7 +38,7 @@
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue';
import getAcct from '@/misc/acct/render';
import { getAcct } from '@/misc/acct';
import MkButton from '@client/components/ui/button.vue';
import { acct } from '../../filters/user';
import * as os from '@client/os';
@ -63,7 +63,7 @@ export default defineComponent({
},
mounted() {
this.connection = os.stream.useSharedConnection('messagingIndex');
this.connection = os.stream.useChannel('messagingIndex');
this.connection.on('message', this.onMessage);
this.connection.on('read', this.onRead);

View File

@ -40,7 +40,7 @@ import { computed, defineComponent } from 'vue';
import XList from '@client/components/date-separated-list.vue';
import XMessage from './messaging-room.message.vue';
import XForm from './messaging-room.form.vue';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import { isBottom, onScrollBottom, scroll } from '@client/scripts/scroll';
import * as os from '@client/os';
import { popout } from '@client/scripts/popout';
@ -141,7 +141,7 @@ const Component = defineComponent({
this.group = group;
}
this.connection = os.stream.connectToChannel('messaging', {
this.connection = os.stream.useChannel('messaging', {
otherparty: this.user ? this.user.id : undefined,
group: this.group ? this.group.id : undefined,
});

View File

@ -52,7 +52,7 @@ import MkInput from '@client/components/ui/input.vue';
import MkTextarea from '@client/components/ui/textarea.vue';
import MkSelect from '@client/components/ui/select.vue';
import MkSwitch from '@client/components/ui/switch.vue';
import getAcct from '@/misc/acct/render';
import { getAcct } from '@/misc/acct';
import * as os from '@client/os';
export default defineComponent({

View File

@ -350,6 +350,9 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
@use "sass:math";
.xqnhankfuuilcwvhgsopeqncafzsquya {
text-align: center;
@ -388,11 +391,11 @@ export default defineComponent({
font-size: 0.8em;
&:first-child {
margin-left: -($gap / 2);
margin-left: -(math.div($gap, 2));
}
&:last-child {
margin-right: -($gap / 2);
margin-right: -(math.div($gap, 2));
}
}
}
@ -413,11 +416,11 @@ export default defineComponent({
font-size: 12px;
&:first-child {
margin-top: -($gap / 2);
margin-top: -(math.div($gap, 2));
}
&:last-child {
margin-bottom: -($gap / 2);
margin-bottom: -(math.div($gap, 2));
}
}
}

View File

@ -61,7 +61,7 @@ export default defineComponent({
if (this.connection) {
this.connection.dispose();
}
this.connection = os.stream.connectToChannel('gamesReversiGame', {
this.connection = os.stream.useChannel('gamesReversiGame', {
gameId: this.game.id
});
this.connection.on('started', this.onStarted);

View File

@ -92,7 +92,7 @@ export default defineComponent({
mounted() {
if (this.$i) {
this.connection = os.stream.useSharedConnection('gamesReversi');
this.connection = os.stream.useChannel('gamesReversi');
this.connection.on('invited', this.onInvited);

View File

@ -52,7 +52,7 @@
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { Room } from '@client/scripts/room/room';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import XPreview from './preview.vue';
const storeItems = require('@client/scripts/room/furnitures.json5');
import { query as urlQuery } from '../../../prelude/url';

View File

@ -0,0 +1,72 @@
<template>
<FormBase>
<FormInfo warn>{{ $ts.customCssWarn }}</FormInfo>
<FormTextarea v-model:value="localCustomCss" manual-save tall class="_monospace" style="tab-size: 2;">
<span>{{ $ts.local }}</span>
</FormTextarea>
</FormBase>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import FormTextarea from '@client/components/form/textarea.vue';
import FormSelect from '@client/components/form/select.vue';
import FormRadios from '@client/components/form/radios.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import FormLink from '@client/components/form/link.vue';
import FormButton from '@client/components/form/button.vue';
import FormInfo from '@client/components/form/info.vue';
import * as os from '@client/os';
import { ColdDeviceStorage } from '@client/store';
import { unisonReload } from '@client/scripts/unison-reload';
import * as symbols from '@client/symbols';
import { defaultStore } from '@client/store';
export default defineComponent({
components: {
FormTextarea,
FormSelect,
FormRadios,
FormBase,
FormGroup,
FormLink,
FormButton,
FormInfo,
},
emits: ['info'],
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.customCss,
icon: 'fas fa-code'
},
localCustomCss: localStorage.getItem('customCss')
}
},
mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
this.$watch('localCustomCss', this.apply);
},
methods: {
async apply() {
localStorage.setItem('customCss', this.localCustomCss);
const { canceled } = await os.dialog({
type: 'info',
text: this.$ts.reloadToApplySetting,
showCancelButton: true
});
if (canceled) return;
unisonReload();
}
}
});
</script>

View File

@ -220,6 +220,9 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
@use "sass:math";
.uawsfosz {
> div {
padding: 24px;
@ -227,12 +230,12 @@ export default defineComponent({
> .meter {
$size: 12px;
background: rgba(0, 0, 0, 0.1);
border-radius: ($size / 2);
border-radius: math.div($size, 2);
overflow: hidden;
> div {
height: $size;
border-radius: ($size / 2);
border-radius: math.div($size, 2);
}
}
}

View File

@ -37,6 +37,7 @@
<FormSwitch v-model:value="showGapBetweenNotesInTimeline">{{ $ts.showGapBetweenNotesInTimeline }}</FormSwitch>
<FormSwitch v-model:value="loadRawImages">{{ $ts.loadRawImages }}</FormSwitch>
<FormSwitch v-model:value="disableShowingAnimatedImages">{{ $ts.disableShowingAnimatedImages }}</FormSwitch>
<FormSwitch v-model:value="squareAvatars">{{ $ts.squareAvatars }}</FormSwitch>
<FormSwitch v-model:value="useSystemFont">{{ $ts.useSystemFont }}</FormSwitch>
<FormSwitch v-model:value="useOsNativeEmojis">{{ $ts.useOsNativeEmojis }}
<div><Mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪" :key="useOsNativeEmojis"/></div>
@ -78,6 +79,8 @@
</FormSelect>
<FormLink to="/settings/deck">{{ $ts.deck }}</FormLink>
<FormLink to="/settings/custom-css"><template #icon><i class="fas fa-code"></i></template>{{ $ts.customCss }}</FormLink>
</FormBase>
</template>
@ -143,6 +146,7 @@ export default defineComponent({
instanceTicker: defaultStore.makeGetterSetter('instanceTicker'),
enableInfiniteScroll: defaultStore.makeGetterSetter('enableInfiniteScroll'),
useReactionPickerForContextMenu: defaultStore.makeGetterSetter('useReactionPickerForContextMenu'),
squareAvatars: defaultStore.makeGetterSetter('squareAvatars'),
},
watch: {
@ -174,6 +178,10 @@ export default defineComponent({
this.reloadAsk();
},
squareAvatars() {
this.reloadAsk();
},
showGapBetweenNotesInTimeline() {
this.reloadAsk();
},

View File

@ -26,7 +26,7 @@
<template #label>{{ $ts.clientSettings }}</template>
<FormLink :active="page === 'general'" replace to="/settings/general"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.general }}</FormLink>
<FormLink :active="page === 'theme'" replace to="/settings/theme"><template #icon><i class="fas fa-palette"></i></template>{{ $ts.theme }}</FormLink>
<FormLink :active="page === 'sidebar'" replace to="/settings/sidebar"><template #icon><i class="fas fa-list-ul"></i></template>{{ $ts.sidebar }}</FormLink>
<FormLink :active="page === 'menu'" replace to="/settings/menu"><template #icon><i class="fas fa-list-ul"></i></template>{{ $ts.menu }}</FormLink>
<FormLink :active="page === 'sounds'" replace to="/settings/sounds"><template #icon><i class="fas fa-music"></i></template>{{ $ts.sounds }}</FormLink>
<FormLink :active="page === 'plugin'" replace to="/settings/plugin"><template #icon><i class="fas fa-plug"></i></template>{{ $ts.plugins }}</FormLink>
</FormGroup>
@ -121,8 +121,9 @@ export default defineComponent({
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
case 'theme/install': return defineAsyncComponent(() => import('./theme.install.vue'));
case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue'));
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
case 'menu': return defineAsyncComponent(() => import('./menu.vue'));
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
case 'custom-css': return defineAsyncComponent(() => import('./custom-css.vue'));
case 'deck': return defineAsyncComponent(() => import('./deck.vue'));
case 'plugin': return defineAsyncComponent(() => import('./plugin.vue'));
case 'plugin/install': return defineAsyncComponent(() => import('./plugin.install.vue'));

View File

@ -4,8 +4,8 @@
<div class="_formLabel"><i class="fab fa-twitter"></i> Twitter</div>
<div class="_formPanel" style="padding: 16px;">
<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectSerice }}</MkButton>
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectSerice }}</MkButton>
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectService }}</MkButton>
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectService }}</MkButton>
</div>
</div>
@ -13,8 +13,8 @@
<div class="_formLabel"><i class="fab fa-discord"></i> Discord</div>
<div class="_formPanel" style="padding: 16px;">
<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectSerice }}</MkButton>
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectSerice }}</MkButton>
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectService }}</MkButton>
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectService }}</MkButton>
</div>
</div>
@ -22,8 +22,8 @@
<div class="_formLabel"><i class="fab fa-github"></i> GitHub</div>
<div class="_formPanel" style="padding: 16px;">
<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectSerice }}</MkButton>
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectSerice }}</MkButton>
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectService }}</MkButton>
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectService }}</MkButton>
</div>
</div>
</FormBase>

View File

@ -1,18 +1,18 @@
<template>
<FormBase>
<FormTextarea v-model:value="items" tall>
<span>{{ $ts.sidebar }}</span>
<FormTextarea v-model:value="items" tall manual-save>
<span>{{ $ts.menu }}</span>
<template #desc><button class="_textButton" @click="addItem">{{ $ts.addItem }}</button></template>
</FormTextarea>
<FormRadios v-model="sidebarDisplay">
<FormRadios v-model="menuDisplay">
<template #desc>{{ $ts.display }}</template>
<option value="full">{{ $ts._sidebar.full }}</option>
<option value="icon">{{ $ts._sidebar.icon }}</option>
<!-- <MkRadio v-model="sidebarDisplay" value="hide" disabled>{{ $ts._sidebar.hide }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
<option value="sideFull">{{ $ts._menuDisplay.sideFull }}</option>
<option value="sideIcon">{{ $ts._menuDisplay.sideIcon }}</option>
<option value="top">{{ $ts._menuDisplay.top }}</option>
<!-- <MkRadio v-model="menuDisplay" value="hide" disabled>{{ $ts._menuDisplay.hide }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
</FormRadios>
<FormButton @click="save()" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
<FormButton @click="reset()" danger><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton>
</FormBase>
</template>
@ -26,9 +26,10 @@ import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import FormButton from '@client/components/form/button.vue';
import * as os from '@client/os';
import { sidebarDef } from '@client/sidebar';
import { menuDef } from '@client/menu';
import { defaultStore } from '@client/store';
import * as symbols from '@client/symbols';
import { unisonReload } from '@client/scripts/unison-reload';
export default defineComponent({
components: {
@ -43,11 +44,11 @@ export default defineComponent({
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.sidebar,
title: this.$ts.menu,
icon: 'fas fa-list-ul'
},
menuDef: sidebarDef,
items: '',
menuDef: menuDef,
items: defaultStore.state.menu.join('\n'),
}
},
@ -56,11 +57,17 @@ export default defineComponent({
return this.items.trim().split('\n').filter(x => x.trim() !== '');
},
sidebarDisplay: defaultStore.makeGetterSetter('sidebarDisplay')
menuDisplay: defaultStore.makeGetterSetter('menuDisplay')
},
created() {
this.items = this.$store.state.menu.join('\n');
watch: {
menuDisplay() {
this.reloadAsk();
},
items() {
this.save();
},
},
mounted() {
@ -84,7 +91,6 @@ export default defineComponent({
});
if (canceled) return;
this.items = [...this.splited, item].join('\n');
this.save();
},
save() {
@ -95,7 +101,6 @@ export default defineComponent({
reset() {
this.$store.reset('menu');
this.items = this.$store.state.menu.join('\n');
this.reloadAsk();
},
async reloadAsk() {
@ -106,7 +111,7 @@ export default defineComponent({
});
if (canceled) return;
location.reload();
unisonReload();
}
},
});

View File

@ -71,7 +71,7 @@
<FormButton primary v-else @click="wallpaper = null">{{ $ts.removeWallpaper }}</FormButton>
<FormGroup>
<FormLink to="https://assets.msky.cafe/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink>
<FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink>
<FormLink to="/settings/theme/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._theme.install }}</FormLink>
</FormGroup>

View File

@ -234,7 +234,7 @@ import MkRemoteCaution from '@client/components/remote-caution.vue';
import MkTab from '@client/components/tab.vue';
import MkInfo from '@client/components/ui/info.vue';
import Progress from '@client/scripts/loading';
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import { getScrollPosition } from '@client/scripts/scroll';
import { getUserMenu } from '@client/scripts/get-user-menu';
import number from '../../filters/number';

View File

@ -1,10 +1,22 @@
<template>
<div class="civpbkhh">
<div v-for="note in notes" class="note">
<div class="content _panel">
{{ note.text }}
<div class="scrollbox" ref="scroll" v-bind:class="{ scroll: isScrolling }">
<div v-for="note in notes" class="note">
<div class="content _panel">
<div class="body">
<MkA class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><i class="fas fa-reply"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
<MkA class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
</div>
<div v-if="note.files.length > 0" class="richcontent">
<XMediaList :media-list="note.files"/>
</div>
<div v-if="note.poll">
<XPoll :note="note" :readOnly="true" />
</div>
</div>
<XReactionsViewer :note="note" ref="reactionsViewer"/>
</div>
<XReactionsViewer :note="note" ref="reactionsViewer"/>
</div>
</div>
</template>
@ -12,16 +24,21 @@
<script lang="ts">
import { defineComponent } from 'vue';
import XReactionsViewer from '@client/components/reactions-viewer.vue';
import XMediaList from '@client/components/media-list.vue';
import XPoll from '@client/components/poll.vue';
import * as os from '@client/os';
export default defineComponent({
components: {
XReactionsViewer
XReactionsViewer,
XMediaList,
XPoll
},
data() {
return {
notes: [],
isScrolling: false,
}
},
@ -29,22 +46,53 @@ export default defineComponent({
os.api('notes/featured').then(notes => {
this.notes = notes;
});
},
updated() {
if (this.$refs.scroll.clientHeight > window.innerHeight) {
this.isScrolling = true;
}
}
});
</script>
<style lang="scss" scoped>
@keyframes scroll {
0% {
transform: translate3d(0, 0, 0);
}
5% {
transform: translate3d(0, 0, 0);
}
75% {
transform: translate3d(0, calc(-100% + 90vh), 0);
}
90% {
transform: translate3d(0, calc(-100% + 90vh), 0);
}
}
.civpbkhh {
text-align: right;
> .note {
margin: 16px 0 16px auto;
> .scrollbox {
&.scroll {
animation: scroll 45s linear infinite;
}
> .content {
padding: 16px;
margin: 0 0 0 auto;
max-width: max-content;
border-radius: 16px;
> .note {
margin: 16px 0 16px auto;
> .content {
padding: 16px;
margin: 0 0 0 auto;
max-width: max-content;
border-radius: 16px;
> .richcontent {
min-width: 250px;
}
}
}
}
}

View File

@ -1,4 +1,4 @@
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import { host as localHost } from '@client/config';
export async function genSearchQuery(v: any, q: string) {

View File

@ -3,6 +3,11 @@ import * as url from '../../prelude/url';
export function getStaticImageUrl(baseUrl: string): string {
const u = new URL(baseUrl);
if (u.href.startsWith(`${instanceUrl}/proxy/`)) {
// もう既にproxyっぽそうだったらsearchParams付けるだけ
u.searchParams.set('static', '1');
return u.href;
}
const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので
return `${instanceUrl}/proxy/${dummy}?${url.query({
url: u.href,

View File

@ -1,7 +1,7 @@
import { i18n } from '@client/i18n';
import copyToClipboard from '@client/scripts/copy-to-clipboard';
import { host } from '@client/config';
import getAcct from '@/misc/acct/render';
import { getAcct } from '@/misc/acct';
import * as os from '@client/os';
import { userActions } from '@client/store';
import { router } from '@client/router';

View File

@ -1,4 +1,4 @@
import parseAcct from '@/misc/acct/parse';
import { parseAcct } from '@/misc/acct';
import { i18n } from '@client/i18n';
import * as os from '@client/os';

View File

@ -1,5 +1,6 @@
import * as os from '@client/os';
import { i18n } from '@client/i18n';
import { defaultStore } from '@client/store';
export function selectFile(src: any, label: string | null, multiple = false) {
return new Promise((res, rej) => {
@ -8,7 +9,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
input.type = 'file';
input.multiple = multiple;
input.onchange = () => {
const promises = Array.from(input.files).map(file => os.upload(file));
const promises = Array.from(input.files).map(file => os.upload(file, defaultStore.state.uploadFolder));
Promise.all(promises).then(driveFiles => {
res(multiple ? driveFiles : driveFiles[0]);
@ -47,7 +48,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
const marker = Math.random().toString(); // TODO: UUIDとか使う
const connection = os.stream.useSharedConnection('main');
const connection = os.stream.useChannel('main');
connection.on('urlUploadFinished', data => {
if (data.marker === marker) {
res(multiple ? [data.file] : data.file);
@ -55,8 +56,9 @@ export function selectFile(src: any, label: string | null, multiple = false) {
}
});
os.api('drive/files/upload_from_url', {
os.api('drive/files/upload-from-url', {
url: url,
folderId: defaultStore.state.uploadFolder,
marker
});

View File

@ -7,8 +7,9 @@ export class StickySidebar {
private isTop = false;
private isBottom = false;
private offsetTop: number;
private globalHeaderHeight: number = 59;
constructor(container: StickySidebar['container'], marginTop = 0) {
constructor(container: StickySidebar['container'], marginTop = 0, globalHeaderHeight = 0) {
this.container = container;
this.el = this.container.children[0] as HTMLElement;
this.el.style.position = 'sticky';
@ -16,30 +17,31 @@ export class StickySidebar {
this.container.prepend(this.spacer);
this.marginTop = marginTop;
this.offsetTop = this.container.getBoundingClientRect().top;
this.globalHeaderHeight = globalHeaderHeight;
}
public calc(scrollTop: number) {
if (scrollTop > this.lastScrollTop) { // downscroll
const overflow = Math.max(0, (this.el.clientHeight + this.marginTop) - window.innerHeight);
const overflow = Math.max(0, this.globalHeaderHeight + (this.el.clientHeight + this.marginTop) - window.innerHeight);
this.el.style.bottom = null;
this.el.style.top = `${-overflow + this.marginTop}px`;
this.el.style.top = `${-overflow + this.marginTop + this.globalHeaderHeight}px`;
this.isBottom = (scrollTop + window.innerHeight) >= (this.el.offsetTop + this.el.clientHeight);
if (this.isTop) {
this.isTop = false;
this.spacer.style.marginTop = `${Math.max(0, this.lastScrollTop + this.marginTop - this.offsetTop)}px`;
this.spacer.style.marginTop = `${Math.max(0, this.globalHeaderHeight + this.lastScrollTop + this.marginTop - this.offsetTop)}px`;
}
} else { // upscroll
const overflow = (this.el.clientHeight + this.marginTop) - window.innerHeight;
const overflow = this.globalHeaderHeight + (this.el.clientHeight + this.marginTop) - window.innerHeight;
this.el.style.top = null;
this.el.style.bottom = `${-overflow}px`;
this.isTop = scrollTop <= this.el.offsetTop;
this.isTop = scrollTop + this.marginTop + this.globalHeaderHeight <= this.el.offsetTop;
if (this.isBottom) {
this.isBottom = false;
this.spacer.style.marginTop = `${this.lastScrollTop + this.marginTop - this.offsetTop - overflow}px`;
this.spacer.style.marginTop = `${this.globalHeaderHeight + this.lastScrollTop + this.marginTop - this.offsetTop - overflow}px`;
}
}

View File

@ -1,312 +0,0 @@
import autobind from 'autobind-decorator';
import { EventEmitter } from 'eventemitter3';
import ReconnectingWebsocket from 'reconnecting-websocket';
import { markRaw } from 'vue';
import { debug, wsUrl } from '@client/config';
import { query as urlQuery } from '../../prelude/url';
/**
* Misskey stream connection
*/
export default class Stream extends EventEmitter {
private stream: ReconnectingWebsocket;
public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
private sharedConnectionPools: Pool[] = [];
private sharedConnections: SharedConnection[] = [];
private nonSharedConnections: NonSharedConnection[] = [];
@autobind
public init(user): void {
const query = urlQuery({
i: user?.token,
_t: Date.now(),
});
this.stream = new ReconnectingWebsocket(`${wsUrl}?${query}`, '', { minReconnectionDelay: 1 }); // https://github.com/pladaria/reconnecting-websocket/issues/91
this.stream.addEventListener('open', this.onOpen);
this.stream.addEventListener('close', this.onClose);
this.stream.addEventListener('message', this.onMessage);
}
@autobind
public useSharedConnection(channel: string, name?: string): SharedConnection {
let pool = this.sharedConnectionPools.find(p => p.channel === channel);
if (pool == null) {
pool = new Pool(this, channel);
this.sharedConnectionPools.push(pool);
}
const connection = markRaw(new SharedConnection(this, channel, pool, name));
this.sharedConnections.push(connection);
return connection;
}
@autobind
public removeSharedConnection(connection: SharedConnection) {
this.sharedConnections = this.sharedConnections.filter(c => c !== connection);
}
@autobind
public removeSharedConnectionPool(pool: Pool) {
this.sharedConnectionPools = this.sharedConnectionPools.filter(p => p !== pool);
}
@autobind
public connectToChannel(channel: string, params?: any): NonSharedConnection {
const connection = markRaw(new NonSharedConnection(this, channel, params));
this.nonSharedConnections.push(connection);
return connection;
}
@autobind
public disconnectToChannel(connection: NonSharedConnection) {
this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection);
}
/**
* Callback of when open connection
*/
@autobind
private onOpen() {
const isReconnect = this.state === 'reconnecting';
this.state = 'connected';
this.emit('_connected_');
// チャンネル再接続
if (isReconnect) {
for (const p of this.sharedConnectionPools)
p.connect();
for (const c of this.nonSharedConnections)
c.connect();
}
}
/**
* Callback of when close connection
*/
@autobind
private onClose() {
if (this.state === 'connected') {
this.state = 'reconnecting';
this.emit('_disconnected_');
}
}
/**
* Callback of when received a message from connection
*/
@autobind
private onMessage(message) {
const { type, body } = JSON.parse(message.data);
if (type === 'channel') {
const id = body.id;
let connections: Connection[];
connections = this.sharedConnections.filter(c => c.id === id);
if (connections.length === 0) {
connections = [this.nonSharedConnections.find(c => c.id === id)];
}
for (const c of connections.filter(c => c != null)) {
c.emit(body.type, Object.freeze(body.body));
if (debug) c.inCount++;
}
} else {
this.emit(type, Object.freeze(body));
}
}
/**
* Send a message to connection
*/
@autobind
public send(typeOrPayload, payload?) {
const data = payload === undefined ? typeOrPayload : {
type: typeOrPayload,
body: payload
};
this.stream.send(JSON.stringify(data));
}
/**
* Close this connection
*/
@autobind
public close() {
this.stream.removeEventListener('open', this.onOpen);
this.stream.removeEventListener('message', this.onMessage);
}
}
let idCounter = 0;
class Pool {
public channel: string;
public id: string;
protected stream: Stream;
public users = 0;
private disposeTimerId: any;
private isConnected = false;
constructor(stream: Stream, channel: string) {
this.channel = channel;
this.stream = stream;
this.id = (++idCounter).toString();
this.stream.on('_disconnected_', this.onStreamDisconnected);
}
@autobind
private onStreamDisconnected() {
this.isConnected = false;
}
@autobind
public inc() {
if (this.users === 0 && !this.isConnected) {
this.connect();
}
this.users++;
// タイマー解除
if (this.disposeTimerId) {
clearTimeout(this.disposeTimerId);
this.disposeTimerId = null;
}
}
@autobind
public dec() {
this.users--;
// そのコネクションの利用者が誰もいなくなったら
if (this.users === 0) {
// また直ぐに再利用される可能性があるので、一定時間待ち、
// 新たな利用者が現れなければコネクションを切断する
this.disposeTimerId = setTimeout(() => {
this.disconnect();
}, 3000);
}
}
@autobind
public connect() {
if (this.isConnected) return;
this.isConnected = true;
this.stream.send('connect', {
channel: this.channel,
id: this.id
});
}
@autobind
private disconnect() {
this.stream.off('_disconnected_', this.onStreamDisconnected);
this.stream.send('disconnect', { id: this.id });
this.stream.removeSharedConnectionPool(this);
}
}
abstract class Connection extends EventEmitter {
public channel: string;
protected stream: Stream;
public abstract id: string;
public name?: string; // for debug
public inCount: number = 0; // for debug
public outCount: number = 0; // for debug
constructor(stream: Stream, channel: string, name?: string) {
super();
this.stream = stream;
this.channel = channel;
this.name = name;
}
@autobind
public send(id: string, typeOrPayload, payload?) {
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
const body = payload === undefined ? typeOrPayload.body : payload;
this.stream.send('ch', {
id: id,
type: type,
body: body
});
if (debug) this.outCount++;
}
public abstract dispose(): void;
}
class SharedConnection extends Connection {
private pool: Pool;
public get id(): string {
return this.pool.id;
}
constructor(stream: Stream, channel: string, pool: Pool, name?: string) {
super(stream, channel, name);
this.pool = pool;
this.pool.inc();
}
@autobind
public send(typeOrPayload, payload?) {
super.send(this.pool.id, typeOrPayload, payload);
}
@autobind
public dispose() {
this.pool.dec();
this.removeAllListeners();
this.stream.removeSharedConnection(this);
}
}
class NonSharedConnection extends Connection {
public id: string;
protected params: any;
constructor(stream: Stream, channel: string, params?: any) {
super(stream, channel);
this.params = params;
this.id = (++idCounter).toString();
this.connect();
}
@autobind
public connect() {
this.stream.send('connect', {
channel: this.channel,
id: this.id,
params: this.params
});
}
@autobind
public send(typeOrPayload, payload?) {
super.send(this.id, typeOrPayload, payload);
}
@autobind
public dispose() {
this.removeAllListeners();
this.stream.send('disconnect', { id: this.id });
this.stream.disconnectToChannel(this);
}
}

Some files were not shown because too many files have changed in this diff Show More