Compare commits

..

192 Commits

Author SHA1 Message Date
d44dc7e00d 8.32.0 2018-09-08 15:30:07 +09:00
82ee3a538b Improve welcome page 2018-09-08 15:28:38 +09:00
380cf0de69 Improve welcome page 2018-09-08 15:11:12 +09:00
11f25ea2e7 8.31.0 2018-09-08 06:44:34 +09:00
ef62497777 ActivityPub Outboxの修正とactivity idのURLを実装 (#2662)
* Fix Outbox structure

* Implement activity endpoint

* Use in instead of or

* Use in, addition
2018-09-08 05:24:55 +09:00
2824d8a5b6 Add animation 2018-09-08 04:54:11 +09:00
1c84c0828e 良い感じに 2018-09-08 01:46:01 +09:00
39e4494836 🎨 2018-09-08 01:31:50 +09:00
e7180d529a 8.30.0 2018-09-07 21:14:27 +09:00
b8cd872738 Merge pull request #2659 from syuilo/greenkeeper/commander-2.18.0
Update commander to the latest version 🚀
2018-09-07 21:14:02 +09:00
efaaa76185 Improve note visibility settings
Closes #2312
Closes #2313
2018-09-07 21:13:15 +09:00
19e1f996a6 Fix bug 2018-09-07 21:10:31 +09:00
40a69bf200 Merge pull request #2654 from syuilo/l10n_develop
New Crowdin translations
2018-09-07 20:41:54 +09:00
9e3abb9989 Improve welcome page 2018-09-07 20:41:12 +09:00
5ba48e06f7 New translations ja-JP.yml (English) 2018-09-07 20:31:22 +09:00
8b3a0a524b Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-09-07 20:24:00 +09:00
d9fe9cc5df 返すタグの数を制限 2018-09-07 20:23:46 +09:00
b202c7906a New translations ja-JP.yml (Norwegian) 2018-09-07 20:23:33 +09:00
b9c868cac6 New translations ja-JP.yml (Dutch) 2018-09-07 20:23:30 +09:00
33adf3c88d New translations ja-JP.yml (Japanese, Kansai) 2018-09-07 20:23:28 +09:00
8b84f40975 New translations ja-JP.yml (Spanish) 2018-09-07 20:23:25 +09:00
fa131d2023 New translations ja-JP.yml (Russian) 2018-09-07 20:23:23 +09:00
a83b38b50a New translations ja-JP.yml (Portuguese) 2018-09-07 20:23:20 +09:00
dcd7b286ef New translations ja-JP.yml (Polish) 2018-09-07 20:23:18 +09:00
b85bf769cd New translations ja-JP.yml (Korean) 2018-09-07 20:23:15 +09:00
630a20d61e New translations ja-JP.yml (Italian) 2018-09-07 20:23:12 +09:00
88c3794cf1 New translations ja-JP.yml (German) 2018-09-07 20:23:10 +09:00
42eb457ad0 New translations ja-JP.yml (French) 2018-09-07 20:23:08 +09:00
d153a8de20 New translations ja-JP.yml (English) 2018-09-07 20:23:06 +09:00
7f7551f44c New translations ja-JP.yml (Chinese Simplified) 2018-09-07 20:23:03 +09:00
23082b55a4 New translations ja-JP.yml (Catalan) 2018-09-07 20:23:00 +09:00
dac7387a7f fix(package): update minio to version 7.0.1 (#2655) 2018-09-07 20:22:04 +09:00
8c6856d894 Improve welcome page 2018-09-07 20:21:25 +09:00
2c0e514fb2 fix(package): update commander to version 2.18.0 2018-09-07 10:32:06 +00:00
1917b0339e #2652 (#2658) 2018-09-07 19:24:18 +09:00
c05419f223 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-09-07 19:23:51 +09:00
e0deaec695 Implement new endpoint 2018-09-07 19:23:39 +09:00
d70e2a788e Add some meta alternate links (#2657) 2018-09-07 19:22:14 +09:00
7343e6e2e8 統計で無視するハッシュタグを設定できるように 2018-09-07 19:20:50 +09:00
106d4cc0d6 🎨 2018-09-07 06:04:00 +09:00
c98879cb7a New translations ja-JP.yml (Norwegian) 2018-09-07 05:52:06 +09:00
9ca755c313 New translations ja-JP.yml (Dutch) 2018-09-07 05:52:04 +09:00
25e0b98840 New translations ja-JP.yml (Japanese, Kansai) 2018-09-07 05:52:01 +09:00
5599c43c71 New translations ja-JP.yml (Spanish) 2018-09-07 05:51:59 +09:00
eb7597d7e4 New translations ja-JP.yml (Russian) 2018-09-07 05:51:56 +09:00
d5767e92c4 New translations ja-JP.yml (Portuguese) 2018-09-07 05:51:54 +09:00
ba3749d373 New translations ja-JP.yml (Polish) 2018-09-07 05:51:51 +09:00
d8088acdf2 New translations ja-JP.yml (Korean) 2018-09-07 05:51:49 +09:00
ad93e0aa3d New translations ja-JP.yml (Italian) 2018-09-07 05:51:46 +09:00
691e58f03d New translations ja-JP.yml (German) 2018-09-07 05:51:44 +09:00
95d5bccfca New translations ja-JP.yml (French) 2018-09-07 05:51:42 +09:00
2aa8e0a4bf New translations ja-JP.yml (English) 2018-09-07 05:51:39 +09:00
6e96d6677d New translations ja-JP.yml (Chinese Simplified) 2018-09-07 05:51:36 +09:00
8816c20f51 New translations ja-JP.yml (Catalan) 2018-09-07 05:51:34 +09:00
e955fe1ffd 8.29.0 2018-09-07 05:47:47 +09:00
5cbcac713a Fix 2018-09-07 05:47:19 +09:00
2b50364ab4 ユーザー名にコントラストを付けるデザインのオンオフを切り替えられるように 2018-09-07 05:45:13 +09:00
fa04ac789e 🎨 2018-09-07 05:37:15 +09:00
95ce8dce3d 8.28.1 2018-09-07 05:32:18 +09:00
0b5eec4ca8 Fix bug 2018-09-07 05:32:09 +09:00
6d9716f90e 8.28.0 2018-09-07 04:24:08 +09:00
aa31061d90 fix(package): update node-sass-json-importer to version 4.0.1 (#2645) 2018-09-07 04:23:26 +09:00
acc7797dff New Crowdin translations (#2615)
* New translations ja-JP.yml (Catalan)

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

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

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Catalan)

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

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

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (English)
2018-09-07 04:22:16 +09:00
7959196dc7 Add sum function (#2653) 2018-09-07 04:21:04 +09:00
c6ff6939a5 Add capitalize function (#2651) 2018-09-07 03:22:55 +09:00
769960f29e Encode fetch URI if needed (#2649) 2018-09-07 02:26:31 +09:00
d92e9759f3 Refactor analog clock widget (#2648) 2018-09-07 01:20:23 +09:00
bf7e19b288 🎨 2018-09-07 01:18:47 +09:00
98954cd6d4 Trim image 2018-09-07 01:02:31 +09:00
538bb978ed Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-09-07 00:52:21 +09:00
10232c5866 Fix bug & some refactor 2018-09-07 00:52:13 +09:00
5cd6a0db16 Fix typo: serive -> service (#2647) 2018-09-07 00:44:57 +09:00
ff0a05a2d6 Add unique function (#2644) 2018-09-07 00:10:03 +09:00
e34b264af2 Fix bug (#2643) 2018-09-07 00:03:44 +09:00
00d79487cd Add erase function (#2641) 2018-09-07 00:02:55 +09:00
3cace734c7 Add concat function (#2640) 2018-09-06 21:31:15 +09:00
f428372869 Refactor effects function (#2639) 2018-09-06 20:06:16 +09:00
5dd2feba9b fix(package): update @types/minio to version 7.0.0 (#2626) 2018-09-06 19:55:29 +09:00
a1b026239e fix(package): update @types/ws to version 6.0.1 (#2636) 2018-09-06 19:55:20 +09:00
40735ce76b Fix bug (#2638) 2018-09-06 19:28:52 +09:00
4a00c13b33 🎨 2018-09-06 16:03:00 +09:00
8e359d54bd if elimination (#2635) 2018-09-06 06:06:22 +09:00
fb76dff836 New translations ja-JP.yml (English) 2018-09-06 05:01:19 +09:00
2448bf4e4e 8.27.0 2018-09-06 04:57:21 +09:00
91e0fc8c62 Improve welcome page 2018-09-06 04:52:42 +09:00
b4f86feddb 🎨 2018-09-06 04:38:07 +09:00
7167c8c593 New translations ja-JP.yml (Norwegian) 2018-09-06 04:36:02 +09:00
51b79d4250 New translations ja-JP.yml (Dutch) 2018-09-06 04:36:00 +09:00
925fcc1c64 New translations ja-JP.yml (Japanese, Kansai) 2018-09-06 04:35:54 +09:00
fcdc14862c New translations ja-JP.yml (Spanish) 2018-09-06 04:35:50 +09:00
dac2844cae New translations ja-JP.yml (Russian) 2018-09-06 04:35:45 +09:00
706b0cea16 New translations ja-JP.yml (Portuguese) 2018-09-06 04:35:41 +09:00
842e7844c7 New translations ja-JP.yml (Polish) 2018-09-06 04:35:39 +09:00
1dceda50d8 New translations ja-JP.yml (Korean) 2018-09-06 04:35:33 +09:00
af8b9abba4 New translations ja-JP.yml (Italian) 2018-09-06 04:35:28 +09:00
07b07685fa New translations ja-JP.yml (German) 2018-09-06 04:35:26 +09:00
cde43fe3c8 New translations ja-JP.yml (French) 2018-09-06 04:35:24 +09:00
2fe84aa75b New translations ja-JP.yml (English) 2018-09-06 04:35:21 +09:00
7d79a4840d New translations ja-JP.yml (Chinese Simplified) 2018-09-06 04:35:19 +09:00
3ee9479572 New translations ja-JP.yml (Catalan) 2018-09-06 04:35:16 +09:00
ccf8e44acc Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-09-06 04:28:42 +09:00
451acb77df Improve welcome page 2018-09-06 04:28:39 +09:00
e2c6227f47 Improve local timeline API 2018-09-06 04:28:22 +09:00
ebd1c877ad Show host in local user detail (#2634) 2018-09-06 03:21:11 +09:00
498094b3c7 Refactor reversi engine (#2633)
* Refactor reversi engine

* Add puttablePlaces
2018-09-06 03:02:52 +09:00
1cc183ecdb Resolve #2631 (#2632) 2018-09-06 02:44:01 +09:00
e8948452fd Resolve #2629 (#2630) 2018-09-06 02:28:04 +09:00
ade7e62836 Add README.md for prelude (#2628) 2018-09-06 02:24:39 +09:00
395cfa6108 Resolve #2625 (#2627) 2018-09-06 02:16:08 +09:00
b5ff2abdb9 互換性のためのコードを追加 & #2623 2018-09-05 23:55:51 +09:00
229e85b2c5 [WIP] Update welcome page 2018-09-05 21:51:31 +09:00
37058e3480 Fix parameter name 2018-09-05 19:35:57 +09:00
a1b82e9723 #2620 2018-09-05 19:32:46 +09:00
db943df0c8 🎨 2018-09-05 18:09:31 +09:00
ff8d300ea8 モバイル版のメニューにお知らせを表示するように 2018-09-05 17:43:31 +09:00
8b490b9b94 #2607 2018-09-05 16:48:59 +09:00
f83f8631ac fix(package): update systeminformation to version 3.45.1 (#2616) 2018-09-05 13:56:59 +09:00
16da91d8d1 New translations ja-JP.yml (Norwegian) 2018-09-05 13:51:56 +09:00
8ffd62b462 New translations ja-JP.yml (Dutch) 2018-09-05 13:51:54 +09:00
935367e167 New translations ja-JP.yml (Japanese, Kansai) 2018-09-05 13:51:50 +09:00
00618260f2 New translations ja-JP.yml (Spanish) 2018-09-05 13:51:46 +09:00
77d66fac7b New translations ja-JP.yml (Russian) 2018-09-05 13:51:40 +09:00
17d7f59b06 New translations ja-JP.yml (Portuguese) 2018-09-05 13:51:38 +09:00
2561547db1 New translations ja-JP.yml (Polish) 2018-09-05 13:51:36 +09:00
7738438616 New translations ja-JP.yml (Korean) 2018-09-05 13:51:34 +09:00
3d8fc4a794 New translations ja-JP.yml (Italian) 2018-09-05 13:51:28 +09:00
87b4e7905e New translations ja-JP.yml (German) 2018-09-05 13:51:25 +09:00
13c5d4985a New translations ja-JP.yml (French) 2018-09-05 13:51:23 +09:00
f0df4096fd New translations ja-JP.yml (English) 2018-09-05 13:51:21 +09:00
5044424549 New translations ja-JP.yml (Chinese Simplified) 2018-09-05 13:51:19 +09:00
8ce67cdcd6 New translations ja-JP.yml (Catalan) 2018-09-05 13:51:16 +09:00
1915ccabdd 8.26.0 2018-09-05 13:49:08 +09:00
6fea2f52f1 nanka iroiro 2018-09-05 13:47:26 +09:00
f77eaaa08a Improve usability 2018-09-05 13:06:49 +09:00
7c5bc03492 Update langs 2018-09-05 12:53:08 +09:00
72a1af6cd4 Merge pull request #2548 from syuilo/l10n_develop
New Crowdin translations
2018-09-05 12:50:11 +09:00
4bce6f14f3 fix(package): update node-sass-json-importer to version 4.0.0 (#2614) 2018-09-05 12:48:00 +09:00
a38ce86f87 fix(package): update systeminformation to version 3.45.0 (#2609) 2018-09-05 12:47:30 +09:00
f539491502 fix(package): update vue-js-modal to version 1.3.26 (#2613) 2018-09-05 12:47:13 +09:00
d279f8e9ff 🎨 2018-09-04 19:19:51 +09:00
eaec936fa6 Fix remote follow (#2606) 2018-09-04 18:33:16 +09:00
a0735b0e7a fix(package): update webpack to version 4.17.2 (#2599) 2018-09-04 18:15:58 +09:00
5b039a1bee Add User-Agent header (#2602) 2018-09-04 17:44:21 +09:00
60fa8e13d6 New translations ja-JP.yml (English) 2018-09-04 02:21:29 +09:00
ecbaea463b New translations ja-JP.yml (Norwegian) 2018-09-04 02:12:04 +09:00
814ddeb436 New translations ja-JP.yml (Dutch) 2018-09-04 02:12:01 +09:00
d6466106e8 New translations ja-JP.yml (Japanese, Kansai) 2018-09-04 02:11:59 +09:00
633f5384f9 New translations ja-JP.yml (Spanish) 2018-09-04 02:11:56 +09:00
fa7989772c New translations ja-JP.yml (Russian) 2018-09-04 02:11:53 +09:00
0e395612a6 New translations ja-JP.yml (Portuguese) 2018-09-04 02:11:50 +09:00
fb3f52f3ad New translations ja-JP.yml (Polish) 2018-09-04 02:11:48 +09:00
ba11c71d65 New translations ja-JP.yml (Korean) 2018-09-04 02:11:46 +09:00
bdc3081167 New translations ja-JP.yml (Italian) 2018-09-04 02:11:43 +09:00
430efcf1b9 New translations ja-JP.yml (German) 2018-09-04 02:11:41 +09:00
996450dd7c New translations ja-JP.yml (French) 2018-09-04 02:11:38 +09:00
fa779f0417 New translations ja-JP.yml (English) 2018-09-04 02:11:35 +09:00
25cec6d28a New translations ja-JP.yml (Chinese Simplified) 2018-09-04 02:11:33 +09:00
c5f8403cea New translations ja-JP.yml (Catalan) 2018-09-04 02:11:30 +09:00
881df20f1b New translations ja-JP.yml (Spanish) 2018-09-03 23:32:05 +09:00
7d269c0441 New translations ja-JP.yml (Spanish) 2018-09-03 23:26:23 +09:00
639b483e6c New translations ja-JP.yml (Spanish) 2018-09-03 23:22:57 +09:00
e894ed5a8b New translations ja-JP.yml (Dutch) 2018-09-03 14:30:56 +09:00
d7808299fd New translations ja-JP.yml (Norwegian) 2018-09-03 14:20:56 +09:00
f92e0c16d2 New translations ja-JP.yml (Dutch) 2018-09-03 14:20:53 +09:00
a951c337b8 New translations ja-JP.yml (English) 2018-09-01 14:30:49 +09:00
db3efb3791 New translations ja-JP.yml (English) 2018-09-01 14:20:51 +09:00
5f9a9867eb New translations ja-JP.yml (Japanese, Kansai) 2018-09-01 09:51:26 +09:00
059a8e07d2 New translations ja-JP.yml (Spanish) 2018-09-01 09:51:24 +09:00
cf82f56e66 New translations ja-JP.yml (Russian) 2018-09-01 09:51:20 +09:00
2778bd14d4 New translations ja-JP.yml (Portuguese) 2018-09-01 09:51:16 +09:00
5b0446739c New translations ja-JP.yml (Polish) 2018-09-01 09:51:14 +09:00
55f235d0ac New translations ja-JP.yml (Korean) 2018-09-01 09:51:11 +09:00
4ec44c68e9 New translations ja-JP.yml (Italian) 2018-09-01 09:51:09 +09:00
e6952d499a New translations ja-JP.yml (German) 2018-09-01 09:51:06 +09:00
e0b82f827b New translations ja-JP.yml (French) 2018-09-01 09:51:03 +09:00
0bccb17e82 New translations ja-JP.yml (English) 2018-09-01 09:51:00 +09:00
b251b8c6a9 New translations ja-JP.yml (Chinese Simplified) 2018-09-01 09:50:58 +09:00
c2a62f632b New translations ja-JP.yml (Catalan) 2018-09-01 09:50:56 +09:00
37b5afa1a3 New translations ja-JP.yml (English) 2018-09-01 04:52:25 +09:00
b80d0a3b12 New translations ja-JP.yml (English) 2018-08-31 16:11:19 +09:00
9f60688d37 New translations ja-JP.yml (Japanese, Kansai) 2018-08-30 22:15:42 +09:00
ca0ea9e57c New translations ja-JP.yml (Spanish) 2018-08-30 22:15:39 +09:00
a77a7e8112 New translations ja-JP.yml (Russian) 2018-08-30 22:15:35 +09:00
b26ea2edc0 New translations ja-JP.yml (Portuguese) 2018-08-30 22:15:31 +09:00
02b99dfd76 New translations ja-JP.yml (Polish) 2018-08-30 22:15:28 +09:00
af02b0f115 New translations ja-JP.yml (Korean) 2018-08-30 22:15:25 +09:00
9b3c379678 New translations ja-JP.yml (Italian) 2018-08-30 22:15:21 +09:00
a423fd7695 New translations ja-JP.yml (German) 2018-08-30 22:15:18 +09:00
de6e1d8c9b New translations ja-JP.yml (French) 2018-08-30 22:15:15 +09:00
d9db3e8629 New translations ja-JP.yml (English) 2018-08-30 22:15:13 +09:00
ac1c81b7d6 New translations ja-JP.yml (Chinese Simplified) 2018-08-30 22:15:10 +09:00
49b2eec534 New translations ja-JP.yml (Catalan) 2018-08-30 22:15:07 +09:00
130 changed files with 4703 additions and 1063 deletions

BIN
assets/about/drive.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
assets/about/post.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

BIN
assets/about/reaction.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
assets/about/ui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
my-turn: "あなたのターンです" my-turn: "あなたのターンです"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
my-turn: "あなたのターンです" my-turn: "あなたのターンです"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "Entwickler" develop: "Entwickler"
feedback: "Feedback" feedback: "Feedback"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "Diese Anmerkung favorisieren" favorite: "Diese Anmerkung favorisieren"
pin: "An die Profilseite pinnen" pin: "An die Profilseite pinnen"
delete: "Löschen" delete: "Löschen"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "Direkt" specified: "Direkt"
specified-desc: "Poste nur für bestimmte Benutzer" specified-desc: "Poste nur für bestimmte Benutzer"
private: "Privat" private: "Privat"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Laden" fetching: "Laden"
no-broadcasts: "Keine Broadcasts" no-broadcasts: "Keine Broadcasts"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "Serverinformationen" title: "Serverinformationen"
toggle: "Sicht umschalten" toggle: "Sicht umschalten"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "Nacht Modus" dark-mode: "Nacht Modus"
circle-icons: "Kreisförmige Icons" circle-icons: "Kreisförmige Icons"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "Übergang in Fensterköpfen" gradient-window-header: "Übergang in Fensterköpfen"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -84,9 +84,10 @@ common:
my-token-regenerated: "Your token has been regenerated, so you will be signed out." my-token-regenerated: "Your token has been regenerated, so you will be signed out."
i-like-sushi: "I prefer sushi rather than pudding" i-like-sushi: "I prefer sushi rather than pudding"
show-reversi-board-labels: "Show row and column labels in Reversi" show-reversi-board-labels: "Show row and column labels in Reversi"
use-contrast-reversi-stones: "Make the stone color clear" use-contrast-reversi-stones: "Make the stone color clear in reversi"
verified-user: "Verified account" verified-user: "Verified account"
disable-animated-mfm: "Disable animated texts in a post" disable-animated-mfm: "Disable animated texts in a post"
do-not-use-in-production: 'As this is for development, do not use this in production.'
reversi: reversi:
drawn: "Draw" drawn: "Draw"
my-turn: "Your turn" my-turn: "Your turn"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "Developers" develop: "Developers"
feedback: "Feedback" feedback: "Feedback"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "Details"
copy-link: "Copy link"
favorite: "Favorite this note" favorite: "Favorite this note"
pin: "Pin to your profile" pin: "Pin to your profile"
delete: "Delete" delete: "Delete"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "Direct" specified: "Direct"
specified-desc: "Post to specified users only" specified-desc: "Post to specified users only"
private: "Private" private: "Private"
common/views/components/trends.vue:
count: "{} users mentioned"
empty: "No popular hashtag trends"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Fetching" fetching: "Fetching"
no-broadcasts: "No announcements" no-broadcasts: "No announcements"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "Toggle views" toggle: "Toggle views"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "Hashtags" title: "Hashtags"
count: "{} users mentioned"
empty: "No popular hashtag trends"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "Server info" title: "Server info"
toggle: "Toggle views" toggle: "Toggle views"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "Remove background" delete-wallpaper: "Remove background"
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
contrasted-acct: "Add contrast to username"
gradient-window-header: "Use gradients on window headers" gradient-window-header: "Use gradients on window headers"
post-form-on-timeline: "Display post form at the top of the timeline" post-form-on-timeline: "Display post form at the top of the timeline"
suggest-recent-hashtags: "Show recent popular hashtags on the post form" suggest-recent-hashtags: "Show recent popular hashtags on the post form"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "Logging in..." signin-button: "Logging in..."
signup-button: "Sign up" signup-button: "Sign up"
timeline: "Timeline" timeline: "Timeline"
announcements: "Announcements"
photos: "Recent uploaded"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "Information"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey storage" title: "Misskey storage"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
i-am-under-limited-internet: "I'm in limited bandwidth" i-am-under-limited-internet: "I'm in limited bandwidth"
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
contrasted-acct: "Add contrast to username"
timeline: "Timeline" timeline: "Timeline"
show-reply-target: "Show reply target" show-reply-target: "Show reply target"
show-my-renotes: "Show my reposts" show-my-renotes: "Show my reposts"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "Post design" post-style: "Post design"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Smart" post-style-smart: "Smart"
notification-position: "Notification style"
notification-position-bottom: "Bottom"
notification-position-top: "Top"
behavior: "Behavior" behavior: "Behavior"
fetch-on-scroll: "Endless loading on scroll" fetch-on-scroll: "Endless loading on scroll"
disable-via-mobile: "Don't mark the post as 'from mobile'" disable-via-mobile: "Don't mark the post as 'from mobile'"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "Settings" settings: "Settings"
signout: "Sign out" signout: "Sign out"
sound: "Sounds" sound: "Sounds"
enableSounds: "Enable sounds" enable-sounds: "Enable sounds"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "Follows you" follows-you: "Follows you"
following: "Following" following: "Following"

View File

@ -11,7 +11,7 @@ common:
warning: "<strong>Misskey no tiene anuncios publicitarios.</strong> Sin embargo, algunas características podrían no estar disponibles si el bloqueador de publicidad está habilitado." warning: "<strong>Misskey no tiene anuncios publicitarios.</strong> Sin embargo, algunas características podrían no estar disponibles si el bloqueador de publicidad está habilitado."
application-authorization: "Autorizaciones de la aplicación." application-authorization: "Autorizaciones de la aplicación."
close: "Cerrar" close: "Cerrar"
do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。" do-not-copy-paste: "Por favor no copies código aquí. Tu cuenta puede resultar comprometida."
got-it: "¡Listo!" got-it: "¡Listo!"
customization-tips: customization-tips:
title: "Consejos de personalización" title: "Consejos de personalización"
@ -58,7 +58,7 @@ common:
friday: "Viernes" friday: "Viernes"
saturday: "Sábado" saturday: "Sábado"
reactions: reactions:
like: "いいね" like: "Me gusta"
love: "amor" love: "amor"
laugh: "risa" laugh: "risa"
hmm: "hmm" hmm: "hmm"
@ -84,9 +84,10 @@ common:
my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado." my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado."
i-like-sushi: "Prefiero sushi a pudín" i-like-sushi: "Prefiero sushi a pudín"
show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi" show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "Hacer el color de la piedra claro en Reversi"
verified-user: "公式アカウント" verified-user: "Cuenta verificada"
disable-animated-mfm: "Desactivar texto animado en una publicación" disable-animated-mfm: "Desactivar texto animado en una publicación"
do-not-use-in-production: 'Esto está en desarrollo, no usarlo para producción.'
reversi: reversi:
drawn: "Empatado" drawn: "Empatado"
my-turn: "Mi turno" my-turn: "Mi turno"
@ -170,9 +171,9 @@ common/views/components/games/reversi/reversi.vue:
common/views/components/games/reversi/reversi.game.vue: common/views/components/games/reversi/reversi.game.vue:
surrender: "Rendirse" surrender: "Rendirse"
surrendered: "Por rendirse" surrendered: "Por rendirse"
is-llotheo: "石の少ない方が勝ち(ロセオ)" is-llotheo: "El último gana (Llotheo)"
looped-map: "ループマップ" looped-map: "Mapa en bucle"
can-put-everywhere: "どこでも置けるモード" can-put-everywhere: "Puedes colocar donde quieras"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi" title: "Misskey Reversi"
sub-title: "¡Juega Reversi con tus amigos!" sub-title: "¡Juega Reversi con tus amigos!"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "Desarrolladores" develop: "Desarrolladores"
feedback: "Opiniones" feedback: "Opiniones"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "Detalles"
copy-link: "Copiar enlace"
favorite: "Me gusta esta nota" favorite: "Me gusta esta nota"
pin: "Fijar en el perfil" pin: "Fijar en el perfil"
delete: "Borrar" delete: "Borrar"
@ -288,10 +291,10 @@ common/views/components/signin.vue:
signin: "Entra" signin: "Entra"
or: "O" or: "O"
signin-with-twitter: "Ingresar con Twitter" signin-with-twitter: "Ingresar con Twitter"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。" login-failed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos."
common/views/components/signup.vue: common/views/components/signup.vue:
invitation-code: "招待コード" invitation-code: "Código de invitación"
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。" invitation-info: "Si no tienes un código de invitación, por favor contacta un <a href=\"{}\">administrador</a>."
username: "Usuario" username: "Usuario"
checking: "Comprobando..." checking: "Comprobando..."
available: "Disponible" available: "Disponible"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "Directo" specified: "Directo"
specified-desc: "Publica solo para los seguidores que quieras" specified-desc: "Publica solo para los seguidores que quieras"
private: "Privada" private: "Privada"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Recuperando" fetching: "Recuperando"
no-broadcasts: "Sin emisión" no-broadcasts: "Sin emisión"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "Alternar vistas" toggle: "Alternar vistas"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "Etiquetas" title: "Etiquetas"
count: "{} usuarios mencionados"
empty: "Ninguna tendencia popular ahora"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "Información del servidor" title: "Información del servidor"
toggle: "Alternar vistas" toggle: "Alternar vistas"
@ -411,7 +415,7 @@ desktop:
uploading-avatar: "Cargando un nuevo avatar" uploading-avatar: "Cargando un nuevo avatar"
avatar-updated: "Avatar actualizado" avatar-updated: "Avatar actualizado"
choose-avatar: "Escoge una imagen de avatar" choose-avatar: "Escoge una imagen de avatar"
invalid-filetype: "この形式のファイルはサポートされていません" invalid-filetype: "Este tipo de archivo no es compatible aquí"
desktop/views/components/activity.chart.vue: desktop/views/components/activity.chart.vue:
total: "Negro ... Total" total: "Negro ... Total"
notes: "Azul ... Notas" notes: "Azul ... Notas"
@ -426,23 +430,23 @@ desktop/views/components/calendar.vue:
next: "Próximo mes" next: "Próximo mes"
go: "Click para navegar" go: "Click para navegar"
desktop/views/components/charts.vue: desktop/views/components/charts.vue:
title: "チャート" title: "Gráficos"
per-day: "1日ごと" per-day: "por día"
per-hour: "1時間ごと" per-hour: "por hora"
notes: "投稿" notes: "Publicaciones"
users: "ユーザー" users: "Usuarios"
drive: "ドライブ" drive: "Unidad"
charts: charts:
notes: "投稿の増減 (統合)" notes: "Número de publicaciones: aumentar/disminuir (Combinado)"
local-notes: "投稿の増減 (ローカル)" local-notes: "Número de publicaciones: aumentar/disminuir (Local)"
remote-notes: "投稿の増減 (リモート)" remote-notes: "Número de publicaciones: aumentar/disminuir (Remoto)"
notes-total: "投稿の累計" notes-total: "Número de publicaciones: Acumulativo total"
users: "ユーザーの増減" users: "Número de usuarios: aumentar/disminuir"
users-total: "ユーザーの累計" users-total: "Número de usuarios: Acumulativo total"
drive: "ドライブ使用量の増減" drive: "Capacidad de almacenamiento usada: aumentar/disminuir"
drive-total: "ドライブ使用量の累計" drive-total: "Capacidad de almacenamiento usada: Acumulativa total"
drive-files: "ドライブのファイル数の増減" drive-files: "Número de archivos almacenados: aumentar/disminuir"
drive-files-total: "ドライブのファイル数の累計" drive-files-total: "Número de archivos almacenados: Acumulativo total"
desktop/views/components/choose-file-from-drive-window.vue: desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Escoger archivos" choose-file: "Escoger archivos"
upload: "Cargar archivos de tu dispositivo" upload: "Cargar archivos de tu dispositivo"
@ -463,7 +467,7 @@ desktop/views/components/drive-window.vue:
desktop/views/components/drive.file.vue: desktop/views/components/drive.file.vue:
avatar: "Avatar" avatar: "Avatar"
banner: "Banner" banner: "Banner"
nsfw: "閲覧注意" nsfw: "Ver más"
contextmenu: contextmenu:
rename: "Renombrar" rename: "Renombrar"
mark-as-sensitive: "Marcar como 'sensible'" mark-as-sensitive: "Marcar como 'sensible'"
@ -515,31 +519,31 @@ desktop/views/components/media-image.vue:
sensitive: "El contenido es NSFW (no seguro para ver en el trabajo, 'not safe for work')" sensitive: "El contenido es NSFW (no seguro para ver en el trabajo, 'not safe for work')"
click-to-show: "Click para mostrar" click-to-show: "Click para mostrar"
desktop/views/components/media-video.vue: desktop/views/components/media-video.vue:
sensitive: "閲覧注意" sensitive: "Este contenido no es apropiado para ver en el trabajo"
click-to-show: "クリックして表示" click-to-show: "Click para mostrar"
desktop/views/components/follow-button.vue: desktop/views/components/follow-button.vue:
following: "Siguiendo" following: "Siguiendo"
follow: "Sigue" follow: "Sigue"
request-pending: "Pendiente de aprobación" request-pending: "Pendiente de aprobación"
follow-request: "フォロー申請" follow-request: "Solicitud de seguir"
desktop/views/components/followers-window.vue: desktop/views/components/followers-window.vue:
followers: "{} のフォロワー" followers: "{} seguidores"
desktop/views/components/followers.vue: desktop/views/components/followers.vue:
empty: "フォロワーはいないようです。" empty: "Parece que no tienes seguidores aún."
desktop/views/components/following-window.vue: desktop/views/components/following-window.vue:
following: "{} のフォロー" following: "Siguiendo {}"
desktop/views/components/following.vue: desktop/views/components/following.vue:
empty: "フォロー中のユーザーはいないようです。" empty: "Parece que aún no sigues a nadie."
desktop/views/components/friends-maker.vue: desktop/views/components/friends-maker.vue:
title: "気になるユーザーをフォロー:" title: "Usuarios recomendados:"
empty: "おすすめのユーザーは見つかりませんでした。" empty: "No se pudieron encontrar usuarios para recomendar"
fetching: "読み込んでいます" fetching: "Cargando"
refresh: "もっと見る" refresh: "Más"
close: "閉じる" close: "Cerrar"
desktop/views/components/game-window.vue: desktop/views/components/game-window.vue:
game: "リバーシ" game: "Reversi"
desktop/views/components/home.vue: desktop/views/components/home.vue:
done: "完了" done: "Listo"
add-widget: "Agregar accesorio:" add-widget: "Agregar accesorio:"
add: "Agregar" add: "Agregar"
desktop/views/input-dialog.vue: desktop/views/input-dialog.vue:
@ -565,8 +569,8 @@ desktop/views/components/notes.note.vue:
detail: "Mostrar detalles" detail: "Mostrar detalles"
private: "Esta publicación es privada" private: "Esta publicación es privada"
deleted: "Esta publicación ha sido borrada" deleted: "Esta publicación ha sido borrada"
hide: "隠す" hide: "Esconder"
see-more: "もっと見る" see-more: "Ver más"
desktop/views/components/notes.vue: desktop/views/components/notes.vue:
error: "Error al cargar." error: "Error al cargar."
retry: "Reintentar" retry: "Reintentar"
@ -602,7 +606,7 @@ desktop/views/components/post-form.vue:
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización." geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
error: "Error" error: "Error"
enter-username: "Por favor escribe un nombre de usuario..." enter-username: "Por favor escribe un nombre de usuario..."
annotations: "内容への注釈 (オプション)" annotations: "Anotaciones a la publicación (opcional)"
desktop/views/components/post-form-window.vue: desktop/views/components/post-form-window.vue:
note: "Nota nueva" note: "Nota nueva"
reply: "Responder" reply: "Responder"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "Suprimir fondo" delete-wallpaper: "Suprimir fondo"
dark-mode: "Modo Nocturno" dark-mode: "Modo Nocturno"
circle-icons: "Usar iconos circulares" circle-icons: "Usar iconos circulares"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "Usar degradados en las cabeceras de las páginas" gradient-window-header: "Usar degradados en las cabeceras de las páginas"
post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -766,40 +771,40 @@ desktop/views/components/timeline.vue:
global: "グローバル" global: "グローバル"
list: "リスト" list: "リスト"
desktop/views/components/ui.header.vue: desktop/views/components/ui.header.vue:
welcome-back: "おかえりなさい、" welcome-back: "Bienvenido/a de vuelta,"
adjective: "さん" adjective: "-san"
desktop/views/components/ui.header.account.vue: desktop/views/components/ui.header.account.vue:
profile: "プロフィール" profile: "Tu perfil"
drive: "ドライブ" drive: "Unidad"
favorites: "お気に入り" favorites: "Favoritos"
lists: "リスト" lists: "Listas"
follow-requests: "フォロー申請" follow-requests: "Solicitudes de seguimiento"
customize: "ホームのカスタマイズ" customize: "Personalizar la página de inicio"
admin: "管理" admin: "Admin"
settings: "設定" settings: "Configuraciones"
signout: "サインアウト" signout: "Desconectarse"
dark: "闇に飲まれる" dark: "Sumergirse en la oscuridad"
desktop/views/components/ui.header.nav.vue: desktop/views/components/ui.header.nav.vue:
home: "ホーム" home: "Inicio"
deck: "デッキ" deck: "Cubierta"
messaging: "メッセージ" messaging: "Mensajes"
game: "ゲーム" game: "Juegos"
desktop/views/components/ui.header.notifications.vue: desktop/views/components/ui.header.notifications.vue:
title: "通知" title: "Notificaciones"
desktop/views/components/ui.header.post.vue: desktop/views/components/ui.header.post.vue:
post: "新規投稿" post: "Crear una publicación"
desktop/views/components/ui.header.search.vue: desktop/views/components/ui.header.search.vue:
placeholder: "検索" placeholder: "Buscar"
desktop/views/components/received-follow-requests-window.vue: desktop/views/components/received-follow-requests-window.vue:
title: "フォロー申請" title: "Solicitudes de seguidores"
accept: "承認" accept: "Aceptar"
reject: "拒否" reject: "Rechazar"
desktop/views/components/user-lists-window.vue: desktop/views/components/user-lists-window.vue:
title: "リスト" title: "Listas de usuario"
create-list: "リストを作成" create-list: "Crear lista"
list-name: "リスト名" list-name: "Nombre de lista"
desktop/views/components/user-preview.vue: desktop/views/components/user-preview.vue:
notes: "投稿" notes: "Publicaciones"
following: "フォロー" following: "フォロー"
followers: "フォロワー" followers: "フォロワー"
desktop/views/components/users-list.vue: desktop/views/components/users-list.vue:
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Compte vérifié" verified-user: "Compte vérifié"
disable-animated-mfm: "Désactiver les textes animés dans les publications" disable-animated-mfm: "Désactiver les textes animés dans les publications"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "Partie nulle" drawn: "Partie nulle"
my-turn: "Cest votre tour" my-turn: "Cest votre tour"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "Développeur·se·s" develop: "Développeur·se·s"
feedback: "Remarques" feedback: "Remarques"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "Mettre cette note en favoris" favorite: "Mettre cette note en favoris"
pin: "Épingler sur votre profil" pin: "Épingler sur votre profil"
delete: "Supprimer" delete: "Supprimer"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "Direct" specified: "Direct"
specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s" specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s"
private: "Privé" private: "Privé"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Récupération" fetching: "Récupération"
no-broadcasts: "Aucune annonce" no-broadcasts: "Aucune annonce"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "Basculer entre les vues" toggle: "Basculer entre les vues"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "Étiquettes" title: "Étiquettes"
count: "{} utilisateur·rice·s mentionné·e·s"
empty: "Aucune tendance"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "Informations sur le serveur" title: "Informations sur le serveur"
toggle: "Afficher les vues" toggle: "Afficher les vues"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "Supprimer le fond d'écran" delete-wallpaper: "Supprimer le fond d'écran"
dark-mode: "Mode nuit" dark-mode: "Mode nuit"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "Se connecter" signin-button: "Se connecter"
signup-button: "S'inscrire" signup-button: "S'inscrire"
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Propulsé par <b>Misskey</b>." powered-by-misskey: "Propulsé par <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Lecteur de Misskey" title: "Lecteur de Misskey"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "Mode nuit" dark-mode: "Mode nuit"
i-am-under-limited-internet: "J'ai un accès Internet limité" i-am-under-limited-internet: "J'ai un accès Internet limité"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
show-reply-target: "Afficher les réponses" show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications" show-my-renotes: "Afficher mes republications"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "Style de la publication" post-style: "Style de la publication"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Intelligent" post-style-smart: "Intelligent"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "Comportement" behavior: "Comportement"
fetch-on-scroll: "Chargement lors du défilement" fetch-on-scroll: "Chargement lors du défilement"
disable-via-mobile: "Ne pas mentionner que ma publication provient d'un 'périphérique mobile'" disable-via-mobile: "Ne pas mentionner que ma publication provient d'un 'périphérique mobile'"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "Réglages" settings: "Réglages"
signout: "Déconnexion" signout: "Déconnexion"
sound: "Sons" sound: "Sons"
enableSounds: "Activer le son" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "vous suit" follows-you: "vous suit"
following: "Abonnements" following: "Abonnements"

View File

@ -5,7 +5,7 @@
const fs = require('fs'); const fs = require('fs');
const yaml = require('js-yaml'); const yaml = require('js-yaml');
const langs = ['de-DE', 'en-US', 'fr-FR', 'ja-JP', 'ja-KS', 'pl-PL', 'es-ES']; const langs = ['de-DE', 'en-US', 'fr-FR', 'ja-JP', 'ja-KS', 'pl-PL', 'es-ES', 'nl-NL'];
const loadLocale = lang => yaml.safeLoad(fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8')); const loadLocale = lang => yaml.safeLoad(fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
const locales = langs.map(lang => ({ [lang]: loadLocale(lang) })); const locales = langs.map(lang => ({ [lang]: loadLocale(lang) }));

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
my-turn: "あなたのターンです" my-turn: "あなたのターンです"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@ -73,6 +86,16 @@ common:
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@ -724,6 +747,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@ -736,6 +762,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -990,7 +1017,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
@ -1347,6 +1377,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1355,8 +1386,14 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"
@ -1376,7 +1413,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストをつけんで!" use-contrast-reversi-stones: "リバーシのアイコンにコントラストをつけんで!"
verified-user: "アメちゃん付きアカウント" verified-user: "アメちゃん付きアカウント"
disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める" disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "おあいこ" drawn: "おあいこ"
my-turn: "あんさんのターンや" my-turn: "あんさんのターンや"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "ほかす" delete: "ほかす"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはあらへんで" no-broadcasts: "お知らせはあらへんで"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "流行は自分で作るんや"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "サインイン中…" signin-button: "サインイン中…"
signup-button: "サインアップ" signup-button: "サインアップ"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "ドライブ" title: "ドライブ"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "べっぴんさん" post-style-smart: "べっぴんさん"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할" disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "무승부" drawn: "무승부"
my-turn: "당신의 차례입니다" my-turn: "당신의 차례입니다"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

1249
locales/nl-NL.yml Normal file

File diff suppressed because it is too large Load Diff

1249
locales/no-NO.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "Wyłącz animowany tekst we wpisach" disable-animated-mfm: "Wyłącz animowany tekst we wpisach"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "Remis" drawn: "Remis"
my-turn: "Twoja kolej" my-turn: "Twoja kolej"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "Autorzy" develop: "Autorzy"
feedback: "Podziel się opinią" feedback: "Podziel się opinią"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "Dodaj do ulubionych" favorite: "Dodaj do ulubionych"
pin: "Przypnij do profilu" pin: "Przypnij do profilu"
delete: "Usuń" delete: "Usuń"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "Bezpośredni" specified: "Bezpośredni"
specified-desc: "Tylko dla określonych użytkowników" specified-desc: "Tylko dla określonych użytkowników"
private: "Prywatny" private: "Prywatny"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Sprawdzanie" fetching: "Sprawdzanie"
no-broadcasts: "Brak transmisji" no-broadcasts: "Brak transmisji"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "Przełącz widok" toggle: "Przełącz widok"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "Hashtagi" title: "Hashtagi"
count: "Wspomniany przez {} użytkowników"
empty: "Brak popularnych hashtagów"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "Informacje o serwerze" title: "Informacje o serwerze"
toggle: "Przełącz widok" toggle: "Przełącz widok"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "Usuń tło" delete-wallpaper: "Usuń tło"
dark-mode: "Tryb ciemny" dark-mode: "Tryb ciemny"
circle-icons: "Używaj okrągłych ikon" circle-icons: "Używaj okrągłych ikon"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "Używaj gradientów na pasku tytułu okna" gradient-window-header: "Używaj gradientów na pasku tytułu okna"
post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "Zaloguj się" signin-button: "Zaloguj się"
signup-button: "Zarejestruj się" signup-button: "Zarejestruj się"
timeline: "Oś czasu" timeline: "Oś czasu"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Oparto o <b>Misskey</b>." powered-by-misskey: "Oparto o <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Dysk Misskey" title: "Dysk Misskey"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "Tryb ciemny" dark-mode: "Tryb ciemny"
i-am-under-limited-internet: "Ograniczaj zużycie transferu" i-am-under-limited-internet: "Ograniczaj zużycie transferu"
circle-icons: "Używaj okrągłych ikon" circle-icons: "Używaj okrągłych ikon"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "Oś czasu" timeline: "Oś czasu"
show-reply-target: "Pokazuj cel odpowiedzi" show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia" show-my-renotes: "Pokazuj moje udostępnienia"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "Styl wpisów" post-style: "Styl wpisów"
post-style-standard: "Standardowy" post-style-standard: "Standardowy"
post-style-smart: "Inteligentny" post-style-smart: "Inteligentny"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "Zachowanie" behavior: "Zachowanie"
fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół"
disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”" disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "Ustawienia" settings: "Ustawienia"
signout: "Wyloguj" signout: "Wyloguj"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "Śledzi Cię" follows-you: "Śledzi Cię"
following: "Śledzeni" following: "Śledzeni"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Conta verificada" verified-user: "Conta verificada"
disable-animated-mfm: "Desativar texto animado nas publicações" disable-animated-mfm: "Desativar texto animado nas publicações"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "Empatado" drawn: "Empatado"
my-turn: "Seu turno" my-turn: "Seu turno"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "Timeline" timeline: "Timeline"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Desenvolvido por <b>Misskey</b>." powered-by-misskey: "Desenvolvido por <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Drive Misskey" title: "Drive Misskey"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
my-turn: "あなたのターンです" my-turn: "あなたのターンです"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -87,6 +87,7 @@ common:
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
my-turn: "あなたのターンです" my-turn: "あなたのターンです"
@ -260,6 +261,8 @@ common/views/components/nav.vue:
develop: "開発者" develop: "開発者"
feedback: "フィードバック" feedback: "フィードバック"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
pin: "ピン留め" pin: "ピン留め"
delete: "削除" delete: "削除"
@ -337,6 +340,9 @@ common/views/components/visibility-chooser.vue:
specified: "ダイレクト" specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開" specified-desc: "指定したユーザーにのみ公開"
private: "非公開" private: "非公開"
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "確認中" fetching: "確認中"
no-broadcasts: "お知らせはありません" no-broadcasts: "お知らせはありません"
@ -360,8 +366,6 @@ common/views/widgets/posts-monitor.vue:
toggle: "表示を切り替え" toggle: "表示を切り替え"
common/views/widgets/hashtags.vue: common/views/widgets/hashtags.vue:
title: "ハッシュタグ" title: "ハッシュタグ"
count: "{}人が投稿"
empty: "トレンドなし"
common/views/widgets/server.vue: common/views/widgets/server.vue:
title: "サーバー情報" title: "サーバー情報"
toggle: "表示を切り替え" toggle: "表示を切り替え"
@ -647,6 +651,7 @@ desktop/views/components/settings.vue:
delete-wallpaper: "壁紙を削除" delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード" dark-mode: "ダークモード"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@ -861,7 +866,10 @@ desktop/views/pages/welcome.vue:
signin-button: "やってる" signin-button: "やってる"
signup-button: "やる" signup-button: "やる"
timeline: "タイムライン" timeline: "タイムライン"
announcements: "お知らせ"
photos: "最近の画像"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
info: "情報"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Misskey Drive" title: "Misskey Drive"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@ -1149,6 +1157,7 @@ mobile/views/pages/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
i-am-under-limited-internet: "私は通信を制限されている" i-am-under-limited-internet: "私は通信を制限されている"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける"
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
@ -1157,6 +1166,9 @@ mobile/views/pages/settings.vue:
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"
notification-position: "通知の表示"
notification-position-bottom: "下"
notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
@ -1178,7 +1190,7 @@ mobile/views/pages/settings.vue:
settings: "設定" settings: "設定"
signout: "サインアウト" signout: "サインアウト"
sound: "サウンド" sound: "サウンド"
enableSounds: "サウンドを有効にする" enable-sounds: "サウンドを有効にする"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "フォローされています" follows-you: "フォローされています"
following: "フォロー" following: "フォロー"

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "8.25.0", "version": "8.32.0",
"clientVersion": "1.0.9297", "clientVersion": "1.0.9489",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -55,7 +55,7 @@
"@types/koa-send": "4.1.1", "@types/koa-send": "4.1.1",
"@types/koa-views": "2.0.3", "@types/koa-views": "2.0.3",
"@types/koa__cors": "2.2.3", "@types/koa__cors": "2.2.3",
"@types/minio": "6.0.2", "@types/minio": "7.0.0",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/mocha": "5.2.3", "@types/mocha": "5.2.3",
"@types/mongodb": "3.1.4", "@types/mongodb": "3.1.4",
@ -80,7 +80,7 @@
"@types/webpack": "4.4.11", "@types/webpack": "4.4.11",
"@types/webpack-stream": "3.2.10", "@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.40", "@types/websocket": "0.0.40",
"@types/ws": "6.0.0", "@types/ws": "6.0.1",
"animejs": "2.2.0", "animejs": "2.2.0",
"autosize": "4.0.2", "autosize": "4.0.2",
"autwh": "0.1.0", "autwh": "0.1.0",
@ -151,7 +151,7 @@
"lodash.assign": "4.2.0", "lodash.assign": "4.2.0",
"mecab-async": "0.1.2", "mecab-async": "0.1.2",
"merge-options": "1.0.1", "merge-options": "1.0.1",
"minio": "7.0.0", "minio": "7.0.1",
"mkdirp": "0.5.1", "mkdirp": "0.5.1",
"mocha": "5.2.0", "mocha": "5.2.0",
"moji": "0.5.1", "moji": "0.5.1",
@ -161,7 +161,7 @@
"nan": "2.11.0", "nan": "2.11.0",
"nested-property": "0.0.7", "nested-property": "0.0.7",
"node-sass": "4.9.3", "node-sass": "4.9.3",
"node-sass-json-importer": "3.3.1", "node-sass-json-importer": "4.0.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"object-assign-deep": "0.4.0", "object-assign-deep": "0.4.0",
"on-build-webpack": "0.1.0", "on-build-webpack": "0.1.0",
@ -194,7 +194,7 @@
"stylus": "0.54.5", "stylus": "0.54.5",
"stylus-loader": "3.0.2", "stylus-loader": "3.0.2",
"summaly": "2.2.0", "summaly": "2.2.0",
"systeminformation": "3.44.2", "systeminformation": "3.45.1",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"tmp": "0.0.33", "tmp": "0.0.33",
@ -210,18 +210,19 @@
"vue": "2.5.17", "vue": "2.5.17",
"vue-chartjs": "3.4.0", "vue-chartjs": "3.4.0",
"vue-cropperjs": "2.2.1", "vue-cropperjs": "2.2.1",
"vue-js-modal": "1.3.25", "vue-js-modal": "1.3.26",
"vue-json-tree-view": "2.1.4", "vue-json-tree-view": "2.1.4",
"vue-loader": "15.4.1", "vue-loader": "15.4.1",
"vue-router": "3.0.1", "vue-router": "3.0.1",
"vue-style-loader": "4.1.2", "vue-style-loader": "4.1.2",
"vue-template-compiler": "2.5.17", "vue-template-compiler": "2.5.17",
"vuedraggable": "2.16.0", "vuedraggable": "2.16.0",
"vuewordcloud": "18.7.11",
"vuex": "3.0.1", "vuex": "3.0.1",
"vuex-persistedstate": "2.5.4", "vuex-persistedstate": "2.5.4",
"web-push": "3.3.2", "web-push": "3.3.2",
"webfinger.js": "2.6.6", "webfinger.js": "2.6.6",
"webpack": "4.17.1", "webpack": "4.17.2",
"webpack-cli": "3.1.0", "webpack-cli": "3.1.0",
"websocket": "1.0.26", "websocket": "1.0.26",
"ws": "6.0.0", "ws": "6.0.0",

View File

@ -140,7 +140,7 @@
// Random // Random
localStorage.setItem('salt', Math.random().toString()); localStorage.setItem('salt', Math.random().toString());
// Clear cache (serive worker) // Clear cache (service worker)
try { try {
navigator.serviceWorker.controller.postMessage('clear'); navigator.serviceWorker.controller.postMessage('clear');

View File

@ -9,7 +9,7 @@ export default async function(mios: MiOS, force = false, silent = false) {
localStorage.setItem('should-refresh', 'true'); localStorage.setItem('should-refresh', 'true');
localStorage.setItem('v', newer); localStorage.setItem('v', newer);
// Clear cache (serive worker) // Clear cache (service worker)
try { try {
if (navigator.serviceWorker.controller) { if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage('clear'); navigator.serviceWorker.controller.postMessage('clear');

View File

@ -1,2 +0,0 @@
const gcd = (a, b) => !b ? a : gcd(b, a % b);
export default gcd;

View File

@ -1,53 +0,0 @@
export default function(qs: string) {
const q = {
text: ''
};
qs.split(' ').forEach(x => {
if (/^([a-z_]+?):(.+?)$/.test(x)) {
const [key, value] = x.split(':');
switch (key) {
case 'user':
q['includeUserUsernames'] = value.split(',');
break;
case 'exclude_user':
q['excludeUserUsernames'] = value.split(',');
break;
case 'follow':
q['following'] = value == 'null' ? null : value == 'true';
break;
case 'reply':
q['reply'] = value == 'null' ? null : value == 'true';
break;
case 'renote':
q['renote'] = value == 'null' ? null : value == 'true';
break;
case 'media':
q['media'] = value == 'null' ? null : value == 'true';
break;
case 'poll':
q['poll'] = value == 'null' ? null : value == 'true';
break;
case 'until':
case 'since':
// YYYY-MM-DD
if (/^[0-9]+\-[0-9]+\-[0-9]+$/) {
const [yyyy, mm, dd] = value.split('-');
q[`${key}_date`] = (new Date(parseInt(yyyy, 10), parseInt(mm, 10) - 1, parseInt(dd, 10))).getTime();
}
break;
default:
q[key] = value;
break;
}
} else {
q.text += x + ' ';
}
});
if (q.text) {
q.text = q.text.trim();
}
return q;
}

View File

@ -1,6 +1,7 @@
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
import Connection from './stream'; import Connection from './stream';
import { erase } from '../../../../../prelude/array';
/** /**
* ストリーム接続を管理するクラス * ストリーム接続を管理するクラス
@ -89,7 +90,7 @@ export default abstract class StreamManager<T extends Connection> extends EventE
* @param userId use で発行したユーザーID * @param userId use で発行したユーザーID
*/ */
public dispose(userId) { public dispose(userId) {
this.users = this.users.filter(id => id != userId); this.users = erase(userId, this.users);
this._connection.user = `Managed (${ this.users.length })`; this._connection.user = `Managed (${ this.users.length })`;

View File

@ -1,19 +1,25 @@
<template> <template>
<span class="mk-acct"> <span class="mk-acct">
<span class="name">@{{ user.username }}</span> <span class="name">@{{ user.username }}</span>
<span class="host" v-if="user.host">@{{ user.host }}</span> <span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="user.host || detail">@{{ user.host || host }}</span>
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { host } from '../../../config';
export default Vue.extend({ export default Vue.extend({
props: ['user'] props: ['user', 'detail'],
data() {
return {
host
};
}
}); });
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.mk-acct .mk-acct
> .host > .host.fade
opacity 0.5 opacity 0.5
</style> </style>

View File

@ -1,5 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import tagCloud from './tag-cloud.vue';
import trends from './trends.vue'; import trends from './trends.vue';
import analogClock from './analog-clock.vue'; import analogClock from './analog-clock.vue';
import menu from './menu.vue'; import menu from './menu.vue';
@ -41,6 +42,7 @@ import uiSelect from './ui/select.vue';
import formButton from './ui/form/button.vue'; import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue'; import formRadio from './ui/form/radio.vue';
Vue.component('mk-tag-cloud', tagCloud);
Vue.component('mk-trends', trends); Vue.component('mk-trends', trends);
Vue.component('mk-analog-clock', analogClock); Vue.component('mk-analog-clock', analogClock);
Vue.component('mk-menu', menu); Vue.component('mk-menu', menu);

View File

@ -20,6 +20,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { erase } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
data() { data() {
return { return {
@ -53,7 +54,7 @@ export default Vue.extend({
get() { get() {
return { return {
choices: this.choices.filter(choice => choice != '') choices: erase('', this.choices)
} }
}, },

View File

@ -21,6 +21,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { sum } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
props: ['note'], props: ['note'],
data() { data() {
@ -33,7 +34,7 @@ export default Vue.extend({
return this.note.poll; return this.note.poll;
}, },
total(): number { total(): number {
return this.poll.choices.reduce((a, b) => a + b.votes, 0); return sum(this.poll.choices.map(x => x.votes));
}, },
isVoted(): boolean { isVoted(): boolean {
return this.poll.choices.some(c => c.isVoted); return this.poll.choices.some(c => c.isVoted);

View File

@ -0,0 +1,90 @@
<template>
<div class="jtivnzhfwquxpsfidertopbmwmchmnmo">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="tags.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
<div v-else>
<vue-word-cloud
:words="tags.slice(0, 20).map(x => [x.name, x.count])"
:color="color"
:spacing="1">
<template slot-scope="{word, text, weight}">
<div style="cursor: pointer;" :title="weight">
{{ text }}
</div>
</template>
</vue-word-cloud>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as VueWordCloud from 'vuewordcloud';
export default Vue.extend({
components: {
[VueWordCloud.name]: VueWordCloud
},
data() {
return {
tags: [],
fetching: true,
clock: null
};
},
mounted() {
this.fetch();
this.clock = setInterval(this.fetch, 1000 * 60);
},
beforeDestroy() {
clearInterval(this.clock);
},
methods: {
fetch() {
(this as any).api('aggregation/hashtags').then(tags => {
this.tags = tags;
this.fetching = false;
});
},
color([, weight]) {
const peak = Math.max.apply(null, this.tags.map(x => x.count));
const w = weight / peak;
if (w > 0.9) {
return this.$store.state.device.darkmode ? '#ff4e69' : '#ff4e69';
} else if (w > 0.5) {
return this.$store.state.device.darkmode ? '#3bc4c7' : '#3bc4c7';
} else {
return this.$store.state.device.darkmode ? '#fff' : '#555';
}
}
}
});
</script>
<style lang="stylus" scoped>
root(isDark)
height 100%
width 100%
> .fetching
> .empty
margin 0
padding 16px
text-align center
color #aaa
> [data-fa]
margin-right 4px
> div
height 100%
width 100%
.jtivnzhfwquxpsfidertopbmwmchmnmo[data-darkmode]
root(true)
.jtivnzhfwquxpsfidertopbmwmchmnmo:not([data-darkmode])
root(false)
</style>

View File

@ -24,19 +24,34 @@ export default Vue.extend({
root(isDark) root(isDark)
margin 16px margin 16px
padding 16px
color isDark ? #fff : #000 color isDark ? #fff : #000
background isDark ? #282C37 : #fff background isDark ? #282C37 : #fff
box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12) box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
@media (min-width 500px)
padding 32px
> header > header
font-weight normal padding 16px
font-size 24px font-weight bold
font-size 20px
color isDark ? #fff : #444 color isDark ? #fff : #444
@media (min-width 500px)
padding 24px 32px
> section
padding 20px 16px
border-top solid 1px isDark ? rgba(#000, 0.3) : rgba(#000, 0.1)
@media (min-width 500px)
padding 32px
&.fit-top
padding-top 0
> header
margin-bottom 16px
font-weight bold
color isDark ? #fff : #444
.ui-card[data-darkmode] .ui-card[data-darkmode]
root(true) root(true)

View File

@ -55,7 +55,7 @@ export default Vue.extend({
root(isDark) root(isDark)
display inline-block display inline-block
margin 32px 32px 32px 0 margin 0 32px 0 0
cursor pointer cursor pointer
transition all 0.3s transition all 0.3s

View File

@ -64,6 +64,12 @@ root(isDark)
cursor pointer cursor pointer
transition all 0.3s transition all 0.3s
&:first-child
margin-top 0
&:last-child
margin-bottom 0
> * > *
user-select none user-select none
@ -89,6 +95,7 @@ root(isDark)
> .button > .button
display inline-block display inline-block
flex-shrink 0
margin 3px 0 0 0 margin 3px 0 0 0
width 34px width 34px
height 14px height 14px

View File

@ -14,7 +14,7 @@
<header> <header>
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
</header> </header>
<p>{{ description }}</p> <p>{{ description.length > 85 ? description.slice(0, 85) + '…' : description }}</p>
<footer> <footer>
<img class="icon" v-if="icon" :src="icon"/> <img class="icon" v-if="icon" :src="icon"/>
<p>{{ sitename }}</p> <p>{{ sitename }}</p>

View File

@ -47,7 +47,7 @@ export default Vue.extend({
props: ['source', 'compact'], props: ['source', 'compact'],
data() { data() {
return { return {
v: this.$store.state.device.visibility || 'public' v: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility
} }
}, },
mounted() { mounted() {
@ -97,7 +97,9 @@ export default Vue.extend({
}, },
methods: { methods: {
choose(visibility) { choose(visibility) {
this.$store.commit('device/setVisibility', visibility); if (this.$store.state.settings.rememberNoteVisibility) {
this.$store.commit('device/setVisibility', visibility);
}
this.$emit('chosen', visibility); this.$emit('chosen', visibility);
this.$destroy(); this.$destroy();
}, },

View File

@ -1,22 +1,24 @@
<template> <template>
<div class="mk-welcome-timeline"> <div class="mk-welcome-timeline">
<div v-for="note in notes"> <transition-group name="ldzpakcixzickvggyixyrhqwjaefknon" tag="div">
<mk-avatar class="avatar" :user="note.user" target="_blank"/> <div v-for="note in notes" :key="note.id">
<div class="body"> <mk-avatar class="avatar" :user="note.user" target="_blank"/>
<header> <div class="body">
<router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link> <header>
<span class="username">@{{ note.user | acct }}</span> <router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
<div class="info"> <span class="username">@{{ note.user | acct }}</span>
<router-link class="created-at" :to="note | notePage"> <div class="info">
<mk-time :time="note.createdAt"/> <router-link class="created-at" :to="note | notePage">
</router-link> <mk-time :time="note.createdAt"/>
</router-link>
</div>
</header>
<div class="text">
<misskey-flavored-markdown v-if="note.text" :text="note.text"/>
</div> </div>
</header>
<div class="text">
<misskey-flavored-markdown v-if="note.text" :text="note.text"/>
</div> </div>
</div> </div>
</div> </transition-group>
</div> </div>
</template> </template>
@ -63,7 +65,7 @@ export default Vue.extend({
local: true, local: true,
reply: false, reply: false,
renote: false, renote: false,
media: false, file: false,
poll: false poll: false
}).then(notes => { }).then(notes => {
this.notes = notes; this.notes = notes;
@ -83,64 +85,73 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.ldzpakcixzickvggyixyrhqwjaefknon-enter
.ldzpakcixzickvggyixyrhqwjaefknon-leave-to
opacity 0
transform translateY(-30px)
root(isDark) root(isDark)
background isDark ? #282C37 : #fff background isDark ? #282C37 : #fff
> div > div
padding 16px > *
overflow-wrap break-word transition transform .3s ease, opacity .3s ease
font-size .9em
color isDark ? #fff : #4C4C4C
border-bottom 1px solid isDark ? rgba(#000, 0.1) : rgba(#000, 0.05)
&:after > div
content "" padding 16px
display block overflow-wrap break-word
clear both font-size .9em
color isDark ? #fff : #4C4C4C
border-bottom 1px solid isDark ? rgba(#000, 0.1) : rgba(#000, 0.05)
> .avatar &:after
display block content ""
float left display block
position -webkit-sticky clear both
position sticky
top 16px
width 42px
height 42px
border-radius 6px
> .body > .avatar
float right display block
width calc(100% - 42px) float left
padding-left 12px position -webkit-sticky
position sticky
top 16px
width 42px
height 42px
border-radius 6px
> header > .body
display flex float right
align-items center width calc(100% - 42px)
margin-bottom 4px padding-left 12px
white-space nowrap
> .name > header
display block display flex
margin 0 .5em 0 0 align-items center
padding 0 margin-bottom 4px
overflow hidden white-space nowrap
font-weight bold
text-overflow ellipsis
color isDark ? #fff : #627079
> .username > .name
margin 0 .5em 0 0 display block
color isDark ? #606984 : #ccc margin 0 .5em 0 0
padding 0
overflow hidden
font-weight bold
text-overflow ellipsis
color isDark ? #fff : #627079
> .info > .username
margin-left auto margin 0 .5em 0 0
font-size 0.9em color isDark ? #606984 : #ccc
> .created-at > .info
color isDark ? #606984 : #c0c0c0 margin-left auto
font-size 0.9em
> .text > .created-at
text-align left color isDark ? #606984 : #c0c0c0
> .text
text-align left
.mk-welcome-timeline[data-darkmode] .mk-welcome-timeline[data-darkmode]
root(true) root(true)

View File

@ -83,7 +83,7 @@ export default Vue.extend({
userId: this.user.id userId: this.user.id
}); });
} else { } else {
if (this.user.isLocked && this.user.hasPendingFollowRequestFromYou) { if (this.user.hasPendingFollowRequestFromYou) {
this.user = await (this as any).api('following/requests/cancel', { this.user = await (this as any).api('following/requests/cancel', {
userId: this.user.id userId: this.user.id
}); });

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="mkw-analog-clock"> <div class="mkw-analog-clock">
<mk-widget-container :naked="!(props.design % 2)" :show-header="false"> <mk-widget-container :naked="props.style % 2 === 0" :show-header="false">
<div class="mkw-analog-clock--body"> <div class="mkw-analog-clock--body">
<mk-analog-clock :dark="$store.state.device.darkmode" :smooth="!(props.design && ~props.design)"/> <mk-analog-clock :dark="$store.state.device.darkmode" :smooth="props.style < 2"/>
</div> </div>
</mk-widget-container> </mk-widget-container>
</div> </div>
@ -13,13 +13,12 @@ import define from '../../../common/define-widget';
export default define({ export default define({
name: 'analog-clock', name: 'analog-clock',
props: () => ({ props: () => ({
design: -1 style: 0
}) })
}).extend({ }).extend({
methods: { methods: {
func() { func() {
if (++this.props.design > 2) this.props.style = (this.props.style + 1) % 4;
this.props.design = -1;
this.save(); this.save();
} }
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="anltbovirfeutcigvwgmgxipejaeozxi" <div class="anltbovirfeutcigvwgmgxipejaeozxi"
:data-found="broadcasts.length != 0" :data-found="announcements && announcements.length != 0"
:data-melt="props.design == 1" :data-melt="props.design == 1"
:data-mobile="platform == 'mobile'" :data-mobile="platform == 'mobile'"
> >
@ -14,12 +14,12 @@
</svg> </svg>
</div> </div>
<p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p>
<h1 v-if="!fetching">{{ broadcasts.length == 0 ? '%i18n:@no-broadcasts%' : broadcasts[i].title }}</h1> <h1 v-if="!fetching">{{ announcements.length == 0 ? '%i18n:@no-broadcasts%' : announcements[i].title }}</h1>
<p v-if="!fetching"> <p v-if="!fetching">
<span v-if="broadcasts.length != 0" v-html="broadcasts[i].text"></span> <span v-if="announcements.length != 0" v-html="announcements[i].text"></span>
<template v-if="broadcasts.length == 0">%i18n:@have-a-nice-day%</template> <template v-if="announcements.length == 0">%i18n:@have-a-nice-day%</template>
</p> </p>
<a v-if="broadcasts.length > 1" @click="next">%i18n:@next% &gt;&gt;</a> <a v-if="announcements.length > 1" @click="next">%i18n:@next% &gt;&gt;</a>
</div> </div>
</template> </template>
@ -36,18 +36,18 @@ export default define({
return { return {
i: 0, i: 0,
fetching: true, fetching: true,
broadcasts: [] announcements: []
}; };
}, },
mounted() { mounted() {
(this as any).os.getMeta().then(meta => { (this as any).os.getMeta().then(meta => {
this.broadcasts = meta.broadcasts; this.announcements = meta.broadcasts;
this.fetching = false; this.fetching = false;
}); });
}, },
methods: { methods: {
next() { next() {
if (this.i == this.broadcasts.length - 1) { if (this.i == this.announcements.length - 1) {
this.i = 0; this.i = 0;
} else { } else {
this.i++; this.i++;
@ -126,7 +126,7 @@ root(isDark)
margin 0 margin 0
font-size 0.95em font-size 0.95em
font-weight normal font-weight normal
color #4078c0 color isDark ? #539eff : #4078c0
> p > p
display block display block

View File

@ -55,13 +55,15 @@ export default Vue.extend({
methods: { methods: {
onFollow(user) { onFollow(user) {
if (user.id == this.u.id) { if (user.id == this.u.id) {
this.user.isFollowing = user.isFollowing; this.u.isFollowing = user.isFollowing;
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
} }
}, },
onUnfollow(user) { onUnfollow(user) {
if (user.id == this.u.id) { if (user.id == this.u.id) {
this.user.isFollowing = user.isFollowing; this.u.isFollowing = user.isFollowing;
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
} }
}, },
@ -74,7 +76,7 @@ export default Vue.extend({
userId: this.u.id userId: this.u.id
}); });
} else { } else {
if (this.u.isLocked && this.u.hasPendingFollowRequestFromYou) { if (this.u.hasPendingFollowRequestFromYou) {
this.u = await (this as any).api('following/requests/cancel', { this.u = await (this as any).api('following/requests/cancel', {
userId: this.u.id userId: this.u.id
}); });

View File

@ -42,8 +42,8 @@
<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span> <span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/> <misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
</div> </div>
<div class="media" v-if="p.media.length > 0"> <div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.media" :raw="true"/> <mk-media-list :media-list="p.files" :raw="true"/>
</div> </div>
<mk-poll v-if="p.poll" :note="p"/> <mk-poll v-if="p.poll" :note="p"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> <mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
@ -86,6 +86,7 @@ import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue'; import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue'; import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './notes.note.sub.vue'; import XSub from './notes.note.sub.vue';
import { sum } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@ -114,7 +115,7 @@ export default Vue.extend({
isRenote(): boolean { isRenote(): boolean {
return (this.note.renote && return (this.note.renote &&
this.note.text == null && this.note.text == null &&
this.note.mediaIds.length == 0 && this.note.fileIds.length == 0 &&
this.note.poll == null); this.note.poll == null);
}, },
p(): any { p(): any {
@ -122,9 +123,7 @@ export default Vue.extend({
}, },
reactionsCount(): number { reactionsCount(): number {
return this.p.reactionCounts return this.p.reactionCounts
? Object.keys(this.p.reactionCounts) ? sum(Object.values(this.p.reactionCounts))
.map(key => this.p.reactionCounts[key])
.reduce((a, b) => a + b)
: 0; : 0;
}, },
title(): string { title(): string {

View File

@ -28,8 +28,8 @@
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/> <misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
<a class="rp" v-if="p.renote">RP:</a> <a class="rp" v-if="p.renote">RP:</a>
</div> </div>
<div class="media" v-if="p.media.length > 0"> <div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.media"/> <mk-media-list :media-list="p.files"/>
</div> </div>
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> <a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
@ -78,6 +78,7 @@ import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue'; import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue'; import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './notes.note.sub.vue'; import XSub from './notes.note.sub.vue';
import { sum } from '../../../../../prelude/array';
function focus(el, fn) { function focus(el, fn) {
const target = fn(el); const target = fn(el);
@ -110,7 +111,7 @@ export default Vue.extend({
isRenote(): boolean { isRenote(): boolean {
return (this.note.renote && return (this.note.renote &&
this.note.text == null && this.note.text == null &&
this.note.mediaIds.length == 0 && this.note.fileIds.length == 0 &&
this.note.poll == null); this.note.poll == null);
}, },
@ -120,9 +121,7 @@ export default Vue.extend({
reactionsCount(): number { reactionsCount(): number {
return this.p.reactionCounts return this.p.reactionCounts
? Object.keys(this.p.reactionCounts) ? sum(Object.values(this.p.reactionCounts))
.map(key => this.p.reactionCounts[key])
.reduce((a, b) => a + b)
: 0; : 0;
}, },

View File

@ -122,7 +122,7 @@ export default Vue.extend({
prepend(note, silent = false) { prepend(note, silent = false) {
//#region 弾く //#region 弾く
const isMyNote = note.userId == this.$store.state.i.id; const isMyNote = note.userId == this.$store.state.i.id;
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null; const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
if (this.$store.state.settings.showMyRenotes === false) { if (this.$store.state.settings.showMyRenotes === false) {
if (isMyNote && isPureRenote) { if (isMyNote && isPureRenote) {

View File

@ -4,7 +4,7 @@
<span class="icon" v-if="geo">%fa:map-marker-alt%</span> <span class="icon" v-if="geo">%fa:map-marker-alt%</span>
<span v-if="!reply">%i18n:@note%</span> <span v-if="!reply">%i18n:@note%</span>
<span v-if="reply">%i18n:@reply%</span> <span v-if="reply">%i18n:@reply%</span>
<span class="count" v-if="media.length != 0">{{ '%i18n:@attaches%'.replace('{}', media.length) }}</span> <span class="count" v-if="files.length != 0">{{ '%i18n:@attaches%'.replace('{}', files.length) }}</span>
<span class="count" v-if="uploadings.length != 0">{{ '%i18n:@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span> <span class="count" v-if="uploadings.length != 0">{{ '%i18n:@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span>
</span> </span>
@ -14,7 +14,7 @@
:reply="reply" :reply="reply"
@posted="onPosted" @posted="onPosted"
@change-uploadings="onChangeUploadings" @change-uploadings="onChangeUploadings"
@change-attached-media="onChangeMedia" @change-attached-files="onChangeFiles"
@geo-attached="onGeoAttached" @geo-attached="onGeoAttached"
@geo-dettached="onGeoDettached"/> @geo-dettached="onGeoDettached"/>
</div> </div>
@ -29,7 +29,7 @@ export default Vue.extend({
data() { data() {
return { return {
uploadings: [], uploadings: [],
media: [], files: [],
geo: null geo: null
}; };
}, },
@ -42,8 +42,8 @@ export default Vue.extend({
onChangeUploadings(files) { onChangeUploadings(files) {
this.uploadings = files; this.uploadings = files;
}, },
onChangeMedia(media) { onChangeFiles(files) {
this.media = media; this.files = files;
}, },
onGeoAttached(geo) { onGeoAttached(geo) {
this.geo = geo; this.geo = geo;

View File

@ -20,7 +20,7 @@
@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
v-autocomplete="'text'" v-autocomplete="'text'"
></textarea> ></textarea>
<div class="medias" :class="{ with: poll }" v-show="files.length != 0"> <div class="files" :class="{ with: poll }" v-show="files.length != 0">
<x-draggable :list="files" :options="{ animation: 150 }"> <x-draggable :list="files" :options="{ animation: 150 }">
<div v-for="file in files" :key="file.id"> <div v-for="file in files" :key="file.id">
<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div> <div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div>
@ -62,6 +62,7 @@ import getFace from '../../../common/scripts/get-face';
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue'; import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import { host } from '../../../config'; import { host } from '../../../config';
import { erase } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@ -99,7 +100,7 @@ export default Vue.extend({
useCw: false, useCw: false,
cw: null, cw: null,
geo: null, geo: null,
visibility: this.$store.state.device.visibility || 'public', visibility: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility,
visibleUsers: [], visibleUsers: [],
autocomplete: null, autocomplete: null,
draghover: false, draghover: false,
@ -188,7 +189,7 @@ export default Vue.extend({
(this.$refs.poll as any).set(draft.data.poll); (this.$refs.poll as any).set(draft.data.poll);
}); });
} }
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
} }
} }
@ -225,12 +226,12 @@ export default Vue.extend({
attachMedia(driveFile) { attachMedia(driveFile) {
this.files.push(driveFile); this.files.push(driveFile);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
}, },
detachMedia(id) { detachMedia(id) {
this.files = this.files.filter(x => x.id != id); this.files = this.files.filter(x => x.id != id);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
}, },
onChangeFile() { onChangeFile() {
@ -249,7 +250,7 @@ export default Vue.extend({
this.text = ''; this.text = '';
this.files = []; this.files = [];
this.poll = false; this.poll = false;
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
}, },
onKeydown(e) { onKeydown(e) {
@ -297,7 +298,7 @@ export default Vue.extend({
if (driveFile != null && driveFile != '') { if (driveFile != null && driveFile != '') {
const file = JSON.parse(driveFile); const file = JSON.parse(driveFile);
this.files.push(file); this.files.push(file);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
e.preventDefault(); e.preventDefault();
} }
//#endregion //#endregion
@ -346,7 +347,7 @@ export default Vue.extend({
}, },
removeVisibleUser(user) { removeVisibleUser(user) {
this.visibleUsers = this.visibleUsers.filter(u => u != user); this.visibleUsers = erase(user, this.visibleUsers);
}, },
post() { post() {
@ -354,7 +355,7 @@ export default Vue.extend({
(this as any).api('notes/create', { (this as any).api('notes/create', {
text: this.text == '' ? undefined : this.text, text: this.text == '' ? undefined : this.text,
mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined, fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
replyId: this.reply ? this.reply.id : undefined, replyId: this.reply ? this.reply.id : undefined,
renoteId: this.renote ? this.renote.id : undefined, renoteId: this.renote ? this.renote.id : undefined,
poll: this.poll ? (this.$refs.poll as any).get() : undefined, poll: this.poll ? (this.$refs.poll as any).get() : undefined,
@ -514,7 +515,7 @@ root(isDark)
margin-right 8px margin-right 8px
white-space nowrap white-space nowrap
> .medias > .files
margin 0 margin 0
padding 0 padding 0
background isDark ? #181b23 : lighten($theme-color, 98%) background isDark ? #181b23 : lighten($theme-color, 98%)

View File

@ -26,6 +26,22 @@
<mk-switch v-model="autoPopout" text="%i18n:@auto-popout%"> <mk-switch v-model="autoPopout" text="%i18n:@auto-popout%">
<span>%i18n:@auto-popout-desc%</span> <span>%i18n:@auto-popout-desc%</span>
</mk-switch> </mk-switch>
<section>
<header>%i18n:@note-visibility%</header>
<mk-switch v-model="$store.state.settings.rememberNoteVisibility" @change="onChangeRememberNoteVisibility" text="%i18n:@remember-note-visibility%"/>
<section>
<header>%i18n:@default-note-visibility%</header>
<ui-select v-model="defaultNoteVisibility">
<option value="public">%i18n:common.note-visibility.public%</option>
<option value="home">%i18n:common.note-visibility.home%</option>
<option value="followers">%i18n:common.note-visibility.followers%</option>
<option value="specified">%i18n:common.note-visibility.specified%</option>
<option value="private">%i18n:common.note-visibility.private%</option>
</ui-select>
</section>
</section>
<details> <details>
<summary>%i18n:@advanced%</summary> <summary>%i18n:@advanced%</summary>
<mk-switch v-model="apiViaStream" text="%i18n:@api-via-stream%"> <mk-switch v-model="apiViaStream" text="%i18n:@api-via-stream%">
@ -44,6 +60,7 @@
<button class="ui" @click="deleteWallpaper">%i18n:@delete-wallpaper%</button> <button class="ui" @click="deleteWallpaper">%i18n:@delete-wallpaper%</button>
<mk-switch v-model="darkmode" text="%i18n:@dark-mode%"/> <mk-switch v-model="darkmode" text="%i18n:@dark-mode%"/>
<mk-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons" text="%i18n:@circle-icons%"/> <mk-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons" text="%i18n:@circle-icons%"/>
<mk-switch v-model="$store.state.settings.contrastedAcct" @change="onChangeContrastedAcct" text="%i18n:@contrasted-acct%"/>
<mk-switch v-model="$store.state.settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="%i18n:@gradient-window-header%"/> <mk-switch v-model="$store.state.settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="%i18n:@gradient-window-header%"/>
<mk-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi" text="%i18n:common.i-like-sushi%"/> <mk-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi" text="%i18n:common.i-like-sushi%"/>
</div> </div>
@ -238,6 +255,11 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); } set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); }
}, },
defaultNoteVisibility: {
get() { return this.$store.state.settings.defaultNoteVisibility; },
set(value) { this.$store.commit('settings/set', { key: 'defaultNoteVisibility', value }); }
},
autoPopout: { autoPopout: {
get() { return this.$store.state.device.autoPopout; }, get() { return this.$store.state.device.autoPopout; },
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); } set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
@ -311,6 +333,12 @@ export default Vue.extend({
value: v value: v
}); });
}, },
onChangeRememberNoteVisibility(v) {
this.$store.dispatch('settings/set', {
key: 'rememberNoteVisibility',
value: v
});
},
onChangeAutoWatch(v) { onChangeAutoWatch(v) {
(this as any).api('i/update', { (this as any).api('i/update', {
autoWatch: v autoWatch: v
@ -376,6 +404,12 @@ export default Vue.extend({
value: v value: v
}); });
}, },
onChangeContrastedAcct(v) {
this.$store.dispatch('settings/set', {
key: 'contrastedAcct',
value: v
});
},
onChangeILikeSushi(v) { onChangeILikeSushi(v) {
this.$store.dispatch('settings/set', { this.$store.dispatch('settings/set', {
key: 'iLikeSushi', key: 'iLikeSushi',

View File

@ -7,9 +7,9 @@
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/> <misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RP: ...</a> <a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RP: ...</a>
</div> </div>
<details v-if="note.media.length > 0"> <details v-if="note.files.length > 0">
<summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary> <summary>({{ '%i18n:@media-count%'.replace('{}', note.files.length) }})</summary>
<mk-media-list :media-list="note.media"/> <mk-media-list :media-list="note.files"/>
</details> </details>
<details v-if="note.poll"> <details v-if="note.poll">
<summary>%i18n:@poll%</summary> <summary>%i18n:@poll%</summary>

View File

@ -0,0 +1,41 @@
<template>
<div class="jdnqwkzlnxcfftthoybjxrebyolvoucw mk-admin-card">
<header>%i18n:@hided-tags%</header>
<textarea v-model="hidedTags"></textarea>
<button class="ui" @click="save">%i18n:@save%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
hidedTags: '',
};
},
created() {
(this as any).os.getMeta().then(meta => {
this.hidedTags = meta.hidedTags.join('\n');
});
},
methods: {
save() {
(this as any).api('admin/update-meta', {
hidedTags: this.hidedTags.split('\n')
});
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
.jdnqwkzlnxcfftthoybjxrebyolvoucw
textarea
width 100%
min-height 300px
</style>

View File

@ -5,6 +5,8 @@
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li> <li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li> <li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li> <li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> --> <!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> --> <!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
</ul> </ul>
@ -17,6 +19,9 @@
<div v-show="page == 'announcements'"> <div v-show="page == 'announcements'">
<x-announcements/> <x-announcements/>
</div> </div>
<div v-show="page == 'hashtags'">
<x-hashtags/>
</div>
<div v-if="page == 'users'"> <div v-if="page == 'users'">
<x-suspend-user/> <x-suspend-user/>
<x-unsuspend-user/> <x-unsuspend-user/>
@ -33,6 +38,7 @@
import Vue from "vue"; import Vue from "vue";
import XDashboard from "./admin.dashboard.vue"; import XDashboard from "./admin.dashboard.vue";
import XAnnouncements from "./admin.announcements.vue"; import XAnnouncements from "./admin.announcements.vue";
import XHashtags from "./admin.hashtags.vue";
import XSuspendUser from "./admin.suspend-user.vue"; import XSuspendUser from "./admin.suspend-user.vue";
import XUnsuspendUser from "./admin.unsuspend-user.vue"; import XUnsuspendUser from "./admin.unsuspend-user.vue";
import XVerifyUser from "./admin.verify-user.vue"; import XVerifyUser from "./admin.verify-user.vue";
@ -43,6 +49,7 @@ export default Vue.extend({
components: { components: {
XDashboard, XDashboard,
XAnnouncements, XAnnouncements,
XHashtags,
XSuspendUser, XSuspendUser,
XUnsuspendUser, XUnsuspendUser,
XVerifyUser, XVerifyUser,

View File

@ -28,6 +28,7 @@
import Vue from 'vue'; import Vue from 'vue';
import Menu from '../../../../common/views/components/menu.vue'; import Menu from '../../../../common/views/components/menu.vue';
import contextmenu from '../../../api/contextmenu'; import contextmenu from '../../../api/contextmenu';
import { countIf } from '../../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
props: { props: {
@ -117,7 +118,7 @@ export default Vue.extend({
toggleActive() { toggleActive() {
if (!this.isStacked) return; if (!this.isStacked) return;
const vms = this.$store.state.settings.deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id)); const vms = this.$store.state.settings.deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id));
if (this.active && vms.filter(vm => vm.$el.classList.contains('active')).length == 1) return; if (this.active && countIf(vm => vm.$el.classList.contains('active'), vms) == 1) return;
this.active = !this.active; this.active = !this.active;
}, },

View File

@ -68,7 +68,7 @@ export default Vue.extend({
(this as any).api('notes/user-list-timeline', { (this as any).api('notes/user-list-timeline', {
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
mediaOnly: this.mediaOnly, withFiles: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes includeLocalRenotes: this.$store.state.settings.showLocalRenotes
@ -90,7 +90,7 @@ export default Vue.extend({
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
mediaOnly: this.mediaOnly, withFiles: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes includeLocalRenotes: this.$store.state.settings.showLocalRenotes
@ -109,7 +109,7 @@ export default Vue.extend({
return promise; return promise;
}, },
onNote(note) { onNote(note) {
if (this.mediaOnly && note.media.length == 0) return; if (this.mediaOnly && note.files.length == 0) return;
// Prepend a note // Prepend a note
(this.$refs.timeline as any).prepend(note); (this.$refs.timeline as any).prepend(note);

View File

@ -28,8 +28,8 @@
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/> <misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
<a class="rp" v-if="p.renote != null">RP:</a> <a class="rp" v-if="p.renote != null">RP:</a>
</div> </div>
<div class="media" v-if="p.media.length > 0"> <div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.media"/> <mk-media-list :media-list="p.files"/>
</div> </div>
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> <a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
@ -54,11 +54,11 @@
</article> </article>
</div> </div>
<div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi"> <div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi">
<div v-if="note.media.length > 0"> <div v-if="note.files.length > 0">
<mk-media-list :media-list="note.media"/> <mk-media-list :media-list="note.files"/>
</div> </div>
<div v-if="note.renote && note.renote.media.length > 0"> <div v-if="note.renote && note.renote.files.length > 0">
<mk-media-list :media-list="note.renote.media"/> <mk-media-list :media-list="note.renote.files"/>
</div> </div>
</div> </div>
</template> </template>
@ -100,7 +100,7 @@ export default Vue.extend({
isRenote(): boolean { isRenote(): boolean {
return (this.note.renote && return (this.note.renote &&
this.note.text == null && this.note.text == null &&
this.note.mediaIds.length == 0 && this.note.fileIds.length == 0 &&
this.note.poll == null); this.note.poll == null);
}, },
@ -371,7 +371,7 @@ root(isDark)
.mk-url-preview .mk-url-preview
margin-top 8px margin-top 8px
> .media > .files
> img > img
display block display block
max-width 100% max-width 100%

View File

@ -127,7 +127,7 @@ export default Vue.extend({
prepend(note, silent = false) { prepend(note, silent = false) {
//#region 弾く //#region 弾く
const isMyNote = note.userId == this.$store.state.i.id; const isMyNote = note.userId == this.$store.state.i.id;
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null; const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
if (this.$store.state.settings.showMyRenotes === false) { if (this.$store.state.settings.showMyRenotes === false) {
if (isMyNote && isPureRenote) { if (isMyNote && isPureRenote) {

View File

@ -96,7 +96,7 @@ export default Vue.extend({
(this.$refs.timeline as any).init(() => new Promise((res, rej) => { (this.$refs.timeline as any).init(() => new Promise((res, rej) => {
(this as any).api(this.endpoint, { (this as any).api(this.endpoint, {
limit: fetchLimit + 1, limit: fetchLimit + 1,
mediaOnly: this.mediaOnly, withFiles: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes includeLocalRenotes: this.$store.state.settings.showLocalRenotes
@ -117,7 +117,7 @@ export default Vue.extend({
const promise = (this as any).api(this.endpoint, { const promise = (this as any).api(this.endpoint, {
limit: fetchLimit + 1, limit: fetchLimit + 1,
mediaOnly: this.mediaOnly, withFiles: this.mediaOnly,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
@ -138,7 +138,7 @@ export default Vue.extend({
}, },
onNote(note) { onNote(note) {
if (this.mediaOnly && note.media.length == 0) return; if (this.mediaOnly && note.files.length == 0) return;
// Prepend a note // Prepend a note
(this.$refs.timeline as any).prepend(note); (this.$refs.timeline as any).prepend(note);

View File

@ -6,7 +6,7 @@
<div class="title"> <div class="title">
<p class="name">{{ user | userName }}</p> <p class="name">{{ user | userName }}</p>
<div> <div>
<span class="username"><mk-acct :user="user"/></span> <span class="username"><mk-acct :user="user" :detail="true" /></span>
<span v-if="user.isBot" title="%i18n:@is-bot%">%fa:robot%</span> <span v-if="user.isBot" title="%i18n:@is-bot%">%fa:robot%</span>
<span class="location" v-if="user.host === null && user.profile.location">%fa:map-marker% {{ user.profile.location }}</span> <span class="location" v-if="user.host === null && user.profile.location">%fa:map-marker% {{ user.profile.location }}</span>
<span class="birthday" v-if="user.host === null && user.profile.birthday">%fa:birthday-cake% {{ user.profile.birthday.replace('-', '').replace('-', '') + '' }} ({{ age }})</span> <span class="birthday" v-if="user.host === null && user.profile.birthday">%fa:birthday-cake% {{ user.profile.birthday.replace('-', '').replace('-', '') + '' }} ({{ age }})</span>

View File

@ -24,12 +24,12 @@ export default Vue.extend({
mounted() { mounted() {
(this as any).api('users/notes', { (this as any).api('users/notes', {
userId: this.user.id, userId: this.user.id,
withMedia: true, withFiles: true,
limit: 9 limit: 9
}).then(notes => { }).then(notes => {
notes.forEach(note => { notes.forEach(note => {
note.media.forEach(media => { note.files.forEach(file => {
if (this.images.length < 9) this.images.push(media); if (this.images.length < 9) this.images.push(file);
}); });
}); });
this.fetching = false; this.fetching = false;

View File

@ -66,7 +66,7 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined, untilDate: this.date ? this.date.getTime() : undefined,
includeReplies: this.mode == 'with-replies', includeReplies: this.mode == 'with-replies',
withMedia: this.mode == 'with-media' withFiles: this.mode == 'with-media'
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -86,7 +86,7 @@ export default Vue.extend({
userId: this.user.id, userId: this.user.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
includeReplies: this.mode == 'with-replies', includeReplies: this.mode == 'with-replies',
withMedia: this.mode == 'with-media', withFiles: this.mode == 'with-media',
untilId: (this.$refs.timeline as any).tail().id untilId: (this.$refs.timeline as any).tail().id
}); });

View File

@ -7,45 +7,128 @@
<mk-forkit class="forkit"/> <mk-forkit class="forkit"/>
<div class="body"> <main>
<div class="main block"> <div class="body">
<h1 v-if="name != 'Misskey'">{{ name }}</h1> <div class="main block">
<h1 v-else><img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" :alt="name"></h1> <div>
<h1 v-if="name != 'Misskey'">{{ name }}</h1>
<h1 v-else><img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" :alt="name"></h1>
<div class="info"> <div class="info">
<span><b>{{ host }}</b> - <span v-html="'%i18n:@powered-by-misskey%'"></span></span> <span><b>{{ host }}</b> - <span v-html="'%i18n:@powered-by-misskey%'"></span></span>
<span class="stats" v-if="stats"> <span class="stats" v-if="stats">
<span>%fa:user% {{ stats.originalUsersCount | number }}</span> <span>%fa:user% {{ stats.originalUsersCount | number }}</span>
<span>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</span> <span>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</span>
</span> </span>
</div>
<p class="desc" v-html="description || '%i18n:common.about%'"></p>
<a class="about" @click="about">%i18n:@about%</a>
<p class="sign">
<span class="signup" @click="signup">%i18n:@signup%</span>
<span class="divider">|</span>
<span class="signin" @click="signin">%i18n:@signin%</span>
</p>
<img src="/assets/pointer.png" alt="" class="char">
</div>
</div> </div>
<p class="desc" v-html="description || '%i18n:common.about%'"></p> <div class="announcements block">
<header>%fa:broadcast-tower% %i18n:@announcements%</header>
<div v-if="announcements && announcements.length > 0">
<div v-for="announcement in announcements">
<h1 v-html="announcement.title"></h1>
<div v-html="announcement.text"></div>
</div>
</div>
</div>
<p class="sign"> <div class="photos block">
<span class="signup" @click="signup">%i18n:@signup%</span> <header>%fa:images% %i18n:@photos%</header>
<span class="divider">|</span> <div>
<span class="signin" @click="signin">%i18n:@signin%</span> <div v-for="photo in photos" :style="`background-image: url(${photo.thumbnailUrl})`"></div>
</p> </div>
</div> </div>
<div class="broadcasts block"> <div class="tag-cloud block">
<div v-for="broadcast in broadcasts"> <div>
<h1 v-html="broadcast.title"></h1> <mk-tag-cloud/>
<div v-html="broadcast.text"></div> </div>
</div>
<div class="nav block">
<div>
<mk-nav class="nav"/>
</div>
</div>
<div class="side">
<div class="trends block">
<div>
<mk-trends/>
</div>
</div>
<div class="tl block">
<header>%fa:comment-alt R% %i18n:@timeline%</header>
<div>
<mk-welcome-timeline class="tl" :max="20"/>
</div>
</div>
<div class="info block">
<header>%fa:info-circle% %i18n:@info%</header>
<div>
<div v-if="meta" class="body">
<p>Version: <b>{{ meta.version }}</b></p>
<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
</div>
</div>
</div>
</div> </div>
</div> </div>
</main>
<div class="nav block"> <modal name="about" :class="$store.state.device.darkmode ? ['about', 'modal-dark'] : ['about', 'modal-light']" width="800px" height="auto" scrollable>
<mk-nav class="nav"/> <article class="fpdezooorhntlzyeszemrsqdlgbysvxq">
</div> <h1>%i18n:common.intro.title%</h1>
<p v-html="'%i18n:common.intro.about%'"></p>
<div class="side"> <section>
<mk-trends class="trends block"/> <h2>%i18n:common.intro.features%</h2>
<section>
<mk-welcome-timeline class="tl block" :max="20"/> <div class="body">
</div> <h3>%i18n:common.intro.rich-contents%</h3>
</div> <p v-html="'%i18n:common.intro.rich-contents-desc%'"></p>
</div>
<div class="image"><img src="/assets/about/post.png" alt=""></div>
</section>
<section>
<div class="body">
<h3>%i18n:common.intro.reaction%</h3>
<p v-html="'%i18n:common.intro.reaction-desc%'"></p>
</div>
<div class="image"><img src="/assets/about/reaction.png" alt=""></div>
</section>
<section>
<div class="body">
<h3>%i18n:common.intro.ui%</h3>
<p v-html="'%i18n:common.intro.ui-desc%'"></p>
</div>
<div class="image"><img src="/assets/about/ui.png" alt=""></div>
</section>
<section>
<div class="body">
<h3>%i18n:common.intro.drive%</h3>
<p v-html="'%i18n:common.intro.drive-desc%'"></p>
</div>
<div class="image"><img src="/assets/about/drive.png" alt=""></div>
</section>
</section>
<p v-html="'%i18n:common.intro.outro%'"></p>
</article>
</modal>
<modal name="signup" :class="$store.state.device.darkmode ? 'modal-dark' : 'modal-light'" width="450px" height="auto" scrollable> <modal name="signup" :class="$store.state.device.darkmode ? 'modal-dark' : 'modal-light'" width="450px" height="auto" scrollable>
<header class="formHeader">%i18n:@signup%</header> <header class="formHeader">%i18n:@signup%</header>
@ -62,37 +145,62 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { host, copyright } from '../../../config'; import { host, copyright } from '../../../config';
import { concat } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
data() { data() {
return { return {
meta: null,
stats: null, stats: null,
copyright, copyright,
host, host,
name: 'Misskey', name: 'Misskey',
description: '', description: '',
broadcasts: [] announcements: [],
photos: []
}; };
}, },
created() { created() {
(this as any).os.getMeta().then(meta => { (this as any).os.getMeta().then(meta => {
this.meta = meta;
this.name = meta.name; this.name = meta.name;
this.description = meta.description; this.description = meta.description;
this.broadcasts = meta.broadcasts; this.announcements = meta.broadcasts;
}); });
(this as any).api('stats').then(stats => { (this as any).api('stats').then(stats => {
this.stats = stats; this.stats = stats;
}); });
const image = [
'image/jpeg',
'image/png',
'image/gif'
];
(this as any).api('notes/local-timeline', {
fileType: image,
limit: 6
}).then((notes: any[]) => {
const files = concat(notes.map((n: any): any[] => n.files));
this.photos = files.filter(f => image.includes(f.type)).slice(0, 6);
});
}, },
methods: { methods: {
about() {
this.$modal.show('about');
},
signup() { signup() {
this.$modal.show('signup'); this.$modal.show('signup');
}, },
signin() { signin() {
this.$modal.show('signin'); this.$modal.show('signin');
}, },
dark() { dark() {
this.$store.commit('device/set', { this.$store.commit('device/set', {
key: 'darkmode', key: 'darkmode',
@ -137,6 +245,54 @@ export default Vue.extend({
margin 0 48px margin 0 48px
font-size 1.5em font-size 1.5em
.v--modal-overlay.about
.v--modal-box.v--modal
margin 32px 0
.fpdezooorhntlzyeszemrsqdlgbysvxq
padding 64px
> p:last-child
margin-bottom 0
> h1
margin-top 0
> section
> h2
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
> section
display grid
grid-template-rows 1fr
grid-template-columns 180px 1fr
gap 32px
margin-bottom 32px
padding-bottom 32px
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
&:nth-child(odd)
grid-template-columns 1fr 180px
> .body
grid-column 1
> .image
grid-column 2
> .body
grid-row 1
grid-column 2
> .image
grid-row 1
grid-column 1
> img
display block
width 100%
height 100%
object-fit cover
</style> </style>
<style lang="stylus" scoped> <style lang="stylus" scoped>
@ -164,116 +320,172 @@ root(isDark)
font-size 18px font-size 18px
color isDark ? #fff : #444 color isDark ? #fff : #444
> .body > main
display grid
grid-template-rows 0.5fr 0.5fr 64px
grid-template-columns 1fr 350px
gap 16px
width 100%
max-width 1200px
height 100vh
min-height 800px
margin 0 auto margin 0 auto
padding 64px padding 64px
width 100%
max-width 1200px
.block .block
color isDark ? #fff : #444 color isDark ? #fff : #444
background isDark ? #313543 : #fff background isDark ? #282C37 : #fff
box-shadow 0 3px 8px rgba(0, 0, 0, 0.2) box-shadow 0 3px 8px rgba(0, 0, 0, 0.2)
//border-radius 8px //border-radius 8px
overflow auto overflow auto
> .main > header
grid-row 1 z-index 1
grid-column 1 padding 0 16px
padding 32px line-height 48px
border-top solid 5px $theme-color background isDark ? #313543 : #fff
> h1 if !isDark
margin 0 box-shadow 0 1px 0px rgba(0, 0, 0, 0.1)
> img & + div
margin -8px 0 0 -16px max-height calc(100% - 48px)
max-width 280px
> .info
margin 0 auto 16px auto
width $width
font-size 14px
> .stats
margin-left 16px
padding-left 16px
border-left solid 1px isDark ? #fff : #444
> *
margin-right 16px
> .sign
font-size 120%
> .divider
margin 0 16px
> .signin
> .signup
cursor pointer
&:hover
color $theme-color
> .hashtags
margin 16px auto
width $width
font-size 14px
background rgba(#000, 0.3)
border-radius 8px
> *
display inline-block
margin 14px
> .broadcasts
grid-row 2
grid-column 1
padding 32px
> div > div
padding 0 0 16px 0
margin 0 0 16px 0
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
> h1
margin 0
font-size 1.5em
> .nav
display flex
justify-content center
align-items center
grid-row 3
grid-column 1
font-size 14px
> .side
display grid
grid-row 1 / 4
grid-column 2
grid-template-rows 1fr 350px
grid-template-columns 1fr
gap 16px
> .tl
grid-row 1
grid-column 1
text-align left
max-height 100%
overflow auto overflow auto
> .trends > .body
display grid
grid-template-rows 1fr 1fr 256px 64px
grid-template-columns 1fr 1fr 350px
gap 16px
height 1200px
> .main
grid-row 1
grid-column 1 / 3
border-top solid 5px $theme-color
> div
padding 32px
min-height 100%
> h1
margin 0
> img
margin -8px 0 0 -16px
max-width 280px
> .info
margin 0 auto 16px auto
width $width
font-size 14px
> .stats
margin-left 16px
padding-left 16px
border-left solid 1px isDark ? #fff : #444
> *
margin-right 16px
> .sign
font-size 120%
> .divider
margin 0 16px
> .signin
> .signup
cursor pointer
&:hover
color $theme-color
> .char
display block
position absolute
right 16px
bottom 16px
width 180px
opacity 0.3
> *:not(.char)
z-index 1
> .announcements
grid-row 2 grid-row 2
grid-column 1 grid-column 1
padding 8px
> div
padding 32px
> div
padding 0 0 16px 0
margin 0 0 16px 0
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
> h1
margin 0
font-size 1.25em
> .photos
grid-row 2
grid-column 2
> div
display grid
grid-template-rows 1fr 1fr 1fr
grid-template-columns 1fr 1fr
gap 8px
height 100%
padding 16px
> div
//border-radius 4px
background-position center center
background-size cover
> .tag-cloud
grid-row 3
grid-column 1 / 3
> div
height 256px
padding 32px
> .nav
display flex
justify-content center
align-items center
grid-row 4
grid-column 1 / 3
font-size 14px
> .side
display grid
grid-row 1 / 5
grid-column 3
grid-template-rows 1fr 350px
grid-template-columns 1fr
gap 16px
> .tl
grid-row 1
grid-column 1
overflow auto
> .trends
grid-row 2
grid-column 1
padding 8px
> .info
grid-row 3
grid-column 1
> div
padding 16px
> .body
> p
display block
margin 0
.mk-welcome[data-darkmode] .mk-welcome[data-darkmode]
root(true) root(true)

View File

@ -49,7 +49,7 @@ export default define({
offset: this.offset, offset: this.offset,
renote: false, renote: false,
reply: false, reply: false,
media: false, file: false,
poll: false poll: false
}).then(notes => { }).then(notes => {
const note = notes ? notes[0] : null; const note = notes ? notes[0] : null;

View File

@ -17,6 +17,7 @@ import Err from './common/views/components/connect-failed.vue';
import { LocalTimelineStreamManager } from './common/scripts/streaming/local-timeline'; import { LocalTimelineStreamManager } from './common/scripts/streaming/local-timeline';
import { HybridTimelineStreamManager } from './common/scripts/streaming/hybrid-timeline'; import { HybridTimelineStreamManager } from './common/scripts/streaming/hybrid-timeline';
import { GlobalTimelineStreamManager } from './common/scripts/streaming/global-timeline'; import { GlobalTimelineStreamManager } from './common/scripts/streaming/global-timeline';
import { erase } from '../../prelude/array';
//#region api requests //#region api requests
let spinner = null; let spinner = null;
@ -537,7 +538,7 @@ export default class MiOS extends EventEmitter {
} }
public unregisterStreamConnection(connection: Connection) { public unregisterStreamConnection(connection: Connection) {
this.connections = this.connections.filter(c => c != connection); this.connections = erase(connection, this.connections);
} }
} }

View File

@ -67,7 +67,7 @@
import Vue from 'vue'; import Vue from 'vue';
import * as EXIF from 'exif-js'; import * as EXIF from 'exif-js';
import * as hljs from 'highlight.js'; import * as hljs from 'highlight.js';
import gcd from '../../../common/scripts/gcd'; import { gcd } from '../../../../../prelude/math';
export default Vue.extend({ export default Vue.extend({
props: ['file'], props: ['file'],

View File

@ -48,12 +48,14 @@ export default Vue.extend({
onFollow(user) { onFollow(user) {
if (user.id == this.u.id) { if (user.id == this.u.id) {
this.u.isFollowing = user.isFollowing; this.u.isFollowing = user.isFollowing;
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
} }
}, },
onUnfollow(user) { onUnfollow(user) {
if (user.id == this.u.id) { if (user.id == this.u.id) {
this.u.isFollowing = user.isFollowing; this.u.isFollowing = user.isFollowing;
this.u.hasPendingFollowRequestFromYou = user.hasPendingFollowRequestFromYou;
} }
}, },
@ -66,7 +68,7 @@ export default Vue.extend({
userId: this.u.id userId: this.u.id
}); });
} else { } else {
if (this.u.isLocked && this.u.hasPendingFollowRequestFromYou) { if (this.u.hasPendingFollowRequestFromYou) {
this.u = await (this as any).api('following/requests/cancel', { this.u = await (this as any).api('following/requests/cancel', {
userId: this.u.id userId: this.u.id
}); });

View File

@ -40,8 +40,8 @@
<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span> <span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/> <misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
</div> </div>
<div class="media" v-if="p.media.length > 0"> <div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.media" :raw="true"/> <mk-media-list :media-list="p.files" :raw="true"/>
</div> </div>
<mk-poll v-if="p.poll" :note="p"/> <mk-poll v-if="p.poll" :note="p"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> <mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
@ -85,6 +85,7 @@ import parse from '../../../../../mfm/parse';
import MkNoteMenu from '../../../common/views/components/note-menu.vue'; import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue'; import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './note.sub.vue'; import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@ -113,7 +114,7 @@ export default Vue.extend({
isRenote(): boolean { isRenote(): boolean {
return (this.note.renote && return (this.note.renote &&
this.note.text == null && this.note.text == null &&
this.note.mediaIds.length == 0 && this.note.fileIds.length == 0 &&
this.note.poll == null); this.note.poll == null);
}, },
@ -123,9 +124,7 @@ export default Vue.extend({
reactionsCount(): number { reactionsCount(): number {
return this.p.reactionCounts return this.p.reactionCounts
? Object.keys(this.p.reactionCounts) ? sum(Object.values(this.p.reactionCounts))
.map(key => this.p.reactionCounts[key])
.reduce((a, b) => a + b)
: 0; : 0;
}, },
@ -369,7 +368,7 @@ root(isDark)
> .mk-url-preview > .mk-url-preview
margin-top 8px margin-top 8px
> .media > .files
> img > img
display block display block
max-width 100% max-width 100%

View File

@ -28,8 +28,8 @@
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/> <misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
<a class="rp" v-if="p.renote != null">RP:</a> <a class="rp" v-if="p.renote != null">RP:</a>
</div> </div>
<div class="media" v-if="p.media.length > 0"> <div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.media"/> <mk-media-list :media-list="p.files"/>
</div> </div>
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url"/> <mk-url-preview v-for="url in urls" :url="url" :key="url"/>
@ -70,6 +70,7 @@ import parse from '../../../../../mfm/parse';
import MkNoteMenu from '../../../common/views/components/note-menu.vue'; import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue'; import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './note.sub.vue'; import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@ -90,7 +91,7 @@ export default Vue.extend({
isRenote(): boolean { isRenote(): boolean {
return (this.note.renote && return (this.note.renote &&
this.note.text == null && this.note.text == null &&
this.note.mediaIds.length == 0 && this.note.fileIds.length == 0 &&
this.note.poll == null); this.note.poll == null);
}, },
@ -100,9 +101,7 @@ export default Vue.extend({
reactionsCount(): number { reactionsCount(): number {
return this.p.reactionCounts return this.p.reactionCounts
? Object.keys(this.p.reactionCounts) ? sum(Object.values(this.p.reactionCounts))
.map(key => this.p.reactionCounts[key])
.reduce((a, b) => a + b)
: 0; : 0;
}, },
@ -414,7 +413,7 @@ root(isDark)
.mk-url-preview .mk-url-preview
margin-top 8px margin-top 8px
> .media > .files
> img > img
display block display block
max-width 100% max-width 100%

View File

@ -125,7 +125,7 @@ export default Vue.extend({
prepend(note, silent = false) { prepend(note, silent = false) {
//#region 弾く //#region 弾く
const isMyNote = note.userId == this.$store.state.i.id; const isMyNote = note.userId == this.$store.state.i.id;
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null; const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
if (this.$store.state.settings.showMyRenotes === false) { if (this.$store.state.settings.showMyRenotes === false) {
if (isMyNote && isPureRenote) { if (isMyNote && isPureRenote) {

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mk-notify"> <div class="mk-notify" :class="pos">
<div> <div>
<mk-notification-preview :notification="notification"/> <mk-notification-preview :notification="notification"/>
</div> </div>
@ -12,11 +12,16 @@ import * as anime from 'animejs';
export default Vue.extend({ export default Vue.extend({
props: ['notification'], props: ['notification'],
computed: {
pos() {
return this.$store.state.device.mobileNotificationPosition;
}
},
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
anime({ anime({
targets: this.$el, targets: this.$el,
bottom: '0px', [this.pos]: '0px',
duration: 500, duration: 500,
easing: 'easeOutQuad' easing: 'easeOutQuad'
}); });
@ -24,7 +29,7 @@ export default Vue.extend({
setTimeout(() => { setTimeout(() => {
anime({ anime({
targets: this.$el, targets: this.$el,
bottom: '-72px', [this.pos]: `-${this.$el.offsetHeight}px`,
duration: 500, duration: 500,
easing: 'easeOutQuad', easing: 'easeOutQuad',
complete: () => this.$destroy() complete: () => this.$destroy()
@ -37,24 +42,32 @@ export default Vue.extend({
<style lang="stylus" scoped> <style lang="stylus" scoped>
.mk-notify .mk-notify
$height = 78px
position fixed position fixed
z-index 1024 z-index 1024
bottom -72px
left 0 left 0
right 0 right 0
width 100% width 100%
max-width 500px max-width 500px
height 72px height $height
margin 0 auto margin 0 auto
padding 8px padding 8px
pointer-events none pointer-events none
font-size 80% font-size 80%
&.bottom
bottom -($height)
&.top
top -($height)
> div > div
height 100% height 100%
-webkit-backdrop-filter blur(2px) -webkit-backdrop-filter blur(2px)
backdrop-filter blur(2px) backdrop-filter blur(2px)
background-color rgba(#000, 0.5) background-color rgba(#000, 0.5)
border-radius 6px border-radius 7px
overflow hidden
</style> </style>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="ulveipglmagnxfgvitaxyszerjwiqmwl"> <div class="ulveipglmagnxfgvitaxyszerjwiqmwl">
<div class="bg" ref="bg" @click="onBgClick"></div> <div class="bg" ref="bg"></div>
<div class="main" ref="main" @click.self="onBgClick"> <div class="main" ref="main">
<mk-post-form ref="form" <mk-post-form ref="form"
:reply="reply" :reply="reply"
:renote="renote" :renote="renote"
@ -83,11 +83,6 @@ export default Vue.extend({
}); });
}, },
onBgClick() {
this.$emit('cancel');
this.close();
},
onPosted() { onPosted() {
this.$emit('posted'); this.$emit('posted');
this.close(); this.close();

View File

@ -59,6 +59,7 @@ import MkVisibilityChooser from '../../../common/views/components/visibility-cho
import getFace from '../../../common/scripts/get-face'; import getFace from '../../../common/scripts/get-face';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import { host } from '../../../config'; import { host } from '../../../config';
import { erase } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@ -94,7 +95,7 @@ export default Vue.extend({
files: [], files: [],
poll: false, poll: false,
geo: null, geo: null,
visibility: this.$store.state.device.visibility || 'public', visibility: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility,
visibleUsers: [], visibleUsers: [],
useCw: false, useCw: false,
cw: null, cw: null,
@ -200,12 +201,12 @@ export default Vue.extend({
attachMedia(driveFile) { attachMedia(driveFile) {
this.files.push(driveFile); this.files.push(driveFile);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
}, },
detachMedia(file) { detachMedia(file) {
this.files = this.files.filter(x => x.id != file.id); this.files = this.files.filter(x => x.id != file.id);
this.$emit('change-attached-media', this.files); this.$emit('change-attached-files', this.files);
}, },
onChangeFile() { onChangeFile() {
@ -262,14 +263,14 @@ export default Vue.extend({
}, },
removeVisibleUser(user) { removeVisibleUser(user) {
this.visibleUsers = this.visibleUsers.filter(u => u != user); this.visibleUsers = erase(user, this.visibleUsers);
}, },
clear() { clear() {
this.text = ''; this.text = '';
this.files = []; this.files = [];
this.poll = false; this.poll = false;
this.$emit('change-attached-media'); this.$emit('change-attached-files');
}, },
post() { post() {
@ -277,7 +278,7 @@ export default Vue.extend({
const viaMobile = this.$store.state.settings.disableViaMobile !== true; const viaMobile = this.$store.state.settings.disableViaMobile !== true;
(this as any).api('notes/create', { (this as any).api('notes/create', {
text: this.text == '' ? undefined : this.text, text: this.text == '' ? undefined : this.text,
mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined, fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
replyId: this.reply ? this.reply.id : undefined, replyId: this.reply ? this.reply.id : undefined,
renoteId: this.renote ? this.renote.id : undefined, renoteId: this.renote ? this.renote.id : undefined,
poll: this.poll ? (this.$refs.poll as any).get() : undefined, poll: this.poll ? (this.$refs.poll as any).get() : undefined,

View File

@ -7,9 +7,9 @@
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/> <misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
<a class="rp" v-if="note.renoteId">RP: ...</a> <a class="rp" v-if="note.renoteId">RP: ...</a>
</div> </div>
<details v-if="note.media.length > 0"> <details v-if="note.files.length > 0">
<summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary> <summary>({{ '%i18n:@media-count%'.replace('{}', note.files.length) }})</summary>
<mk-media-list :media-list="note.media"/> <mk-media-list :media-list="note.files"/>
</details> </details>
<details v-if="note.poll"> <details v-if="note.poll">
<summary>%i18n:@poll%</summary> <summary>%i18n:@poll%</summary>

View File

@ -34,6 +34,12 @@
<li @click="dark"><p><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template><span>%i18n:@darkmode%</span></p></li> <li @click="dark"><p><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template><span>%i18n:@darkmode%</span></p></li>
</ul> </ul>
</div> </div>
<div class="announcements" v-if="announcements && announcements.length > 0">
<article v-for="announcement in announcements">
<span v-html="announcement.title" class="title"></span>
<div v-html="announcement.text"></div>
</article>
</div>
<a :href="aboutUrl"><p class="about">%i18n:@about%</p></a> <a :href="aboutUrl"><p class="about">%i18n:@about%</p></a>
</div> </div>
</transition> </transition>
@ -46,23 +52,32 @@ import { lang } from '../../../config';
export default Vue.extend({ export default Vue.extend({
props: ['isOpen'], props: ['isOpen'],
data() { data() {
return { return {
hasGameInvitation: false, hasGameInvitation: false,
connection: null, connection: null,
connectionId: null, connectionId: null,
aboutUrl: `/docs/${lang}/about` aboutUrl: `/docs/${lang}/about`,
announcements: []
}; };
}, },
computed: { computed: {
hasUnreadNotification(): boolean { hasUnreadNotification(): boolean {
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification; return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification;
}, },
hasUnreadMessagingMessage(): boolean { hasUnreadMessagingMessage(): boolean {
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage; return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
} }
}, },
mounted() { mounted() {
(this as any).os.getMeta().then(meta => {
this.announcements = meta.broadcasts;
});
if (this.$store.getters.isSignedIn) { if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.getConnection(); this.connection = (this as any).os.stream.getConnection();
this.connectionId = (this as any).os.stream.use(); this.connectionId = (this as any).os.stream.use();
@ -71,6 +86,7 @@ export default Vue.extend({
this.connection.on('reversi_no_invites', this.onReversiNoInvites); this.connection.on('reversi_no_invites', this.onReversiNoInvites);
} }
}, },
beforeDestroy() { beforeDestroy() {
if (this.$store.getters.isSignedIn) { if (this.$store.getters.isSignedIn) {
this.connection.off('reversi_invited', this.onReversiInvited); this.connection.off('reversi_invited', this.onReversiInvited);
@ -78,18 +94,22 @@ export default Vue.extend({
(this as any).os.stream.dispose(this.connectionId); (this as any).os.stream.dispose(this.connectionId);
} }
}, },
methods: { methods: {
search() { search() {
const query = window.prompt('%i18n:@search%'); const query = window.prompt('%i18n:@search%');
if (query == null || query == '') return; if (query == null || query == '') return;
this.$router.push(`/search?q=${encodeURIComponent(query)}`); this.$router.push(`/search?q=${encodeURIComponent(query)}`);
}, },
onReversiInvited() { onReversiInvited() {
this.hasGameInvitation = true; this.hasGameInvitation = true;
}, },
onReversiNoInvites() { onReversiNoInvites() {
this.hasGameInvitation = false; this.hasGameInvitation = false;
}, },
dark() { dark() {
this.$store.commit('device/set', { this.$store.commit('device/set', {
key: 'darkmode', key: 'darkmode',
@ -204,6 +224,17 @@ root(isDark)
color $color color $color
opacity 0.5 opacity 0.5
.announcements
> article
background isDark ? rgba(30, 129, 216, 0.2) : rgba(155, 196, 232, 0.2)
color isDark ? #fff : #3f4967
padding 16px
margin 8px 0
font-size 12px
> .title
font-weight bold
.about .about
margin 0 0 8px 0 margin 0 0 8px 0
padding 1em 0 padding 1em 0

View File

@ -41,7 +41,7 @@ export default Vue.extend({
(this.$refs.timeline as any).init(() => new Promise((res, rej) => { (this.$refs.timeline as any).init(() => new Promise((res, rej) => {
(this as any).api('users/notes', { (this as any).api('users/notes', {
userId: this.user.id, userId: this.user.id,
withMedia: this.withMedia, withFiles: this.withMedia,
limit: fetchLimit + 1 limit: fetchLimit + 1
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
@ -62,7 +62,7 @@ export default Vue.extend({
const promise = (this as any).api('users/notes', { const promise = (this as any).api('users/notes', {
userId: this.user.id, userId: this.user.id,
withMedia: this.withMedia, withFiles: this.withMedia,
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id untilId: (this.$refs.timeline as any).tail().id
}); });

View File

@ -10,80 +10,117 @@
<ui-card> <ui-card>
<div slot="title">%fa:palette% %i18n:@design%</div> <div slot="title">%fa:palette% %i18n:@design%</div>
<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch> <section>
<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch> <ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
<ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch> <ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
<ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch> <ui-switch v-model="$store.state.settings.contrastedAcct" @change="onChangeContrastedAcct">%i18n:@contrasted-acct%</ui-switch>
<ui-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch> <ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch>
<ui-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones">%i18n:common.use-contrast-reversi-stones%</ui-switch> <ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
<ui-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
<ui-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
</section>
<div> <section>
<div>%i18n:@timeline%</div> <header>%i18n:@timeline%</header>
<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch> <div>
<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch> <ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch> <ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
<ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch> <ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
</div> <ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
</div>
</section>
<div> <section>
<div>%i18n:@post-style%</div> <header>%i18n:@post-style%</header>
<ui-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</ui-radio> <ui-radio v-model="postStyle" value="standard">%i18n:@post-style-standard%</ui-radio>
<ui-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</ui-radio> <ui-radio v-model="postStyle" value="smart">%i18n:@post-style-smart%</ui-radio>
</div> </section>
<section>
<header>%i18n:@notification-position%</header>
<ui-radio v-model="mobileNotificationPosition" value="bottom">%i18n:@notification-position-bottom%</ui-radio>
<ui-radio v-model="mobileNotificationPosition" value="top">%i18n:@notification-position-top%</ui-radio>
</section>
</ui-card> </ui-card>
<ui-card> <ui-card>
<div slot="title">%fa:cog% %i18n:@behavior%</div> <div slot="title">%fa:cog% %i18n:@behavior%</div>
<ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
<ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch> <section>
<ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch> <ui-switch v-model="$store.state.settings.fetchOnScroll" @change="onChangeFetchOnScroll">%i18n:@fetch-on-scroll%</ui-switch>
<ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch> <ui-switch v-model="$store.state.settings.disableViaMobile" @change="onChangeDisableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch> <ui-switch v-model="loadRawImages">%i18n:@load-raw-images%</ui-switch>
<ui-switch v-model="$store.state.settings.loadRemoteMedia" @change="onChangeLoadRemoteMedia">%i18n:@load-remote-media%</ui-switch>
<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch>
</section>
<section>
<header>%i18n:@note-visibility%</header>
<ui-switch v-model="$store.state.settings.rememberNoteVisibility" @change="onChangeRememberNoteVisibility">%i18n:@remember-note-visibility%</ui-switch>
<section>
<header>%i18n:@default-note-visibility%</header>
<ui-select v-model="defaultNoteVisibility">
<option value="public">%i18n:common.note-visibility.public%</option>
<option value="home">%i18n:common.note-visibility.home%</option>
<option value="followers">%i18n:common.note-visibility.followers%</option>
<option value="specified">%i18n:common.note-visibility.specified%</option>
<option value="private">%i18n:common.note-visibility.private%</option>
</ui-select>
</section>
</section>
</ui-card> </ui-card>
<ui-card> <ui-card>
<div slot="title">%fa:volume-up% %i18n:@sound%</div> <div slot="title">%fa:volume-up% %i18n:@sound%</div>
<ui-switch v-model="enableSounds">%i18n:@enable-sounds%</ui-switch> <section>
<ui-switch v-model="enableSounds">%i18n:@enable-sounds%</ui-switch>
</section>
</ui-card> </ui-card>
<ui-card> <ui-card>
<div slot="title">%fa:language% %i18n:@lang%</div> <div slot="title">%fa:language% %i18n:@lang%</div>
<ui-select v-model="lang" placeholder="%i18n:@auto%"> <section class="fit-top">
<optgroup label="%i18n:@recommended%"> <ui-select v-model="lang" placeholder="%i18n:@auto%">
<option value="">%i18n:@auto%</option> <optgroup label="%i18n:@recommended%">
</optgroup> <option value="">%i18n:@auto%</option>
</optgroup>
<optgroup label="%i18n:@specify-language%"> <optgroup label="%i18n:@specify-language%">
<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option> <option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
</optgroup> </optgroup>
</ui-select> </ui-select>
<span>%fa:info-circle% %i18n:@lang-tip%</span> <span>%fa:info-circle% %i18n:@lang-tip%</span>
</section>
</ui-card> </ui-card>
<ui-card> <ui-card>
<div slot="title">%fa:B twitter% %i18n:@twitter%</div> <div slot="title">%fa:B twitter% %i18n:@twitter%</div>
<p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p> <section>
<p> <p class="account" v-if="$store.state.i.twitter"><a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
<a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a> <p>
<span v-if="$store.state.i.twitter"> or </span> <a :href="`${apiUrl}/connect/twitter`" target="_blank">{{ $store.state.i.twitter ? '%i18n:@twitter-reconnect%' : '%i18n:@twitter-connect%' }}</a>
<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a> <span v-if="$store.state.i.twitter"> or </span>
</p> <a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="$store.state.i.twitter">%i18n:@twitter-disconnect%</a>
</p>
</section>
</ui-card> </ui-card>
<ui-card> <ui-card>
<div slot="title">%fa:sync-alt% %i18n:@update%</div> <div slot="title">%fa:sync-alt% %i18n:@update%</div>
<div>%i18n:@version% <i>{{ version }}</i></div> <section>
<template v-if="latestVersion !== undefined"> <div>%i18n:@version% <i>{{ version }}</i></div>
<div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div> <template v-if="latestVersion !== undefined">
</template> <div>%i18n:@latest-version% <i>{{ latestVersion ? latestVersion : version }}</i></div>
<ui-button @click="checkForUpdate" :disabled="checkingForUpdate"> </template>
<template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template> <ui-button @click="checkForUpdate" :disabled="checkingForUpdate">
<template v-else>%i18n:@check-for-updates%</template> <template v-if="checkingForUpdate">%i18n:@update-checking%<mk-ellipsis/></template>
</ui-button> <template v-else>%i18n:@check-for-updates%</template>
</ui-button>
</section>
</ui-card> </ui-card>
</div> </div>
@ -134,6 +171,16 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'postStyle', value }); } set(value) { this.$store.commit('device/set', { key: 'postStyle', value }); }
}, },
mobileNotificationPosition: {
get() { return this.$store.state.device.mobileNotificationPosition; },
set(value) { this.$store.commit('device/set', { key: 'mobileNotificationPosition', value }); }
},
defaultNoteVisibility: {
get() { return this.$store.state.settings.defaultNoteVisibility; },
set(value) { this.$store.commit('settings/set', { key: 'defaultNoteVisibility', value }); }
},
lightmode: { lightmode: {
get() { return this.$store.state.device.lightmode; }, get() { return this.$store.state.device.lightmode; },
set(value) { this.$store.commit('device/set', { key: 'lightmode', value }); } set(value) { this.$store.commit('device/set', { key: 'lightmode', value }); }
@ -171,6 +218,13 @@ export default Vue.extend({
}); });
}, },
onChangeRememberNoteVisibility(v) {
this.$store.dispatch('settings/set', {
key: 'rememberNoteVisibility',
value: v
});
},
onChangeDisableViaMobile(v) { onChangeDisableViaMobile(v) {
this.$store.dispatch('settings/set', { this.$store.dispatch('settings/set', {
key: 'disableViaMobile', key: 'disableViaMobile',
@ -192,6 +246,13 @@ export default Vue.extend({
}); });
}, },
onChangeContrastedAcct(v) {
this.$store.dispatch('settings/set', {
key: 'contrastedAcct',
value: v
});
},
onChangeILikeSushi(v) { onChangeILikeSushi(v) {
this.$store.dispatch('settings/set', { this.$store.dispatch('settings/set', {
key: 'iLikeSushi', key: 'iLikeSushi',
@ -273,7 +334,7 @@ export default Vue.extend({
<style lang="stylus" scoped> <style lang="stylus" scoped>
root(isDark) root(isDark)
margin 0 auto margin 0 auto
max-width 500px max-width 600px
width 100% width 100%
> .signin-as > .signin-as

View File

@ -2,47 +2,49 @@
<ui-card> <ui-card>
<div slot="title">%fa:user% %i18n:@title%</div> <div slot="title">%fa:user% %i18n:@title%</div>
<ui-form :disabled="saving"> <section class="fit-top">
<ui-input v-model="name" :max="30"> <ui-form :disabled="saving">
<span>%i18n:@name%</span> <ui-input v-model="name" :max="30">
</ui-input> <span>%i18n:@name%</span>
</ui-input>
<ui-input v-model="username" readonly> <ui-input v-model="username" readonly>
<span>%i18n:@account%</span> <span>%i18n:@account%</span>
<span slot="prefix">@</span> <span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span> <span slot="suffix">@{{ host }}</span>
</ui-input> </ui-input>
<ui-input v-model="location"> <ui-input v-model="location">
<span>%i18n:@location%</span> <span>%i18n:@location%</span>
<span slot="prefix">%fa:map-marker-alt%</span> <span slot="prefix">%fa:map-marker-alt%</span>
</ui-input> </ui-input>
<ui-input v-model="birthday" type="date"> <ui-input v-model="birthday" type="date">
<span>%i18n:@birthday%</span> <span>%i18n:@birthday%</span>
<span slot="prefix">%fa:birthday-cake%</span> <span slot="prefix">%fa:birthday-cake%</span>
</ui-input> </ui-input>
<ui-textarea v-model="description" :max="500"> <ui-textarea v-model="description" :max="500">
<span>%i18n:@description%</span> <span>%i18n:@description%</span>
</ui-textarea> </ui-textarea>
<ui-input type="file" @change="onAvatarChange"> <ui-input type="file" @change="onAvatarChange">
<span>%i18n:@avatar%</span> <span>%i18n:@avatar%</span>
<span slot="icon">%fa:image%</span> <span slot="icon">%fa:image%</span>
<span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span> <span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
</ui-input> </ui-input>
<ui-input type="file" @change="onBannerChange"> <ui-input type="file" @change="onBannerChange">
<span>%i18n:@banner%</span> <span>%i18n:@banner%</span>
<span slot="icon">%fa:image%</span> <span slot="icon">%fa:image%</span>
<span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span> <span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
</ui-input> </ui-input>
<ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch> <ui-switch v-model="isCat">%i18n:@is-cat%</ui-switch>
<ui-button @click="save">%i18n:@save%</ui-button> <ui-button @click="save">%i18n:@save%</ui-button>
</ui-form> </ui-form>
</section>
</ui-card> </ui-card>
</template> </template>

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="title"> <div class="title">
<h1>{{ user | userName }}</h1> <h1>{{ user | userName }}</h1>
<span class="username"><mk-acct :user="user"/></span> <span class="username"><mk-acct :user="user" :detail="true" /></span>
<span class="followed" v-if="user.isFollowed">%i18n:@follows-you%</span> <span class="followed" v-if="user.isFollowed">%i18n:@follows-you%</span>
</div> </div>
<div class="description"> <div class="description">

View File

@ -26,7 +26,7 @@ export default Vue.extend({
mounted() { mounted() {
(this as any).api('users/notes', { (this as any).api('users/notes', {
userId: this.user.id, userId: this.user.id,
withMedia: true, withFiles: true,
limit: 6 limit: 6
}).then(notes => { }).then(notes => {
notes.forEach(note => { notes.forEach(note => {

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="welcome"> <div class="wgwfgvvimdjvhjfwxropcwksnzftjqes">
<div> <div>
<img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" :alt="name"> <img :src="$store.state.device.darkmode ? 'assets/title.dark.svg' : 'assets/title.light.svg'" :alt="name">
<p class="host">{{ host }}</p> <p class="host">{{ host }}</p>
@ -15,12 +15,53 @@
<mk-welcome-timeline/> <mk-welcome-timeline/>
</div> </div>
<div class="hashtags"> <div class="hashtags">
<router-link v-for="tag in tags" :key="tag" :to="`/tags/${ tag }`" :title="tag">#{{ tag }}</router-link> <mk-tag-cloud/>
</div>
<div class="photos">
<div v-for="photo in photos" :style="`background-image: url(${photo.thumbnailUrl})`"></div>
</div> </div>
<div class="stats" v-if="stats"> <div class="stats" v-if="stats">
<span>%fa:user% {{ stats.originalUsersCount | number }}</span> <span>%fa:user% {{ stats.originalUsersCount | number }}</span>
<span>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</span> <span>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</span>
</div> </div>
<div class="announcements" v-if="announcements && announcements.length > 0">
<article v-for="announcement in announcements">
<span class="title" v-html="announcement.title"></span>
<div v-html="announcement.text"></div>
</article>
</div>
<article class="about-misskey">
<h1>%i18n:common.intro.title%</h1>
<p v-html="'%i18n:common.intro.about%'"></p>
<section>
<h2>%i18n:common.intro.features%</h2>
<section>
<h3>%i18n:common.intro.rich-contents%</h3>
<div class="image"><img src="/assets/about/post.png" alt=""></div>
<p v-html="'%i18n:common.intro.rich-contents-desc%'"></p>
</section>
<section>
<h3>%i18n:common.intro.reaction%</h3>
<div class="image"><img src="/assets/about/reaction.png" alt=""></div>
<p v-html="'%i18n:common.intro.reaction-desc%'"></p>
</section>
<section>
<h3>%i18n:common.intro.ui%</h3>
<div class="image"><img src="/assets/about/ui.png" alt=""></div>
<p v-html="'%i18n:common.intro.ui-desc%'"></p>
</section>
<section>
<h3>%i18n:common.intro.drive%</h3>
<div class="image"><img src="/assets/about/drive.png" alt=""></div>
<p v-html="'%i18n:common.intro.drive-desc%'"></p>
</section>
</section>
<p v-html="'%i18n:common.intro.outro%'"></p>
</article>
<div class="info" v-if="meta">
<p>Version: <b>{{ meta.version }}</b></p>
<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
</div>
<footer> <footer>
<small>{{ copyright }}</small> <small>{{ copyright }}</small>
</footer> </footer>
@ -30,39 +71,53 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { apiUrl, copyright, host } from '../../../config'; import { copyright, host } from '../../../config';
import { concat } from '../../../../../prelude/array';
export default Vue.extend({ export default Vue.extend({
data() { data() {
return { return {
apiUrl, meta: null,
copyright, copyright,
stats: null, stats: null,
host, host,
name: 'Misskey', name: 'Misskey',
description: '', description: '',
tags: [] photos: [],
announcements: []
}; };
}, },
created() { created() {
(this as any).os.getMeta().then(meta => { (this as any).os.getMeta().then(meta => {
this.meta = meta;
this.name = meta.name; this.name = meta.name;
this.description = meta.description; this.description = meta.description;
this.announcements = meta.broadcasts;
}); });
(this as any).api('stats').then(stats => { (this as any).api('stats').then(stats => {
this.stats = stats; this.stats = stats;
}); });
(this as any).api('hashtags/trend').then(stats => { const image = [
this.tags = stats.map(x => x.tag); 'image/jpeg',
'image/png',
'image/gif'
];
(this as any).api('notes/local-timeline', {
fileType: image,
limit: 6
}).then((notes: any[]) => {
const files = concat(notes.map((n: any): any[] => n.files));
this.photos = files.filter(f => image.includes(f.type)).slice(0, 6);
}); });
} }
}); });
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.welcome root(isDark)
text-align center text-align center
//background #fff //background #fff
@ -138,12 +193,21 @@ export default Vue.extend({
-webkit-overflow-scrolling touch -webkit-overflow-scrolling touch
> .hashtags > .hashtags
padding 16px 0 padding 0 8px
border solid 2px #ddd height 200px
border-radius 8px
> * > .photos
margin 0 16px display grid
grid-template-rows 1fr 1fr 1fr
grid-template-columns 1fr 1fr
gap 8px
height 300px
margin-top 16px
> div
border-radius 4px
background-position center center
background-size cover
> .stats > .stats
margin 16px 0 margin 16px 0
@ -156,6 +220,68 @@ export default Vue.extend({
> * > *
margin 0 8px margin 0 8px
> .announcements
margin 16px 0
> article
background isDark ? rgba(30, 129, 216, 0.2) : rgba(155, 196, 232, 0.2)
border-radius 6px
color isDark ? #fff : #3f4967
padding 16px
margin 8px 0
font-size 12px
> .title
font-weight bold
> .about-misskey
margin 16px 0
padding 32px
font-size 14px
background #fff
border-radius 6px
overflow hidden
color #3a3e46
> h1
margin 0
& + p
margin-top 8px
> p:last-child
margin-bottom 0
> section
> h2
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
> section
margin-bottom 16px
padding-bottom 16px
border-bottom 1px solid isDark ? rgba(#000, 0.2) : rgba(#000, 0.05)
> h3
margin-bottom 8px
> p
margin-bottom 0
> .image
> img
display block
width 100%
height 120px
object-fit cover
> .info
padding 16px 0
border solid 2px #ddd
border-radius 8px
> *
margin 0 16px
> footer > footer
text-align center text-align center
color #444 color #444
@ -165,4 +291,10 @@ export default Vue.extend({
margin 16px 0 0 0 margin 16px 0 0 0
opacity 0.7 opacity 0.7
.wgwfgvvimdjvhjfwxropcwksnzftjqes[data-darkmode]
root(true)
.wgwfgvvimdjvhjfwxropcwksnzftjqes:not([data-darkmode])
root(false)
</style> </style>

View File

@ -4,6 +4,7 @@ import * as nestedProperty from 'nested-property';
import MiOS from './mios'; import MiOS from './mios';
import { hostname } from './config'; import { hostname } from './config';
import { erase } from '../../prelude/array';
const defaultSettings = { const defaultSettings = {
home: null, home: null,
@ -15,6 +16,7 @@ const defaultSettings = {
suggestRecentHashtags: true, suggestRecentHashtags: true,
showClockOnHeader: true, showClockOnHeader: true,
circleIcons: true, circleIcons: true,
contrastedAcct: true,
gradientWindowHeader: false, gradientWindowHeader: false,
showReplyTarget: true, showReplyTarget: true,
showMyRenotes: true, showMyRenotes: true,
@ -24,6 +26,8 @@ const defaultSettings = {
disableViaMobile: false, disableViaMobile: false,
memo: null, memo: null,
iLikeSushi: false, iLikeSushi: false,
rememberNoteVisibility: false,
defaultNoteVisibility: 'public',
games: { games: {
reversi: { reversi: {
showBoardLabels: false, showBoardLabels: false,
@ -43,7 +47,8 @@ const defaultDeviceSettings = {
debug: false, debug: false,
lightmode: false, lightmode: false,
loadRawImages: false, loadRawImages: false,
postStyle: 'standard' postStyle: 'standard',
mobileNotificationPosition: 'bottom'
}; };
export default (os: MiOS) => new Vuex.Store({ export default (os: MiOS) => new Vuex.Store({
@ -194,7 +199,7 @@ export default (os: MiOS) => new Vuex.Store({
removeDeckColumn(state, id) { removeDeckColumn(state, id) {
state.deck.columns = state.deck.columns.filter(c => c.id != id); state.deck.columns = state.deck.columns.filter(c => c.id != id);
state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id)); state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0); state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
}, },
@ -265,7 +270,7 @@ export default (os: MiOS) => new Vuex.Store({
stackLeftDeckColumn(state, id) { stackLeftDeckColumn(state, id) {
const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1); const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id)); state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
const left = state.deck.layout[i - 1]; const left = state.deck.layout[i - 1];
if (left) state.deck.layout[i - 1].push(id); if (left) state.deck.layout[i - 1].push(id);
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0); state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
@ -273,7 +278,7 @@ export default (os: MiOS) => new Vuex.Store({
popRightDeckColumn(state, id) { popRightDeckColumn(state, id) {
const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1); const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id)); state.deck.layout = state.deck.layout.map(ids => erase(id, ids));
state.deck.layout.splice(i + 1, 0, [id]); state.deck.layout.splice(i + 1, 0, [id]);
state.deck.layout = state.deck.layout.filter(ids => ids.length > 0); state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
}, },

View File

@ -3,6 +3,7 @@
*/ */
import composeNotification from './common/scripts/compose-notification'; import composeNotification from './common/scripts/compose-notification';
import { erase } from '../../prelude/array';
// キャッシュするリソース // キャッシュするリソース
const cachee = [ const cachee = [
@ -24,8 +25,7 @@ self.addEventListener('activate', ev => {
// Clean up old caches // Clean up old caches
ev.waitUntil( ev.waitUntil(
caches.keys().then(keys => Promise.all( caches.keys().then(keys => Promise.all(
keys erase(_VERSION_, keys)
.filter(key => key != _VERSION_)
.map(key => caches.delete(key)) .map(key => caches.delete(key))
)) ))
); );

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 274 KiB

View File

@ -7,6 +7,7 @@ import { URL } from 'url';
import * as yaml from 'js-yaml'; import * as yaml from 'js-yaml';
import { Source, Mixin } from './types'; import { Source, Mixin } from './types';
import isUrl = require('is-url'); import isUrl = require('is-url');
const pkg = require('../../package.json');
/** /**
* Path of configuration directory * Path of configuration directory
@ -43,6 +44,7 @@ export default function load() {
mixin.stats_url = `${mixin.scheme}://${mixin.host}/stats`; mixin.stats_url = `${mixin.scheme}://${mixin.host}/stats`;
mixin.status_url = `${mixin.scheme}://${mixin.host}/status`; mixin.status_url = `${mixin.scheme}://${mixin.host}/status`;
mixin.drive_url = `${mixin.scheme}://${mixin.host}/files`; mixin.drive_url = `${mixin.scheme}://${mixin.host}/files`;
mixin.user_agent = `Misskey/${pkg.version} (${config.url})`;
if (config.localDriveCapacityMb == null) config.localDriveCapacityMb = 256; if (config.localDriveCapacityMb == null) config.localDriveCapacityMb = 256;
if (config.remoteDriveCapacityMb == null) config.remoteDriveCapacityMb = 8; if (config.remoteDriveCapacityMb == null) config.remoteDriveCapacityMb = 8;

View File

@ -114,6 +114,7 @@ export type Mixin = {
status_url: string; status_url: string;
dev_url: string; dev_url: string;
drive_url: string; drive_url: string;
user_agent: string;
}; };
export type Config = Source & Mixin; export type Config = Source & Mixin;

View File

@ -4,6 +4,12 @@ import config from '../config';
const index = { const index = {
settings: { settings: {
analysis: { analysis: {
normalizer: {
lowercase_normalizer: {
type: 'custom',
filter: ['lowercase']
}
},
analyzer: { analyzer: {
bigram: { bigram: {
tokenizer: 'bigram_tokenizer' tokenizer: 'bigram_tokenizer'
@ -24,7 +30,8 @@ const index = {
text: { text: {
type: 'text', type: 'text',
index: true, index: true,
analyzer: 'bigram' analyzer: 'bigram',
normalizer: 'lowercase_normalizer'
} }
} }
} }

View File

@ -33,19 +33,19 @@ props:
ja-JP: "投稿の本文" ja-JP: "投稿の本文"
en-US: "The text of this note" en-US: "The text of this note"
mediaIds: fileIds:
type: "id(DriveFile)[]" type: "id(DriveFile)[]"
optional: true optional: true
desc: desc:
ja-JP: "添付されているメディアのID (なければレスポンスでは空配列)" ja-JP: "添付されているファイルのID (なければレスポンスでは空配列)"
en-US: "The IDs of the attached media (empty array for response if no media is attached)" en-US: "The IDs of the attached files (empty array for response if no files is attached)"
media: files:
type: "entity(DriveFile)[]" type: "entity(DriveFile)[]"
optional: true optional: true
desc: desc:
ja-JP: "添付されているメディア" ja-JP: "添付されているファイル"
en-US: "The attached media" en-US: "The attached files"
userId: userId:
type: "id(User)" type: "id(User)"

View File

@ -1,3 +1,5 @@
import { count, concat } from "../../prelude/array";
// MISSKEY REVERSI ENGINE // MISSKEY REVERSI ENGINE
/** /**
@ -88,8 +90,8 @@ export default class Reversi {
//#endregion //#endregion
// ゲームが始まった時点で片方の色の石しかないか、始まった時点で勝敗が決定するようなマップの場合がある // ゲームが始まった時点で片方の色の石しかないか、始まった時点で勝敗が決定するようなマップの場合がある
if (this.canPutSomewhere(BLACK).length == 0) { if (!this.canPutSomewhere(BLACK)) {
if (this.canPutSomewhere(WHITE).length == 0) { if (!this.canPutSomewhere(WHITE)) {
this.turn = null; this.turn = null;
} else { } else {
this.turn = WHITE; this.turn = WHITE;
@ -101,14 +103,14 @@ export default class Reversi {
* 黒石の数 * 黒石の数
*/ */
public get blackCount() { public get blackCount() {
return this.board.filter(x => x === BLACK).length; return count(BLACK, this.board);
} }
/** /**
* 白石の数 * 白石の数
*/ */
public get whiteCount() { public get whiteCount() {
return this.board.filter(x => x === WHITE).length; return count(WHITE, this.board);
} }
/** /**
@ -170,9 +172,9 @@ export default class Reversi {
private calcTurn() { private calcTurn() {
// ターン計算 // ターン計算
if (this.canPutSomewhere(!this.prevColor).length > 0) { if (this.canPutSomewhere(!this.prevColor)) {
this.turn = !this.prevColor; this.turn = !this.prevColor;
} else if (this.canPutSomewhere(this.prevColor).length > 0) { } else if (this.canPutSomewhere(this.prevColor)) {
this.turn = this.prevColor; this.turn = this.prevColor;
} else { } else {
this.turn = null; this.turn = null;
@ -204,10 +206,17 @@ export default class Reversi {
/** /**
* 打つことができる場所を取得します * 打つことができる場所を取得します
*/ */
public canPutSomewhere(color: Color): number[] { public puttablePlaces(color: Color): number[] {
return Array.from(this.board.keys()).filter(i => this.canPut(color, i)); return Array.from(this.board.keys()).filter(i => this.canPut(color, i));
} }
/**
* 打つことができる場所があるかどうかを取得します
*/
public canPutSomewhere(color: Color): boolean {
return this.puttablePlaces(color).length > 0;
}
/** /**
* 指定のマスに石を打つことができるかどうかを取得します * 指定のマスに石を打つことができるかどうかを取得します
* @param color 自分の色 * @param color 自分の色
@ -229,87 +238,55 @@ export default class Reversi {
/** /**
* 指定のマスに石を置いた時の、反転させられる石を取得します * 指定のマスに石を置いた時の、反転させられる石を取得します
* @param color 自分の色 * @param color 自分の色
* @param pos 位置 * @param initPos 位置
*/ */
public effects(color: Color, pos: number): number[] { public effects(color: Color, initPos: number): number[] {
const enemyColor = !color; const enemyColor = !color;
// ひっくり返せる石(の位置)リスト const diffVectors: [number, number][] = [
let stones: number[] = []; [ 0, -1], // 上
[ +1, -1], // 右上
[ +1, 0], // 右
[ +1, +1], // 右下
[ 0, +1], // 下
[ -1, +1], // 左下
[ -1, 0], // 左
[ -1, -1] // 左上
];
const initPos = pos; const effectsInLine = ([dx, dy]: [number, number]): number[] => {
const nextPos = (x: number, y: number): [number, number] => [x + dx, y + dy];
// 走査
const iterate = (fn: (i: number) => number[]) => {
let i = 1;
const found = [];
const found: number[] = []; // 挟めるかもしれない相手の石を入れておく配列
let [x, y] = this.transformPosToXy(initPos);
while (true) { while (true) {
let [x, y] = fn(i); [x, y] = nextPos(x, y);
// 座標が指し示す位置がボード外に出たとき // 座標が指し示す位置がボード外に出たとき
if (this.opts.loopedBoard) { if (this.opts.loopedBoard) {
if (x < 0 ) x = this.mapWidth - ((-x) % this.mapWidth); x = ((x % this.mapWidth) + this.mapWidth) % this.mapWidth;
if (y < 0 ) y = this.mapHeight - ((-y) % this.mapHeight); y = ((y % this.mapHeight) + this.mapHeight) % this.mapHeight;
if (x >= this.mapWidth ) x = x % this.mapWidth;
if (y >= this.mapHeight) y = y % this.mapHeight;
// for debug
//if (x < 0 || y < 0 || x >= this.mapWidth || y >= this.mapHeight) {
// console.log(x, y);
//}
// 一周して自分に帰ってきたら
if (this.transformXyToPos(x, y) == initPos) { if (this.transformXyToPos(x, y) == initPos) {
// ↓のコメントアウトを外すと、「現時点で自分の石が隣接していないが、 // 盤面の境界でループし、自分が石を置く位置に戻ってきたとき、挟めるようにしている (ref: Test4のマップ)
// そこに置いたとするとループして最終的に挟んだことになる」というケースを有効化します。(Test4のマップで違いが分かります) return found;
// このケースを有効にした方が良いのか無効にした方が良いのか判断がつかなかったためとりあえず無効としておきます
// (あと無効な方がゲームとしておもしろそうだった)
stones = stones.concat(found);
break;
} }
} else { } else {
if (x == -1 || y == -1 || x == this.mapWidth || y == this.mapHeight) break; if (x == -1 || y == -1 || x == this.mapWidth || y == this.mapHeight) {
return []; // 挟めないことが確定 (盤面外に到達)
}
} }
const pos = this.transformXyToPos(x, y); const pos = this.transformXyToPos(x, y);
if (this.mapDataGet(pos) === 'null') return []; // 挟めないことが確定 (配置不可能なマスに到達)
//#region 「配置不能」マスに当たった場合走査終了
const pixel = this.mapDataGet(pos);
if (pixel == 'null') break;
//#endregion
// 石取得
const stone = this.board[pos]; const stone = this.board[pos];
if (stone === null) return []; // 挟めないことが確定 (石が置かれていないマスに到達)
// 石が置かれていないマスなら走査終了 if (stone === enemyColor) found.push(pos); // 挟めるかもしれない (相手の石を発見)
if (stone === null) break; if (stone === color) return found; // 挟めることが確定 (対となる自分の石を発見)
// 相手の石なら「ひっくり返せるかもリスト」に入れておく
if (stone === enemyColor) found.push(pos);
// 自分の石なら「ひっくり返せるかもリスト」を「ひっくり返せるリスト」に入れ、走査終了
if (stone === color) {
stones = stones.concat(found);
break;
}
i++;
} }
}; };
const [x, y] = this.transformPosToXy(pos); return concat(diffVectors.map(effectsInLine));
iterate(i => [x , y - i]); // 上
iterate(i => [x + i, y - i]); // 右上
iterate(i => [x + i, y ]); // 右
iterate(i => [x + i, y + i]); // 右下
iterate(i => [x , y + i]); // 下
iterate(i => [x - i, y + i]); // 左下
iterate(i => [x - i, y ]); // 左
iterate(i => [x - i, y - i]); // 左上
return stones;
} }
/** /**

View File

@ -4,10 +4,7 @@ const { JSDOM } = jsdom;
import config from '../config'; import config from '../config';
import { INote } from '../models/note'; import { INote } from '../models/note';
import { TextElement } from './parse'; import { TextElement } from './parse';
import { intersperse } from '../prelude/array';
function intersperse<T>(sep: T, xs: T[]): T[] {
return [].concat(...xs.map(x => [sep, x])).slice(1);
}
const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers: INote['mentionedRemoteUsers']) => void } = { const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers: INote['mentionedRemoteUsers']) => void } = {
bold({ document }, { bold }) { bold({ document }, { bold }) {

View File

@ -1,3 +1,5 @@
import { capitalize } from "../../../prelude/string";
function escape(text: string) { function escape(text: string) {
return text return text
.replace(/>/g, '&gt;') .replace(/>/g, '&gt;')
@ -89,7 +91,7 @@ const _keywords = [
]; ];
const keywords = _keywords const keywords = _keywords
.concat(_keywords.map(k => k[0].toUpperCase() + k.substr(1))) .concat(_keywords.map(capitalize))
.concat(_keywords.map(k => k.toUpperCase())) .concat(_keywords.map(k => k.toUpperCase()))
.sort((a, b) => b.length - a.length); .sort((a, b) => b.length - a.length);

View File

@ -16,9 +16,9 @@ const summarize = (note: any): string => {
// 本文 // 本文
summary += note.text ? note.text : ''; summary += note.text ? note.text : '';
// メディアが添付されているとき // ファイルが添付されているとき
if (note.media.length != 0) { if (note.files.length != 0) {
summary += ` (${note.media.length}つのメディア)`; summary += ` (${note.files.length}つのファイル)`;
} }
// 投票が添付されているとき // 投票が添付されているとき

View File

@ -1,5 +1,5 @@
import { INote } from '../models/note'; import { INote } from '../models/note';
export default function(note: INote): boolean { export default function(note: INote): boolean {
return note.renoteId != null && (note.text != null || note.poll != null || (note.mediaIds != null && note.mediaIds.length > 0)); return note.renoteId != null && (note.text != null || note.poll != null || (note.fileIds != null && note.fileIds.length > 0));
} }

View File

@ -92,7 +92,7 @@ export async function deleteDriveFile(driveFile: string | mongo.ObjectID | IDriv
// このDriveFileを添付しているNoteをすべて削除 // このDriveFileを添付しているNoteをすべて削除
await Promise.all(( await Promise.all((
await Note.find({ mediaIds: d._id }) await Note.find({ fileIds: d._id })
).map(x => deleteNote(x))); ).map(x => deleteNote(x)));
// このDriveFileを添付しているMessagingMessageをすべて削除 // このDriveFileを添付しているMessagingMessageをすべて削除

View File

@ -4,12 +4,13 @@ const Meta = db.get<IMeta>('meta');
export default Meta; export default Meta;
export type IMeta = { export type IMeta = {
broadcasts: any[]; broadcasts?: any[];
stats: { stats?: {
notesCount: number; notesCount: number;
originalNotesCount: number; originalNotesCount: number;
usersCount: number; usersCount: number;
originalUsersCount: number; originalUsersCount: number;
}; };
disableRegistration: boolean; disableRegistration?: boolean;
hidedTags?: string[];
}; };

View File

@ -6,7 +6,7 @@ import { IUser, pack as packUser } from './user';
import { pack as packApp } from './app'; import { pack as packApp } from './app';
import PollVote, { deletePollVote } from './poll-vote'; import PollVote, { deletePollVote } from './poll-vote';
import Reaction, { deleteNoteReaction } from './note-reaction'; import Reaction, { deleteNoteReaction } from './note-reaction';
import { pack as packFile } from './drive-file'; import { pack as packFile, IDriveFile } from './drive-file';
import NoteWatching, { deleteNoteWatching } from './note-watching'; import NoteWatching, { deleteNoteWatching } from './note-watching';
import NoteReaction from './note-reaction'; import NoteReaction from './note-reaction';
import Favorite, { deleteFavorite } from './favorite'; import Favorite, { deleteFavorite } from './favorite';
@ -17,9 +17,20 @@ const Note = db.get<INote>('notes');
Note.createIndex('uri', { sparse: true, unique: true }); Note.createIndex('uri', { sparse: true, unique: true });
Note.createIndex('userId'); Note.createIndex('userId');
Note.createIndex('tagsLower'); Note.createIndex('tagsLower');
Note.createIndex('_files.contentType');
Note.createIndex({ Note.createIndex({
createdAt: -1 createdAt: -1
}); });
// 後方互換性のため
Note.update({}, {
$rename: {
mediaIds: 'fileIds'
}
}, {
multi: true
});
export default Note; export default Note;
export function isValidText(text: string): boolean { export function isValidText(text: string): boolean {
@ -34,7 +45,7 @@ export type INote = {
_id: mongo.ObjectID; _id: mongo.ObjectID;
createdAt: Date; createdAt: Date;
deletedAt: Date; deletedAt: Date;
mediaIds: mongo.ObjectID[]; fileIds: mongo.ObjectID[];
replyId: mongo.ObjectID; replyId: mongo.ObjectID;
renoteId: mongo.ObjectID; renoteId: mongo.ObjectID;
poll: { poll: {
@ -92,6 +103,7 @@ export type INote = {
inbox?: string; inbox?: string;
}; };
_replyIds?: mongo.ObjectID[]; _replyIds?: mongo.ObjectID[];
_files?: IDriveFile[];
}; };
/** /**
@ -271,11 +283,15 @@ export const pack = async (
_note.app = packApp(_note.appId); _note.app = packApp(_note.appId);
} }
// Populate media // Populate files
_note.media = hide ? [] : Promise.all(_note.mediaIds.map((fileId: mongo.ObjectID) => _note.files = hide ? [] : Promise.all(_note.fileIds.map((fileId: mongo.ObjectID) =>
packFile(fileId) packFile(fileId)
)); ));
// 後方互換性のため
_note.mediaIds = _note.fileIds;
_note.media = _note.files;
// When requested a detailed note data // When requested a detailed note data
if (opts.detail) { if (opts.detail) {
//#region 重いので廃止 //#region 重いので廃止
@ -344,7 +360,7 @@ export const pack = async (
} }
if (hide) { if (hide) {
_note.mediaIds = []; _note.fileIds = [];
_note.text = null; _note.text = null;
_note.poll = null; _note.poll = null;
_note.cw = null; _note.cw = null;

View File

@ -432,10 +432,10 @@ export const pack = (
followerId: _user.id, followerId: _user.id,
followeeId: meId followeeId: meId
}), }),
_user.isLocked ? FollowRequest.findOne({ FollowRequest.findOne({
followerId: meId, followerId: meId,
followeeId: _user.id followeeId: _user.id
}) : Promise.resolve(null), }),
FollowRequest.findOne({ FollowRequest.findOne({
followerId: _user.id, followerId: _user.id,
followeeId: meId followeeId: meId

3
src/prelude/README.md Normal file
View File

@ -0,0 +1,3 @@
# Prelude
このディレクトリのコードはJavaScriptの表現能力を補うためのコードです。
Misskey固有の処理とは独立したコードの集まりですが、Misskeyのコードを読みやすくすることを目的としています。

27
src/prelude/array.ts Normal file
View File

@ -0,0 +1,27 @@
export function countIf<T>(f: (x: T) => boolean, xs: T[]): number {
return xs.filter(f).length;
}
export function count<T>(x: T, xs: T[]): number {
return countIf(y => x === y, xs);
}
export function concat<T>(xss: T[][]): T[] {
return ([] as T[]).concat(...xss);
}
export function intersperse<T>(sep: T, xs: T[]): T[] {
return concat(xs.map(x => [sep, x])).slice(1);
}
export function erase<T>(x: T, xs: T[]): T[] {
return xs.filter(y => x !== y);
}
export function unique<T>(xs: T[]): T[] {
return [...new Set(xs)];
}
export function sum(xs: number[]): number {
return xs.reduce((a, b) => a + b, 0);
}

3
src/prelude/math.ts Normal file
View File

@ -0,0 +1,3 @@
export function gcd(a: number, b: number): number {
return b === 0 ? a : gcd(b, a % b);
}

3
src/prelude/string.ts Normal file
View File

@ -0,0 +1,3 @@
export function capitalize(s: string): string {
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}

View File

@ -78,11 +78,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
} }
//#endergion //#endergion
// 添付メディア // 添付ファイル
// TODO: attachmentは必ずしもImageではない // TODO: attachmentは必ずしもImageではない
// TODO: attachmentは必ずしも配列ではない // TODO: attachmentは必ずしも配列ではない
// Noteがsensitiveなら添付もsensitiveにする // Noteがsensitiveなら添付もsensitiveにする
const media = note.attachment const files = note.attachment
.map(attach => attach.sensitive = note.sensitive) .map(attach => attach.sensitive = note.sensitive)
? await Promise.all(note.attachment.map(x => resolveImage(actor, x))) ? await Promise.all(note.attachment.map(x => resolveImage(actor, x)))
: []; : [];
@ -100,7 +100,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
return await post(actor, { return await post(actor, {
createdAt: new Date(note.published), createdAt: new Date(note.published),
media, files: files,
reply, reply,
renote: undefined, renote: undefined,
cw: note.summary, cw: note.summary,

View File

@ -5,7 +5,7 @@ export default (object: any, note: INote) => {
const attributedTo = `${config.url}/users/${note.userId}`; const attributedTo = `${config.url}/users/${note.userId}`;
return { return {
id: `${config.url}/notes/${note._id}`, id: `${config.url}/notes/${note._id}/activity`,
actor: `${config.url}/users/${note.userId}`, actor: `${config.url}/users/${note.userId}`,
type: 'Announce', type: 'Announce',
published: note.createdAt.toISOString(), published: note.createdAt.toISOString(),

View File

@ -8,8 +8,8 @@ import User from '../../../models/user';
import toHtml from '../misc/get-note-html'; import toHtml from '../misc/get-note-html';
export default async function renderNote(note: INote, dive = true): Promise<any> { export default async function renderNote(note: INote, dive = true): Promise<any> {
const promisedFiles: Promise<IDriveFile[]> = note.mediaIds const promisedFiles: Promise<IDriveFile[]> = note.fileIds
? DriveFile.find({ _id: { $in: note.mediaIds } }) ? DriveFile.find({ _id: { $in: note.fileIds } })
: Promise.resolve([]); : Promise.resolve([]);
let inReplyTo; let inReplyTo;

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