Compare commits

...

201 Commits

Author SHA1 Message Date
2488d40421 Merge pull request #2482 from syuilo/develop
8.13.0
2018-08-25 19:46:50 +09:00
bf7875bfaa Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-08-25 19:46:20 +09:00
a84fa30774 8.13.0 2018-08-25 19:46:12 +09:00
c19a763b3d Merge pull request #2481 from syuilo/greenkeeper/systeminformation-3.43.0
fix(package): update systeminformation to version 3.43.0
2018-08-25 19:45:31 +09:00
0875460974 ユーザーのアイコンにサムネイルを使うように
Closes #2365
2018-08-25 19:44:47 +09:00
f0b08d3936 Add brackets 2018-08-25 19:39:06 +09:00
16520c7b4c Merge pull request #2476 from acid-chicken/patch-4
Fix #2392
2018-08-25 19:37:35 +09:00
65549d06d9 ✌️ 2018-08-25 19:34:54 +09:00
ce2d2a10c1 fix(package): update systeminformation to version 3.43.0
Closes #2477
2018-08-25 08:56:01 +00:00
0ebe801af4 Update boot.js 2018-08-25 17:06:40 +09:00
05daa7ac7d Merge pull request #2475 from syuilo/develop
8.12.0
2018-08-25 16:35:29 +09:00
990a583e5e 8.12.0 2018-08-25 16:34:41 +09:00
d9b02a18bf Merge pull request #2474 from mei23/mei-0825-appleroma2
Pleromaとつながらないのを修正
2018-08-25 16:33:02 +09:00
30aae79e5c Merge pull request #2473 from syuilo/develop
8.11.1
2018-08-25 15:41:06 +09:00
a149c121fb 8.11.1 2018-08-25 15:40:47 +09:00
47f4b51207 Fix bug 2018-08-25 15:40:22 +09:00
79f4d886d0 Merge pull request #2472 from syuilo/develop
8.11.0
2018-08-25 15:34:33 +09:00
2b556aba03 8.11.0 2018-08-25 15:34:10 +09:00
739c993911 Fix #2466 2018-08-25 15:30:48 +09:00
cb180e00de Merge pull request #2471 from syuilo/greenkeeper/@types/node-10.9.2
Update @types/node to the latest version 🚀
2018-08-25 15:26:25 +09:00
4d46a61051 ✌️ 2018-08-25 15:26:13 +09:00
81969ea8b2 🎨 2018-08-25 15:25:16 +09:00
ac474f3884 Send actor in Delete 2018-08-25 14:52:35 +09:00
a39aaf6eb1 Send actor in Undo Follow 2018-08-25 14:46:47 +09:00
68a7661f08 Create Note activity にも toとcc 2018-08-25 14:23:51 +09:00
ffcb2f755c Send actor in CreateNote, Announce 2018-08-25 14:12:44 +09:00
366e0d6bde fix(package): update @types/node to version 10.9.2 2018-08-25 04:40:46 +00:00
b3a3238e43 HTTP Signature検証対象ヘッダにDateが含まれてなくても許容する 2018-08-25 13:40:12 +09:00
92828028db Add Activity id if missing 2018-08-25 13:11:54 +09:00
edb61e52c5 Use resolvable ActivityPub keyId 2018-08-25 12:46:06 +09:00
ded297b04c Merge pull request #2469 from syuilo/develop
8.10.0
2018-08-25 12:44:37 +09:00
65e1d5978a Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-08-25 12:44:15 +09:00
86e76358b1 8.10.0 2018-08-25 12:44:06 +09:00
435e0257a4 Merge pull request #2468 from syuilo/l10n_develop
New Crowdin translations
2018-08-25 12:43:35 +09:00
1c45cc808b Improve stats page 2018-08-25 12:43:18 +09:00
ed27a2f963 New translations ja-JP.yml (English) 2018-08-25 12:41:07 +09:00
1f53d1a149 Send Content-Type in ActivityPub request 2018-08-25 12:32:31 +09:00
8295f6d7a3 New translations ja-JP.yml (Japanese, Kansai) 2018-08-25 12:31:41 +09:00
b02f6341c9 New translations ja-JP.yml (Spanish) 2018-08-25 12:31:39 +09:00
f6d577d411 New translations ja-JP.yml (Russian) 2018-08-25 12:31:37 +09:00
db3e73318e New translations ja-JP.yml (Portuguese) 2018-08-25 12:31:35 +09:00
29c2071711 New translations ja-JP.yml (Polish) 2018-08-25 12:31:33 +09:00
3acd524d09 New translations ja-JP.yml (Korean) 2018-08-25 12:31:30 +09:00
dae65cc123 New translations ja-JP.yml (Italian) 2018-08-25 12:31:28 +09:00
695f154d87 New translations ja-JP.yml (German) 2018-08-25 12:31:26 +09:00
59dca9a812 New translations ja-JP.yml (French) 2018-08-25 12:31:23 +09:00
b9f04f8f53 New translations ja-JP.yml (English) 2018-08-25 12:31:20 +09:00
0985f14f18 New translations ja-JP.yml (Chinese Simplified) 2018-08-25 12:31:18 +09:00
56684dd7c3 New translations ja-JP.yml (Catalan) 2018-08-25 12:31:16 +09:00
47a5f3bc67 チャートコンポーネントを分離するなど 2018-08-25 12:28:05 +09:00
1c1e3009e9 ✌️ 2018-08-25 12:14:36 +09:00
c7c3f6999b Merge pull request #2465 from syuilo/develop
8.9.2
2018-08-25 11:11:00 +09:00
fb4aa9bc1c 8.9.2 2018-08-25 11:10:38 +09:00
ef57f5907b Fix bug 2018-08-25 11:10:27 +09:00
eff44f9cd1 Merge pull request #2464 from syuilo/develop
8.9.1
2018-08-25 10:28:47 +09:00
d7fa92d58f 8.9.1 2018-08-25 10:28:28 +09:00
4e8033d5a4 Fix bug 2018-08-25 10:28:09 +09:00
8a207d8311 Merge pull request #2461 from syuilo/develop
8.9.0
2018-08-25 08:41:16 +09:00
94ba9c8437 8.9.0 2018-08-25 08:40:16 +09:00
88c71c2998 #2451 2018-08-25 08:39:12 +09:00
7b6e55047f #2460 2018-08-25 08:35:41 +09:00
9d85d0bb08 Merge pull request #2411 from syuilo/l10n_develop
New Crowdin translations
2018-08-25 07:22:34 +09:00
27ac0bbc00 Merge pull request #2429 from syuilo/greenkeeper/vue-js-modal-1.3.19
Update vue-js-modal to the latest version 🚀
2018-08-25 07:21:44 +09:00
affde9b4e2 Merge pull request #2459 from syuilo/greenkeeper/@types/node-10.9.1
fix(package): update @types/node to version 10.9.1
2018-08-25 07:21:35 +09:00
88324b6dd9 Merge pull request #2432 from syuilo/greenkeeper/@types/sharp-0.17.10
Update @types/sharp to the latest version 🚀
2018-08-25 07:21:16 +09:00
9b95ffe6c6 Merge pull request #2433 from syuilo/greenkeeper/@types/webpack-4.4.11
Update @types/webpack to the latest version 🚀
2018-08-25 07:21:08 +09:00
6b137f8d69 Merge pull request #2458 from syuilo/master
Master
2018-08-25 07:20:38 +09:00
e78b2b0ab8 Merge pull request #2457 from mei23/mei-0825-apresolveuri3
リモートからのActivityに添付されている投稿は使用しないように変更
2018-08-25 07:07:46 +09:00
8b51428347 ActivityPub resolve で 添付のNoteを使用しないように 2018-08-25 06:50:35 +09:00
b8d53a7b40 Merge pull request #2455 from mei23/mei-0824-apattchobj
ActivityPubで非公開投稿が添付されてしまう件の修正
2018-08-25 05:25:14 +09:00
b0d9e9caa2 New translations ja-JP.yml (Japanese, Kansai) 2018-08-25 01:31:08 +09:00
1fc4ec8dc1 New translations ja-JP.yml (Japanese, Kansai) 2018-08-25 01:21:15 +09:00
a1e1e25800 New translations ja-JP.yml (English) 2018-08-24 23:57:28 +09:00
3b020732ec New translations ja-JP.yml (English) 2018-08-24 23:41:35 +09:00
dcf92945fe New translations ja-JP.yml (English) 2018-08-24 23:31:52 +09:00
f9f33903d4 New translations ja-JP.yml (French) 2018-08-24 21:51:28 +09:00
d8bf06ab0f New translations ja-JP.yml (French) 2018-08-24 21:43:26 +09:00
806dabe58b Merge pull request #2450 from syuilo/develop
8.8.0
2018-08-24 15:02:21 +09:00
a17b8c56d7 New translations ja-JP.yml (Japanese, Kansai) 2018-08-24 15:01:39 +09:00
0eaaaba8f2 New translations ja-JP.yml (Spanish) 2018-08-24 15:01:36 +09:00
f359d79d36 New translations ja-JP.yml (Russian) 2018-08-24 15:01:34 +09:00
1d84000d94 New translations ja-JP.yml (Portuguese) 2018-08-24 15:01:32 +09:00
b70e22c150 8.8.0 2018-08-24 15:01:30 +09:00
0774ffe376 New translations ja-JP.yml (Polish) 2018-08-24 15:01:29 +09:00
0096d7d8ac New translations ja-JP.yml (Korean) 2018-08-24 15:01:27 +09:00
38db966b3d New translations ja-JP.yml (Italian) 2018-08-24 15:01:24 +09:00
cb7d313a66 New translations ja-JP.yml (German) 2018-08-24 15:01:21 +09:00
91b7905f3f New translations ja-JP.yml (French) 2018-08-24 15:01:18 +09:00
9a81fba992 New translations ja-JP.yml (English) 2018-08-24 15:01:16 +09:00
43553d5c09 New translations ja-JP.yml (Chinese Simplified) 2018-08-24 15:01:14 +09:00
e0ca8ce173 New translations ja-JP.yml (Catalan) 2018-08-24 15:01:11 +09:00
13624ea7c2 バグ修正など 2018-08-24 14:55:58 +09:00
9502586c8b ActivityPub Renote/Replyで 対象Noteを添付しないようにする 2018-08-24 14:53:40 +09:00
d6753f2cf2 fix(package): update @types/node to version 10.9.1
Closes #2431
2018-08-24 00:40:11 +00:00
5ba36efcd2 Merge pull request #2446 from syuilo/develop
8.7.0
2018-08-24 09:39:57 +09:00
fd497ef105 8.7.0 2018-08-24 09:39:37 +09:00
9c4a7bf94c Improve chart 2018-08-24 09:39:16 +09:00
91f8adc138 Merge pull request #2445 from syuilo/develop
8.6.0
2018-08-24 08:57:54 +09:00
69fa2373cb 8.6.0 2018-08-24 08:57:31 +09:00
8b37fc4772 Improve chart 2018-08-24 08:56:57 +09:00
81e4ed9591 Merge pull request #2444 from syuilo/develop
8.5.1
2018-08-24 08:36:01 +09:00
9cda89ec04 8.5.1 2018-08-24 08:35:38 +09:00
fc180f030f Fix bug 2018-08-24 08:35:01 +09:00
a827b6028d Merge pull request #2442 from syuilo/develop
8.5.0
2018-08-24 07:24:08 +09:00
4517bf7342 8.5.0 2018-08-24 07:23:42 +09:00
b21287262e チャート取得APIを誰でも利用できるようにするなど 2018-08-24 07:23:04 +09:00
a60ae130c1 New translations ja-JP.yml (Japanese, Kansai) 2018-08-24 07:21:28 +09:00
dd88acd411 New translations ja-JP.yml (Spanish) 2018-08-24 07:21:25 +09:00
b63fc1a9e5 New translations ja-JP.yml (Russian) 2018-08-24 07:21:23 +09:00
17f143cfb2 New translations ja-JP.yml (Portuguese) 2018-08-24 07:21:20 +09:00
cf57d847d1 New translations ja-JP.yml (Polish) 2018-08-24 07:21:18 +09:00
7c4c7bea14 New translations ja-JP.yml (Korean) 2018-08-24 07:21:16 +09:00
e5ec47fc75 New translations ja-JP.yml (Italian) 2018-08-24 07:21:14 +09:00
ad91dc2423 New translations ja-JP.yml (German) 2018-08-24 07:21:11 +09:00
7acbe53948 New translations ja-JP.yml (French) 2018-08-24 07:21:08 +09:00
fe1b8ba0cb New translations ja-JP.yml (English) 2018-08-24 07:21:05 +09:00
b0a8a51b69 New translations ja-JP.yml (Chinese Simplified) 2018-08-24 07:21:03 +09:00
c3ca21e610 New translations ja-JP.yml (Catalan) 2018-08-24 07:21:00 +09:00
c1b47a2119 Add missing changelog 2018-08-24 07:20:26 +09:00
caf625afee Merge pull request #2441 from syuilo/develop
8.4.0
2018-08-24 07:18:00 +09:00
2bad3865a3 8.4.0 2018-08-24 07:17:40 +09:00
3f7d248684 Improve chart 2018-08-24 07:17:17 +09:00
4e7382b793 New translations ja-JP.yml (Japanese, Kansai) 2018-08-24 07:12:36 +09:00
552ff4a044 New translations ja-JP.yml (Spanish) 2018-08-24 07:12:33 +09:00
afb52a0cd5 New translations ja-JP.yml (Russian) 2018-08-24 07:12:31 +09:00
1ac89b0f5b New translations ja-JP.yml (Portuguese) 2018-08-24 07:12:28 +09:00
5039ca7ee1 New translations ja-JP.yml (Polish) 2018-08-24 07:12:26 +09:00
a48fd9ce18 New translations ja-JP.yml (Korean) 2018-08-24 07:12:24 +09:00
58859c4811 New translations ja-JP.yml (Italian) 2018-08-24 07:12:22 +09:00
5988fb3111 New translations ja-JP.yml (German) 2018-08-24 07:12:19 +09:00
8dce821789 New translations ja-JP.yml (French) 2018-08-24 07:12:16 +09:00
16fde0b507 New translations ja-JP.yml (English) 2018-08-24 07:12:13 +09:00
9723662706 New translations ja-JP.yml (Chinese Simplified) 2018-08-24 07:12:11 +09:00
df4415b4fe New translations ja-JP.yml (Catalan) 2018-08-24 07:12:09 +09:00
6e179e7cde Fix 2018-08-24 07:06:25 +09:00
87f248b8ec Merge pull request #2440 from syuilo/develop
8.3.1
2018-08-24 07:03:49 +09:00
027140eccc 8.3.1 2018-08-24 07:03:25 +09:00
92cf205c66 Fix bug 2018-08-24 07:02:52 +09:00
fa3299840f Refactor 2018-08-24 07:02:27 +09:00
f54529d46f New translations ja-JP.yml (Japanese, Kansai) 2018-08-24 06:51:15 +09:00
b772add064 New translations ja-JP.yml (Spanish) 2018-08-24 06:51:13 +09:00
231f2e77a4 New translations ja-JP.yml (Russian) 2018-08-24 06:51:10 +09:00
a000a9e607 New translations ja-JP.yml (Portuguese) 2018-08-24 06:51:08 +09:00
e8da15ab1e New translations ja-JP.yml (Polish) 2018-08-24 06:51:05 +09:00
e070ccb313 New translations ja-JP.yml (Korean) 2018-08-24 06:51:02 +09:00
2b06579228 New translations ja-JP.yml (Italian) 2018-08-24 06:50:59 +09:00
853c847ba1 New translations ja-JP.yml (German) 2018-08-24 06:50:57 +09:00
e852680b0a New translations ja-JP.yml (French) 2018-08-24 06:50:55 +09:00
0b0ee915b3 New translations ja-JP.yml (English) 2018-08-24 06:50:52 +09:00
516d1d093f New translations ja-JP.yml (Chinese Simplified) 2018-08-24 06:50:49 +09:00
aee9c79c0f New translations ja-JP.yml (Catalan) 2018-08-24 06:50:47 +09:00
2d4b183c14 Merge pull request #2439 from syuilo/develop
8.3.0
2018-08-24 06:43:12 +09:00
03b20e11ca 8.3.0 2018-08-24 06:42:40 +09:00
e0e006e284 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-08-24 06:41:56 +09:00
a294a881ec Improve chart 2018-08-24 06:41:53 +09:00
53926082e7 Merge pull request #2438 from mei23/mei-0824-basehtmlcc
ベースHTMLは immutableキャッシュしないようにする
2018-08-24 05:47:53 +09:00
2d185becc3 New translations ja-JP.yml (Japanese, Kansai) 2018-08-24 05:41:31 +09:00
67fff324b0 New translations ja-JP.yml (Spanish) 2018-08-24 05:41:29 +09:00
f64b7fcabc New translations ja-JP.yml (Russian) 2018-08-24 05:41:27 +09:00
4cefa16db6 New translations ja-JP.yml (Portuguese) 2018-08-24 05:41:25 +09:00
22722379df New translations ja-JP.yml (Polish) 2018-08-24 05:41:22 +09:00
b2b83dc45d New translations ja-JP.yml (Korean) 2018-08-24 05:41:19 +09:00
ebf6f8bbfd New translations ja-JP.yml (Italian) 2018-08-24 05:41:17 +09:00
3e1631d180 New translations ja-JP.yml (German) 2018-08-24 05:41:14 +09:00
97cb3c8613 New translations ja-JP.yml (French) 2018-08-24 05:41:11 +09:00
6dda3a5d8a New translations ja-JP.yml (English) 2018-08-24 05:41:09 +09:00
e50b0540f5 New translations ja-JP.yml (Chinese Simplified) 2018-08-24 05:41:06 +09:00
63b4aee9bd New translations ja-JP.yml (Catalan) 2018-08-24 05:41:04 +09:00
5b5de6a89c ベースHTMLは immutableキャッシュしないようにする 2018-08-24 05:41:03 +09:00
a11c991f83 Merge pull request #2436 from mei23/mei-0824-api404
/api/ 下の存在しないにURL対しては404を返すようにする
2018-08-24 05:40:30 +09:00
a0adcf0d1a Merge pull request #2437 from syuilo/develop
8.2.0
2018-08-24 05:38:18 +09:00
93b2b82993 8.2.0 2018-08-24 05:37:42 +09:00
4dee7d91b1 Better charts 2018-08-24 05:37:19 +09:00
839be6477d Return 404 for unknown API 2018-08-24 05:26:26 +09:00
59e2ed8ab0 Merge pull request #2435 from syuilo/master
Master
2018-08-24 03:48:05 +09:00
83790004dd 8.1.0 (#2426) (#2434)
* Update url-preview.vue

* 一時間ごとのグラフも見れるように

* Merge pull request #2423 from syuilo/develop (#2425)

* 8.1.0
2018-08-24 03:47:36 +09:00
b70e9824ac fix(package): update @types/webpack to version 4.4.11 2018-08-23 18:26:42 +00:00
155d49e8ac fix(package): update @types/sharp to version 0.17.10 2018-08-23 18:16:46 +00:00
4ae10ab33d fix(package): update vue-js-modal to version 1.3.19 2018-08-23 14:46:37 +00:00
7124586eb1 New translations ja-JP.yml (French) 2018-08-23 18:12:02 +09:00
74f6ed1851 New translations ja-JP.yml (French) 2018-08-23 18:03:12 +09:00
efae7a7bce 8.1.0 (#2426)
* Update url-preview.vue

* 一時間ごとのグラフも見れるように

* Merge pull request #2423 from syuilo/develop (#2425)

* 8.1.0
2018-08-23 16:38:12 +09:00
e59f13e8ff Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-08-23 16:37:40 +09:00
31ed8949b9 8.1.0 2018-08-23 16:37:32 +09:00
f1174a15e0 Merge pull request #2423 from syuilo/develop (#2425) 2018-08-23 16:37:07 +09:00
912ffae600 Merge pull request #2424 from acid-chicken/patch-4
Fix #2421
2018-08-23 16:36:42 +09:00
71a5662195 一時間ごとのグラフも見れるように 2018-08-23 16:36:23 +09:00
774834a31f Update url-preview.vue 2018-08-23 16:25:36 +09:00
1d9c88e9a1 New translations ja-JP.yml (English) 2018-08-23 05:44:01 +09:00
8eb8243153 New translations ja-JP.yml (Japanese, Kansai) 2018-08-23 03:01:33 +09:00
b4967b862c New translations ja-JP.yml (Spanish) 2018-08-23 03:01:31 +09:00
aee3517736 New translations ja-JP.yml (Russian) 2018-08-23 03:01:28 +09:00
52ff8e84fa New translations ja-JP.yml (Portuguese) 2018-08-23 03:01:26 +09:00
9bb6db649c New translations ja-JP.yml (Polish) 2018-08-23 03:01:24 +09:00
da99be9897 New translations ja-JP.yml (Korean) 2018-08-23 03:01:21 +09:00
2d7ec8a471 New translations ja-JP.yml (Italian) 2018-08-23 03:01:19 +09:00
4cbbfdad1a New translations ja-JP.yml (German) 2018-08-23 03:01:17 +09:00
2924858311 New translations ja-JP.yml (French) 2018-08-23 03:01:14 +09:00
85916bfea1 New translations ja-JP.yml (English) 2018-08-23 03:01:12 +09:00
38ccd9e794 New translations ja-JP.yml (Chinese Simplified) 2018-08-23 03:01:10 +09:00
c64b6be915 New translations ja-JP.yml (Catalan) 2018-08-23 03:01:07 +09:00
56 changed files with 1484 additions and 700 deletions

View File

@ -5,6 +5,16 @@ ChangeLog
This document describes breaking changes only.
8.0.0
-----
### Migration
起動する前に、`node cli/migration/8.0.0`してください。
Please run `node cli/migration/8.0.0` before launch.
7.0.0
-----

View File

@ -58,7 +58,7 @@ common:
friday: "金曜日"
saturday: "土曜日"
reactions:
like: "ええやん"
like: "いいね"
love: "しゅき"
laugh: "笑"
hmm: "ふぅ~む"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,7 +58,7 @@ common:
friday: "金曜日"
saturday: "土曜日"
reactions:
like: "ええやん"
like: "いいね"
love: "Lieben"
laugh: "Lachen"
hmm: "Hmm...?"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet."
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "Vorheriger Monat"
next: "Nächster Monat"
go: "Klicke zur Navigation"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Datei auswählen"
upload: "Dateien von deinem PC hochladen"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "Listen"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "Einstellungen"
signout: "Ausloggen"
dark: "Verdunkeln"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -84,6 +84,7 @@ common:
my-token-regenerated: "Your token has been regenerated, so you will be signed out."
i-like-sushi: "I prefer sushi rather than pudding"
show-reversi-board-labels: "Show row and column labels in Reversi"
use-contrast-reversi-stones: "Make the stone color clear"
verified-user: "Verified account"
disable-animated-mfm: "Disable animated texts in a post"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "Previous month"
next: "Next month"
go: "Click to navigate"
desktop/views/components/charts.vue:
title: "Charts"
per-day: "per Day"
per-hour: "per Hour"
notes: "Posts"
users: "Users"
drive: "Drive"
charts:
notes: "The number of posts: increase/decrease (Combined)"
local-notes: "The number of posts: increase/decrease (Local)"
remote-notes: "The number of posts: increase/decrease (Remote)"
notes-total: "The number of posts: cumulative total"
users: "The number of users: increase/decrease"
users-total: "The number of users: cumulative total"
drive: "Capacity used as the storage: increase/decrease"
drive-total: "Capacity used as the storage: cumulative total"
drive-files: "The number of files on the storage: increase/decrease"
drive-files-total: "The number of files on the storage: cumulative total"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Choose files"
upload: "Upload files from your device"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "Lists"
follow-requests: "Follow requests"
customize: "Customize home layout"
admin: "Admin"
settings: "Settings"
signout: "Sign out"
dark: "Submerge in dark"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "User account unverification settings"
unverify: "Unverify account"
unverified: "The account is now being unverified"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "Posts"
local: "Local"
remote: "Remote"
desktop/views/pages/admin/admin.users-chart.vue:
title: "Users"
local: "Local"
remote: "Remote"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "Drive"
local: "Local"
remote: "Remote"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Only media posts"
is-media-view: "Media view"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "Games"
darkmode: "Dark theme"
settings: "Settings"
admin: "Admin"
about: "About Misskey"
mobile/views/components/user-timeline.vue:
no-notes: "It seems this user hasn't posted anything yet."

View File

@ -58,7 +58,7 @@ common:
friday: "Viernes"
saturday: "Sábado"
reactions:
like: "ええやん"
like: "いいね"
love: "amor"
laugh: "risa"
hmm: "hmm"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado."
i-like-sushi: "Prefiero sushi a pudín"
show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "Desactivar texto animado en una publicación"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "Mes anterior"
next: "Próximo mes"
go: "Click para navegar"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Escoger archivos"
upload: "Cargar archivos de tu dispositivo"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,10 +58,10 @@ common:
friday: "Vendredi"
saturday: "Samedi"
reactions:
like: "ええやん"
like: "J'aime"
love: "Adore"
laugh: "Rire"
hmm: "Hmm ... ?"
hmm: "Hmm ?"
surprise: "Wow"
congrats: "Félicitations !"
angry: "En colère"
@ -69,10 +69,10 @@ common:
rip: "RIP"
pudding: "Pudding"
note-placeholders:
a: "Que faites vous maintenant ?"
a: "Que faites-vous maintenant ?"
b: "Quoi de neuf ?"
c: "Qu'avez-vous en tête ?"
d: "Voulez-vous exprimer quelque chose ?"
d: "Désirez-vous publier quelques mots ?"
e: "Écrivez ici"
f: "En attente de vos écrits"
search: "Recherche"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "Votre token vient d'être généré, vous allez maintenant être déconnecté."
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Compte vérifié"
disable-animated-mfm: "Désactiver les textes animés dans les publications"
reversi:
@ -230,7 +231,7 @@ common/views/components/connect-failed.troubleshooter.vue:
flush: "Vider le cache"
set-version: "Choisissez une version"
common/views/components/messaging.vue:
search-user: "Trouver un·e utilisateur·rice"
search-user: "Trouver un·e utilisateur·trice"
you: "Vous"
no-history: "Pas d'historique"
common/views/components/messaging-room.vue:
@ -378,7 +379,7 @@ common/views/widgets/tips.vue:
tips-line3: "Vous pouvez glisser et déposer des fichiers sur la fenêtre de la note"
tips-line4: "Vous pouvez coller des images à partir du presse-papier sur la fenêtre de la note"
tips-line5: "Vous pouvez téléverser des fichiers sur le Drive en faisant un glisser-déposer"
tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます"
tips-line6: "Vous pouvez déplacer un dossier en le glissant dans le Drive"
tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます"
tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres"
tips-line9: "Misskey est sous licence AGPLv3"
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "Mois dernier"
next: "Mois prochain"
go: "Cliquez pour naviguer"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Sélection de fichiers"
upload: "Téléverser des fichiers à partir de votre ordinateur"
@ -512,7 +531,7 @@ desktop/views/components/following.vue:
empty: "Vous ne suivez aucun compte."
desktop/views/components/friends-maker.vue:
title: "Utilisateurs recommandés :"
empty: "Impossible de trouver des utilisateurs à recommander."
empty: "Impossible de trouver des utilisateurs·trices à recommander."
fetching: "Chargement"
refresh: "Plus"
close: "Fermer"
@ -629,7 +648,7 @@ desktop/views/components/settings.vue:
circle-icons: "Utiliser des icônes circulaires"
gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "Listes"
follow-requests: "Demandes de suivi"
customize: "Personnaliser l'Accueil"
admin: "Admin"
settings: "Réglages"
signout: "Déconnexion"
dark: "Fall in dark"
@ -791,12 +811,12 @@ desktop/views/components/window.vue:
popout: "ポップアウト"
close: "Fermer"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
dashboard: "Tableau de bord"
drive: "Drive"
users: "Utilisateur·rice·s"
update: "Mises à jour"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
dashboard: "Tableau de bord"
all-users: "Tou·te·s les utilisateur·rice·s"
original-users: "Utilisateur·rice·s sur cette instance"
all-notes: "Toutes les publications"
@ -811,25 +831,13 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend: "Suspension levée"
unsuspended: "La suspension de lutilisateur·rice a été levée avec succès"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify-user: "Paramètres de vérification du compte utilisateur"
verify: "Vérification du compte"
verified: "Le compte a été vérifié"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverify: "Ôter la vérification du compte"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Les publications médias uniquement"
is-media-view: "Vue média"
@ -977,7 +985,7 @@ mobile/views/components/follow-button.vue:
follow-request: "Demande d'abonnement"
mobile/views/components/friends-maker.vue:
title: "Abonnez-vous aux utilisateurs"
empty: "Impossible de trouver des utilisateurs à recommander."
empty: "Impossible de trouver des utilisateurs·trices à recommander."
fetching: "Chargement"
refresh: "Voir plus"
close: "Fermer"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "Jeux"
darkmode: "Mode nuit"
settings: "Réglages"
admin: "管理"
about: "À propose de Misskey"
mobile/views/components/user-timeline.vue:
no-notes: "Cette utilisateur semble n'avoir rien poster pour le moment"

View File

@ -58,7 +58,7 @@ common:
friday: "金曜日"
saturday: "土曜日"
reactions:
like: "ええやん"
like: "いいね"
love: "しゅき"
laugh: "笑"
hmm: "ふぅ~む"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -473,6 +473,25 @@ desktop/views/components/calendar.vue:
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -915,8 +934,8 @@ desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
invite: "招待"
desktop/views/pages/admin/admin.suspend-user.vue:
@ -939,21 +958,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -964,6 +968,12 @@ desktop/views/pages/deck/deck.note.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
desktop/views/pages/welcome.vue:
about: "詳しく..."
gotit: "わかった"

View File

@ -84,6 +84,7 @@ common:
my-token-regenerated: "あんさんのトークンが更新されたらしいわ。すまんがとりあえずサインアウトすんで。"
i-like-sushi: "寿司(のほうがプリンよりむしろ)ウマい、タコ焼きはあらへんけど。"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示や!"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストをつけんで!"
verified-user: "アメちゃん付きアカウント"
disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める"
reversi:
@ -190,17 +191,17 @@ common/views/components/games/reversi/reversi.index.vue:
common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "ゲームの設定"
choose-map: "マップを選択"
random: "ランダム"
random: "いんじゃんほい"
black-or-white: "先手/後手"
black-is: "{}が黒"
black-is: "{}が黒"
rules: "ルール"
is-llotheo: "石の少ない方が勝ち(ロセオ)"
is-llotheo: "石の少ない方が勝ちや!(ロセオ)"
looped-map: "ループマップ"
can-put-everywhere: "どこでも置けるモード"
can-put-everywhere: "どこに置いてもええモード"
settings-of-the-bot: "Botの設定"
this-game-is-started-soon: "ゲームは数秒後に開始されます"
waiting-for-other: "相手の準備が完了すのを待っています"
waiting-for-me: "あなたの準備が完了すのを待っています"
this-game-is-started-soon: "ゲームは数秒後に開始されんで"
waiting-for-other: "相手の準備が完了すのを待ってんで"
waiting-for-me: "あんさんの準備が完了すのを待ってんで"
waiting-for-both: "準備中"
cancel: "やめとくわ"
ready: "準備完了"
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,7 +58,7 @@ common:
friday: "금요일"
saturday: "토요일"
reactions:
like: "ええやん"
like: "いいね"
love: "좋아"
laugh: "크크"
hmm: "음..."
@ -84,6 +84,7 @@ common:
my-token-regenerated: "당신의 토큰이 업데이트되어 있기 때문에 로그 아웃합니다."
i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아"
show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,7 +58,7 @@ common:
friday: "Piątek"
saturday: "Sobota"
reactions:
like: "ええやん"
like: "いいね"
love: "Kocham"
laugh: "Śmieszne"
hmm: "Hmm…?"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "Twój token został wygenerowany. Zostaniesz wylogowany."
i-like-sushi: "Wolę sushi od puddingu"
show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "Wyłącz animowany tekst we wpisach"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "Poprzedni miesiąc"
next: "Następny miesiąc"
go: "Naciśnij, aby przejść"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Wybierz plik"
upload: "Wyślij pliki z Twojego komputera"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "Listy"
follow-requests: "Prośby o śledzenie"
customize: "Dostosuj stronę główną"
admin: "管理"
settings: "Ustawienia"
signout: "Wyloguj się"
dark: "Sprowadź ciemność"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Tylko wpisy z zawartością multimedialną"
is-media-view: "Widok multimediów"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "Gry"
darkmode: "Tryb ciemny"
settings: "Ustawienia"
admin: "管理"
about: "O Misskey"
mobile/views/components/user-timeline.vue:
no-notes: "Wygląda na to, że ten użytkownik nie opublikował jeszcze niczego"

View File

@ -58,7 +58,7 @@ common:
friday: "sexta"
saturday: "sábado"
reactions:
like: "Legal..."
like: "いいね"
love: "Amei"
laugh: "Riso"
hmm: "Hmm...?"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "Eu prefiro sushi a pudim"
show-reversi-board-labels: "Mostrar etiquetas de colunas e linhas no Reversi"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Conta verificada"
disable-animated-mfm: "Desativar texto animado nas publicações"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,7 +58,7 @@ common:
friday: "金曜日"
saturday: "土曜日"
reactions:
like: "ええやん"
like: "いいね"
love: "しゅき"
laugh: "笑"
hmm: "ふぅ~む"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -58,7 +58,7 @@ common:
friday: "金曜日"
saturday: "土曜日"
reactions:
like: "ええやん"
like: "いいね"
love: "しゅき"
laugh: "笑"
hmm: "ふぅ~む"
@ -84,6 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi:
@ -423,6 +424,24 @@ desktop/views/components/calendar.vue:
prev: "前の月"
next: "次の月"
go: "クリックして時間遡行"
desktop/views/components/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計"
users: "ユーザーの増減"
users-total: "ユーザーの累計"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の累計"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "ファイル選択中"
upload: "PCからドライブにファイルをアップロード"
@ -754,6 +773,7 @@ desktop/views/components/ui.header.account.vue:
lists: "リスト"
follow-requests: "フォロー申請"
customize: "ホームのカスタマイズ"
admin: "管理"
settings: "設定"
signout: "サインアウト"
dark: "闇に飲まれる"
@ -818,18 +838,6 @@ desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.notes-chart.vue:
title: "投稿"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.users-chart.vue:
title: "ユーザー"
local: "ローカル"
remote: "リモート"
desktop/views/pages/admin/admin.drive-chart.vue:
title: "ドライブ"
local: "ローカル"
remote: "リモート"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue:
game: "ゲーム"
darkmode: "ダークモード"
settings: "設定"
admin: "管理"
about: "Misskeyについて"
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"

View File

@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "8.0.0",
"clientVersion": "1.0.8790",
"version": "8.13.0",
"clientVersion": "1.0.9001",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@ -60,7 +60,7 @@
"@types/mocha": "5.2.3",
"@types/mongodb": "3.1.4",
"@types/ms": "0.7.30",
"@types/node": "10.7.1",
"@types/node": "10.9.2",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.2.0",
@ -70,14 +70,14 @@
"@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.27",
"@types/sharp": "0.17.9",
"@types/sharp": "0.17.10",
"@types/showdown": "1.7.5",
"@types/single-line-log": "1.1.0",
"@types/speakeasy": "2.0.2",
"@types/systeminformation": "3.23.0",
"@types/tmp": "0.0.33",
"@types/uuid": "3.4.3",
"@types/webpack": "4.4.10",
"@types/webpack": "4.4.11",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.39",
"@types/ws": "6.0.0",
@ -89,6 +89,7 @@
"bootstrap-vue": "2.0.0-rc.11",
"cafy": "11.3.0",
"chalk": "2.4.1",
"chart.js": "2.7.2",
"commander": "2.17.1",
"crc-32": "1.2.0",
"css-loader": "1.0.0",
@ -149,6 +150,7 @@
"loader-utils": "1.1.0",
"lodash.assign": "4.2.0",
"mecab-async": "0.1.2",
"merge-options": "1.0.1",
"minio": "7.0.0",
"mkdirp": "0.5.1",
"mocha": "5.2.0",
@ -192,7 +194,7 @@
"stylus": "0.54.5",
"stylus-loader": "3.0.2",
"summaly": "2.1.4",
"systeminformation": "3.42.9",
"systeminformation": "3.43.0",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"tmp": "0.0.33",
@ -206,8 +208,9 @@
"uuid": "3.3.2",
"v-animate-css": "0.0.2",
"vue": "2.5.17",
"vue-chartjs": "3.4.0",
"vue-cropperjs": "2.2.1",
"vue-js-modal": "1.3.18",
"vue-js-modal": "1.3.19",
"vue-json-tree-view": "2.1.4",
"vue-loader": "15.4.0",
"vue-router": "3.0.1",

View File

@ -51,8 +51,9 @@
}
}
if (settings) {
if (settings.device.lang) lang = settings.device.lang;
if (settings && settings.device.lang &&
LANGS.includes(settings.device.lang)) {
lang = settings.device.lang;
}
//#endregion

View File

@ -176,7 +176,7 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
.twitter
.player
position relative
width 100%

View File

@ -1,8 +1,10 @@
import Vue from 'vue';
Vue.filter('bytes', (v, digits = 0) => {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (v == 0) return '0Byte';
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (v == 0) return '0';
const isMinus = v < 0;
if (isMinus) v = -v;
const i = Math.floor(Math.log(v) / Math.log(1024));
return (v / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
return (isMinus ? '-' : '') + (v / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
});

View File

@ -25,6 +25,7 @@ import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue';
import MkDeck from './views/pages/deck/deck.vue';
import MkAdmin from './views/pages/admin/admin.vue';
import MkStats from './views/pages/stats/stats.vue';
import MkUser from './views/pages/user/user.vue';
import MkFavorites from './views/pages/favorites.vue';
import MkSelectDrive from './views/pages/selectdrive.vue';
@ -57,6 +58,7 @@ init(async (launch) => {
{ path: '/', name: 'index', component: MkIndex },
{ path: '/deck', name: 'deck', component: MkDeck },
{ path: '/admin', name: 'admin', component: MkAdmin },
{ path: '/stats', name: 'stats', component: MkStats },
{ path: '/i/customize-home', component: MkHomeCustomize },
{ path: '/i/favorites', component: MkFavorites },
{ path: '/i/messaging/:user', component: MkMessagingRoom },
@ -94,7 +96,7 @@ init(async (launch) => {
/**
* Init Notification
*/
if ('Notification' in window) {
if ('Notification' in window && os.store.getters.isSignedIn) {
// 許可を得ていなかったらリクエスト
if ((Notification as any).permission == 'default') {
await Notification.requestPermission();

View File

@ -0,0 +1,42 @@
import Vue from 'vue';
import { Line } from 'vue-chartjs';
import * as mergeOptions from 'merge-options';
export default Vue.extend({
extends: Line,
props: {
data: {
required: true
},
opts: {
required: false
}
},
watch: {
data() {
this.render();
}
},
mounted() {
this.render();
},
methods: {
render() {
this.renderChart(this.data, mergeOptions({
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
type: 'time',
distribution: 'series'
}]
},
tooltips: {
intersect: false,
mode: 'x',
position: 'nearest'
}
}, this.opts || {}));
}
}
});

View File

@ -0,0 +1,585 @@
<template>
<div class="gkgckalzgidaygcxnugepioremxvxvpt">
<header>
<b>%i18n:@title%:</b>
<select v-model="chartType">
<optgroup label="%i18n:@users%">
<option value="users">%i18n:@charts.users%</option>
<option value="users-total">%i18n:@charts.users-total%</option>
</optgroup>
<optgroup label="%i18n:@notes%">
<option value="notes">%i18n:@charts.notes%</option>
<option value="local-notes">%i18n:@charts.local-notes%</option>
<option value="remote-notes">%i18n:@charts.remote-notes%</option>
<option value="notes-total">%i18n:@charts.notes-total%</option>
</optgroup>
<optgroup label="%i18n:@drive%">
<option value="drive-files">%i18n:@charts.drive-files%</option>
<option value="drive-files-total">%i18n:@charts.drive-files-total%</option>
<option value="drive">%i18n:@charts.drive%</option>
<option value="drive-total">%i18n:@charts.drive-total%</option>
</optgroup>
</select>
<div>
<span @click="span = 'day'" :class="{ active: span == 'day' }">%i18n:@per-day%</span> | <span @click="span = 'hour'" :class="{ active: span == 'hour' }">%i18n:@per-hour%</span>
</div>
</header>
<div>
<x-chart v-if="chart" :data="data[0]" :opts="data[1]"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import XChart from './charts.chart.ts';
const colors = {
local: 'rgb(246, 88, 79)',
remote: 'rgb(65, 221, 222)',
localPlus: 'rgb(52, 178, 118)',
remotePlus: 'rgb(158, 255, 209)',
localMinus: 'rgb(255, 97, 74)',
remoteMinus: 'rgb(255, 149, 134)'
};
const rgba = (color: string): string => {
return color.replace('rgb', 'rgba').replace(')', ', 0.1)');
};
export default Vue.extend({
components: {
XChart
},
data() {
return {
chart: null,
chartType: 'notes',
span: 'hour'
};
},
computed: {
data(): any {
if (this.chart == null) return null;
switch (this.chartType) {
case 'users': return this.usersChart(false);
case 'users-total': return this.usersChart(true);
case 'notes': return this.notesChart('combined');
case 'local-notes': return this.notesChart('local');
case 'remote-notes': return this.notesChart('remote');
case 'notes-total': return this.notesTotalChart();
case 'drive': return this.driveChart();
case 'drive-total': return this.driveTotalChart();
case 'drive-files': return this.driveFilesChart();
case 'drive-files-total': return this.driveFilesTotalChart();
}
},
stats(): any[] {
return (
this.span == 'day' ? this.chart.perDay :
this.span == 'hour' ? this.chart.perHour :
null
);
}
},
created() {
(this as any).api('chart').then(chart => {
this.chart = chart;
});
},
methods: {
notesChart(type: string): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
normal: type == 'local' ? x.notes.local.diffs.normal : type == 'remote' ? x.notes.remote.diffs.normal : x.notes.local.diffs.normal + x.notes.remote.diffs.normal,
reply: type == 'local' ? x.notes.local.diffs.reply : type == 'remote' ? x.notes.remote.diffs.reply : x.notes.local.diffs.reply + x.notes.remote.diffs.reply,
renote: type == 'local' ? x.notes.local.diffs.renote : type == 'remote' ? x.notes.remote.diffs.renote : x.notes.local.diffs.renote + x.notes.remote.diffs.renote,
all: type == 'local' ? (x.notes.local.inc + -x.notes.local.dec) : type == 'remote' ? (x.notes.remote.inc + -x.notes.remote.dec) : (x.notes.local.inc + -x.notes.local.dec) + (x.notes.remote.inc + -x.notes.remote.dec)
}));
return [{
datasets: [{
label: 'All',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.all }))
}, {
label: 'Renotes',
fill: true,
backgroundColor: 'rgba(161, 222, 65, 0.1)',
borderColor: '#a1de41',
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.renote }))
}, {
label: 'Replies',
fill: true,
backgroundColor: 'rgba(247, 121, 108, 0.1)',
borderColor: '#f7796c',
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.reply }))
}, {
label: 'Normal',
fill: true,
backgroundColor: 'rgba(65, 221, 222, 0.1)',
borderColor: '#41ddde',
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.normal }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('number')(value);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`;
}
}
}
}];
},
notesTotalChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localCount: x.notes.local.total,
remoteCount: x.notes.remote.total
}));
return [{
datasets: [{
label: 'Combined',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount }))
}, {
label: 'Local',
fill: true,
backgroundColor: rgba(colors.local),
borderColor: colors.local,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localCount }))
}, {
label: 'Remote',
fill: true,
backgroundColor: rgba(colors.remote),
borderColor: colors.remote,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteCount }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('number')(value);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`;
}
}
}
}];
},
usersChart(total: boolean): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localCount: total ? x.users.local.total : (x.users.local.inc + -x.users.local.dec),
remoteCount: total ? x.users.remote.total : (x.users.remote.inc + -x.users.remote.dec)
}));
return [{
datasets: [{
label: 'Combined',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount }))
}, {
label: 'Local',
fill: true,
backgroundColor: rgba(colors.local),
borderColor: colors.local,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localCount }))
}, {
label: 'Remote',
fill: true,
backgroundColor: rgba(colors.remote),
borderColor: colors.remote,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteCount }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('number')(value);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`;
}
}
}
}];
},
driveChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localInc: x.drive.local.incSize,
localDec: -x.drive.local.decSize,
remoteInc: x.drive.remote.incSize,
remoteDec: -x.drive.remote.decSize,
}));
return [{
datasets: [{
label: 'All',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec }))
}, {
label: 'Local +',
fill: true,
backgroundColor: rgba(colors.localPlus),
borderColor: colors.localPlus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localInc }))
}, {
label: 'Local -',
fill: true,
backgroundColor: rgba(colors.localMinus),
borderColor: colors.localMinus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localDec }))
}, {
label: 'Remote +',
fill: true,
backgroundColor: rgba(colors.remotePlus),
borderColor: colors.remotePlus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteInc }))
}, {
label: 'Remote -',
fill: true,
backgroundColor: rgba(colors.remoteMinus),
borderColor: colors.remoteMinus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteDec }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('bytes')(value, 1);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('bytes')(tooltipItem.yLabel, 1)}`;
}
}
}
}];
},
driveTotalChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localSize: x.drive.local.totalSize,
remoteSize: x.drive.remote.totalSize
}));
return [{
datasets: [{
label: 'Combined',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteSize + x.localSize }))
}, {
label: 'Local',
fill: true,
backgroundColor: rgba(colors.local),
borderColor: colors.local,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localSize }))
}, {
label: 'Remote',
fill: true,
backgroundColor: rgba(colors.remote),
borderColor: colors.remote,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteSize }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('bytes')(value, 1);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('bytes')(tooltipItem.yLabel, 1)}`;
}
}
}
}];
},
driveFilesChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localInc: x.drive.local.incCount,
localDec: -x.drive.local.decCount,
remoteInc: x.drive.remote.incCount,
remoteDec: -x.drive.remote.decCount
}));
return [{
datasets: [{
label: 'All',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec }))
}, {
label: 'Local +',
fill: true,
backgroundColor: rgba(colors.localPlus),
borderColor: colors.localPlus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localInc }))
}, {
label: 'Local -',
fill: true,
backgroundColor: rgba(colors.localMinus),
borderColor: colors.localMinus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localDec }))
}, {
label: 'Remote +',
fill: true,
backgroundColor: rgba(colors.remotePlus),
borderColor: colors.remotePlus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteInc }))
}, {
label: 'Remote -',
fill: true,
backgroundColor: rgba(colors.remoteMinus),
borderColor: colors.remoteMinus,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteDec }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('number')(value);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`;
}
}
}
}];
},
driveFilesTotalChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
localCount: x.drive.local.totalCount,
remoteCount: x.drive.remote.totalCount,
}));
return [{
datasets: [{
label: 'Combined',
fill: false,
borderColor: '#555',
borderWidth: 2,
borderDash: [4, 4],
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localCount + x.remoteCount }))
}, {
label: 'Local',
fill: true,
backgroundColor: rgba(colors.local),
borderColor: colors.local,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.localCount }))
}, {
label: 'Remote',
fill: true,
backgroundColor: rgba(colors.remote),
borderColor: colors.remote,
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
data: data.map(x => ({ t: x.date, y: x.remoteCount }))
}]
}, {
scales: {
yAxes: [{
ticks: {
callback: value => {
return Vue.filter('number')(value);
}
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || '';
return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`;
}
}
}
}];
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
.gkgckalzgidaygcxnugepioremxvxvpt
padding 32px
background #fff
box-shadow 0 2px 8px rgba(#000, 0.1)
*
user-select none
> header
display flex
margin 0 0 1em 0
padding 0 0 8px 0
font-size 1em
color #555
border-bottom solid 1px #eee
> b
margin-right 8px
> *:last-child
margin-left auto
*
&:not(.active)
color $theme-color
cursor pointer
> div
> *
display block
height 300px
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="obdskegsannmntldydackcpzezagxqfy card">
<div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card">
<header>%i18n:@dashboard%</header>
<div v-if="stats" class="stats">
<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>

View File

@ -1,51 +0,0 @@
<template>
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<polyline
:points="points"
fill="none"
stroke-width="1"
stroke="#555"/>
</svg>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
chart: {
required: true
},
type: {
type: String,
required: true
}
},
data() {
return {
viewBoxX: 365,
viewBoxY: 70,
points: null
};
},
created() {
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.drive.local.totalSize : d.drive.remote.totalSize));
if (peak != 0) {
const data = this.chart.slice().reverse().map(x => ({
size: this.type == 'local' ? x.drive.local.totalSize : x.drive.remote.totalSize
}));
this.points = data.map((d, i) => `${i},${(1 - (d.size / peak)) * this.viewBoxY}`).join(' ');
}
}
});
</script>
<style lang="stylus" scoped>
svg
display block
padding 10px
width 100%
</style>

View File

@ -1,34 +0,0 @@
<template>
<div class="card">
<header>%i18n:@title%</header>
<div class="card">
<header>%i18n:@local%</header>
<x-chart v-if="chart" :chart="chart" type="local"/>
</div>
<div class="card">
<header>%i18n:@remote%</header>
<x-chart v-if="chart" :chart="chart" type="remote"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XChart from "./admin.drive-chart.chart.vue";
export default Vue.extend({
components: {
XChart
},
props: {
chart: {
required: true
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
</style>

View File

@ -1,76 +0,0 @@
<template>
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<polyline
:points="pointsNote"
fill="none"
stroke-width="1"
stroke="#41ddde"/>
<polyline
:points="pointsReply"
fill="none"
stroke-width="1"
stroke="#f7796c"/>
<polyline
:points="pointsRenote"
fill="none"
stroke-width="1"
stroke="#a1de41"/>
<polyline
:points="pointsTotal"
fill="none"
stroke-width="1"
stroke="#555"
stroke-dasharray="2 2"/>
</svg>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
chart: {
required: true
},
type: {
type: String,
required: true
}
},
data() {
return {
viewBoxX: 365,
viewBoxY: 70,
pointsNote: null,
pointsReply: null,
pointsRenote: null,
pointsTotal: null
};
},
created() {
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.notes.local.diff : d.notes.remote.diff));
if (peak != 0) {
const data = this.chart.slice().reverse().map(x => ({
normal: this.type == 'local' ? x.notes.local.diffs.normal : x.notes.remote.diffs.normal,
reply: this.type == 'local' ? x.notes.local.diffs.reply : x.notes.remote.diffs.reply,
renote: this.type == 'local' ? x.notes.local.diffs.renote : x.notes.remote.diffs.renote,
total: this.type == 'local' ? x.notes.local.diff : x.notes.remote.diff
}));
this.pointsNote = data.map((d, i) => `${i},${(1 - (d.normal / peak)) * this.viewBoxY}`).join(' ');
this.pointsReply = data.map((d, i) => `${i},${(1 - (d.reply / peak)) * this.viewBoxY}`).join(' ');
this.pointsRenote = data.map((d, i) => `${i},${(1 - (d.renote / peak)) * this.viewBoxY}`).join(' ');
this.pointsTotal = data.map((d, i) => `${i},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ');
}
}
});
</script>
<style lang="stylus" scoped>
svg
display block
padding 10px
width 100%
</style>

View File

@ -1,34 +0,0 @@
<template>
<div class="card">
<header>%i18n:@title%</header>
<div class="card">
<header>%i18n:@local%</header>
<x-chart v-if="chart" :chart="chart" type="local"/>
</div>
<div class="card">
<header>%i18n:@remote%</header>
<x-chart v-if="chart" :chart="chart" type="remote"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XChart from "./admin.notes-chart.chart.vue";
export default Vue.extend({
components: {
XChart
},
props: {
chart: {
required: true
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="card">
<div class="mk-admin-card">
<header>%i18n:@suspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="suspendUser" :disabled="suspending">%i18n:@suspend%</button>

View File

@ -1,5 +1,5 @@
<template>
<div class="card">
<div class="mk-admin-card">
<header>%i18n:@unsuspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</button>

View File

@ -1,5 +1,5 @@
<template>
<div class="card">
<div class="mk-admin-card">
<header>%i18n:@unverify-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</button>

View File

@ -1,51 +0,0 @@
<template>
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<polyline
:points="points"
fill="none"
stroke-width="1"
stroke="#555"/>
</svg>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
chart: {
required: true
},
type: {
type: String,
required: true
}
},
data() {
return {
viewBoxX: 365,
viewBoxY: 70,
points: null
};
},
created() {
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.users.local.diff : d.users.remote.diff));
if (peak != 0) {
const data = this.chart.slice().reverse().map(x => ({
count: this.type == 'local' ? x.users.local.diff : x.users.remote.diff
}));
this.points = data.map((d, i) => `${i},${(1 - (d.count / peak)) * this.viewBoxY}`).join(' ');
}
}
});
</script>
<style lang="stylus" scoped>
svg
display block
padding 10px
width 100%
</style>

View File

@ -1,34 +0,0 @@
<template>
<div class="card">
<header>%i18n:@title%</header>
<div class="card">
<header>%i18n:@local%</header>
<x-chart v-if="chart" :chart="chart" type="local"/>
</div>
<div class="card">
<header>%i18n:@remote%</header>
<x-chart v-if="chart" :chart="chart" type="remote"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XChart from "./admin.users-chart.chart.vue";
export default Vue.extend({
components: {
XChart
},
props: {
chart: {
required: true
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="card">
<div class="mk-admin-card">
<header>%i18n:@verify-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="verifyUser" :disabled="verifying">%i18n:@verify%</button>

View File

@ -11,9 +11,7 @@
<main>
<div v-show="page == 'dashboard'">
<x-dashboard/>
<x-users-chart :chart="chart"/>
<x-notes-chart :chart="chart"/>
<x-drive-chart :chart="chart"/>
<x-charts/>
</div>
<div v-if="page == 'users'">
<x-suspend-user/>
@ -34,9 +32,7 @@ import XSuspendUser from "./admin.suspend-user.vue";
import XUnsuspendUser from "./admin.unsuspend-user.vue";
import XVerifyUser from "./admin.verify-user.vue";
import XUnverifyUser from "./admin.unverify-user.vue";
import XUsersChart from "./admin.users-chart.vue";
import XNotesChart from "./admin.notes-chart.vue";
import XDriveChart from "./admin.drive-chart.vue";
import XCharts from "../../components/charts.vue";
export default Vue.extend({
components: {
@ -45,21 +41,13 @@ export default Vue.extend({
XUnsuspendUser,
XVerifyUser,
XUnverifyUser,
XUsersChart,
XNotesChart,
XDriveChart
XCharts
},
data() {
return {
page: 'dashboard',
chart: null
page: 'dashboard'
};
},
created() {
(this as any).api('admin/chart').then(chart => {
this.chart = chart;
});
},
methods: {
nav(page: string) {
this.page = page;
@ -115,7 +103,7 @@ export default Vue.extend({
> div
max-width 800px
.card
.mk-admin-card
padding 32px
background #fff
box-shadow 0 2px 8px rgba(#000, 0.1)

View File

@ -0,0 +1,64 @@
<template>
<div class="tcrwdhwpuxrwmcttxjcsehgpagpstqey">
<div v-if="stats" class="stats">
<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>
<div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div>
<div><b>%fa:pen% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div>
<div><span>%fa:pen% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div>
</div>
<div>
<x-charts/>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XCharts from "../../components/charts.vue";
export default Vue.extend({
components: {
XCharts
},
data() {
return {
stats: null
};
},
created() {
(this as any).api('stats').then(stats => {
this.stats = stats;
});
},
});
</script>
<style lang="stylus">
@import '~const.styl'
.tcrwdhwpuxrwmcttxjcsehgpagpstqey
width 100%
padding 16px
> .stats
display flex
justify-content center
margin-bottom 16px
padding 32px
background #fff
box-shadow 0 2px 8px rgba(#000, 0.1)
> div
flex 1
text-align center
> *:first-child
display block
color $theme-color
> *:last-child
font-size 70%
> div
max-width 800px
</style>

View File

@ -11,7 +11,7 @@
<a class="avatar">
<img :src="user.avatarUrl" alt="avatar"/>
</a>
<mk-mute-button v-if="$store.state.i.id != user.id" :user="user"/>
<mk-mute-button v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
<mk-follow-button v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
</div>
<div class="title">

View File

@ -8,8 +8,14 @@ export default Stats;
export interface IStats {
_id: mongo.ObjectID;
/**
* 集計日時
*/
date: Date;
/**
* 集計期間
*/
span: 'day' | 'hour';
/**
@ -18,26 +24,36 @@ export interface IStats {
users: {
local: {
/**
* この日時点での、ローカルのユーザーの総計
* 集計期間時点での、全ユーザー数 (ローカル)
*/
total: number;
/**
* ローカルのユーザー数の前日比
* 増加したユーザー数 (ローカル)
*/
diff: number;
inc: number;
/**
* 減少したユーザー数 (ローカル)
*/
dec: number;
};
remote: {
/**
* この日時点での、リモートのユーザーの総計
* 集計期間時点での、全ユーザー数 (リモート)
*/
total: number;
/**
* リモートのユーザー数の前日比
* 増加したユーザー数 (リモート)
*/
diff: number;
inc: number;
/**
* 減少したユーザー数 (リモート)
*/
dec: number;
};
};
@ -47,28 +63,33 @@ export interface IStats {
notes: {
local: {
/**
* この日時点での、ローカルの投稿の総計
* 集計期間時点での、全投稿数 (ローカル)
*/
total: number;
/**
* ローカルの投稿数の前日比
* 増加した投稿数 (ローカル)
*/
diff: number;
inc: number;
/**
* 減少した投稿数 (ローカル)
*/
dec: number;
diffs: {
/**
* ローカルの通常の投稿数の前日比
* 通常の投稿数の差分 (ローカル)
*/
normal: number;
/**
* ローカルのリプライの投稿数の前日比
* リプライの投稿数の差分 (ローカル)
*/
reply: number;
/**
* ローカルのRenoteの投稿数の前日比
* Renoteの投稿数の差分 (ローカル)
*/
renote: number;
};
@ -76,28 +97,33 @@ export interface IStats {
remote: {
/**
* この日時点での、リモートの投稿の総計
* 集計期間時点での、全投稿数 (リモート)
*/
total: number;
/**
* リモートの投稿数の前日比
* 増加した投稿数 (リモート)
*/
diff: number;
inc: number;
/**
* 減少した投稿数 (リモート)
*/
dec: number;
diffs: {
/**
* リモートの通常の投稿数の前日比
* 通常の投稿数の差分 (リモート)
*/
normal: number;
/**
* リモートのリプライの投稿数の前日比
* リプライの投稿数の差分 (リモート)
*/
reply: number;
/**
* リモートのRenoteの投稿数の前日比
* Renoteの投稿数の差分 (リモート)
*/
renote: number;
};
@ -110,46 +136,66 @@ export interface IStats {
drive: {
local: {
/**
* この日時点での、ローカルのドライブファイル数の総計
* 集計期間時点での、ドライブファイル数 (ローカル)
*/
totalCount: number;
/**
* この日時点での、ローカルのドライブファイルサイズの総計
* 集計期間時点での、ドライブファイルの合計サイズ (ローカル)
*/
totalSize: number;
/**
* ローカルのドライブファイル数の前日比
* 増加したドライブファイル数 (ローカル)
*/
diffCount: number;
incCount: number;
/**
* ローカルのドライブファイルサイズの前日比
* 増加したドライブ使用量 (ローカル)
*/
diffSize: number;
incSize: number;
/**
* 減少したドライブファイル数 (ローカル)
*/
decCount: number;
/**
* 減少したドライブ使用量 (ローカル)
*/
decSize: number;
};
remote: {
/**
* この日時点での、リモートのドライブファイル数の総計
* 集計期間時点での、ドライブファイル数 (リモート)
*/
totalCount: number;
/**
* この日時点での、リモートのドライブファイルサイズの総計
* 集計期間時点での、ドライブファイルの合計サイズ (リモート)
*/
totalSize: number;
/**
* リモートのドライブファイル数の前日比
* 増加したドライブファイル数 (リモート)
*/
diffCount: number;
incCount: number;
/**
* リモートのドライブファイルサイズの前日比
* 増加したドライブ使用量 (リモート)
*/
diffSize: number;
incSize: number;
/**
* 減少したドライブファイル数 (リモート)
*/
decCount: number;
/**
* 減少したドライブ使用量 (リモート)
*/
decSize: number;
};
};
}

View File

@ -131,5 +131,7 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
//#endregion
// リモートサーバーからフェッチしてきて登録
return await createNote(value, resolver);
// ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにートが生成されるが
// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
return await createNote(uri, resolver);
}

View File

@ -166,8 +166,8 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs
const avatarId = avatar ? avatar._id : null;
const bannerId = banner ? banner._id : null;
const avatarUrl = avatar && avatar.metadata.url ? avatar.metadata.url : null;
const bannerUrl = banner && banner.metadata.url ? banner.metadata.url : null;
const avatarUrl = (avatar && avatar.metadata.thumbnailUrl) ? avatar.metadata.thumbnailUrl : (avatar && avatar.metadata.url) ? avatar.metadata.url : null;
const bannerUrl = (banner && banner.metadata.url) ? banner.metadata.url : null;
await User.update({ _id: user._id }, {
$set: {
@ -255,7 +255,7 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver)
sharedInbox: person.sharedInbox,
avatarId: avatar ? avatar._id : null,
bannerId: banner ? banner._id : null,
avatarUrl: avatar && avatar.metadata.url ? avatar.metadata.url : null,
avatarUrl: (avatar && avatar.metadata.thumbnailUrl) ? avatar.metadata.thumbnailUrl : (avatar && avatar.metadata.url) ? avatar.metadata.url : null,
bannerUrl: banner && banner.metadata.url ? banner.metadata.url : null,
description: htmlToMFM(person.summary),
followersCount,

View File

@ -6,6 +6,7 @@ export default (object: any, note: INote) => {
return {
id: `${config.url}/notes/${note._id}`,
actor: `${config.url}/users/${note.userId}`,
type: 'Announce',
published: note.createdAt.toISOString(),
to: ['https://www.w3.org/ns/activitystreams#Public'],

View File

@ -1,4 +1,17 @@
export default (object: any) => ({
type: 'Create',
object
});
import config from '../../../config';
import { INote } from '../../../models/note';
export default (object: any, note: INote) => {
const activity = {
id: `${config.url}/notes/${note._id}/activity`,
actor: `${config.url}/users/${note.userId}`,
type: 'Create',
published: note.createdAt.toISOString(),
object
} as any;
if (object.to) activity.to = object.to;
if (object.cc) activity.cc = object.cc;
return activity;
};

View File

@ -1,4 +1,8 @@
export default (object: any) => ({
import config from '../../../config';
import { ILocalUser } from "../../../models/user";
export default (object: any, user: ILocalUser) => ({
type: 'Delete',
actor: `${config.url}/users/${user._id}`,
object
});

View File

@ -1,7 +1,16 @@
export default (x: any) => Object.assign({
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{ Hashtag: 'as:Hashtag' }
]
}, x);
import config from '../../../config';
import * as uuid from 'uuid';
export default (x: any) => {
if (x !== null && typeof x === 'object' && x.id == null) {
x.id = `${config.url}/${uuid.v4()}`;
}
return Object.assign({
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{ Hashtag: 'as:Hashtag' }
]
}, x);
};

View File

@ -1,4 +1,8 @@
export default (object: any) => ({
import config from '../../../config';
import { ILocalUser, IUser } from "../../../models/user";
export default (object: any, user: ILocalUser | IUser) => ({
type: 'Undo',
actor: `${config.url}/users/${user._id}`,
object
});

View File

@ -19,6 +19,9 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso
port,
method: 'POST',
path: pathname + search,
headers: {
'Content-Type': 'application/activity+json'
}
}, res => {
log(`${url} --> ${res.statusCode}`);
@ -32,7 +35,7 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso
sign(req, {
authorizationHeaderName: 'Signature',
key: user.keypair,
keyId: `acct:${user.username}@${config.host}`
keyId: `${config.url}/users/${user._id}/publickey`
});
// Signature: Signature ... => Signature: ...

View File

@ -25,7 +25,7 @@ function inbox(ctx: Router.IRouterContext) {
ctx.req.headers.authorization = 'Signature ' + ctx.req.headers.signature;
try {
signature = httpSignature.parseRequest(ctx.req);
signature = httpSignature.parseRequest(ctx.req, { 'headers': [] });
} catch (e) {
ctx.status = 401;
return;

View File

@ -1,103 +0,0 @@
import Stats, { IStats } from '../../../../models/stats';
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export const meta = {
requireCredential: true,
requireAdmin: true
};
export default (params: any) => new Promise(async (res, rej) => {
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
const stats = await Stats.find({
span: 'day',
date: {
$gt: new Date(y - 1, m, d)
}
}, {
sort: {
date: -1
},
fields: {
_id: 0
}
});
const chart: Array<Omit<IStats, '_id'>> = [];
for (let i = 364; i >= 0; i--) {
const day = new Date(y, m, d - i);
const stat = stats.find(s => s.date.getTime() == day.getTime());
if (stat) {
chart.unshift(stat);
} else { // 隙間埋め
const mostRecent = stats.find(s => s.date.getTime() < day.getTime());
if (mostRecent) {
chart.unshift(Object.assign({}, mostRecent, {
date: day
}));
} else {
chart.unshift({
date: day,
span: 'day',
users: {
local: {
total: 0,
diff: 0
},
remote: {
total: 0,
diff: 0
}
},
notes: {
local: {
total: 0,
diff: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
},
remote: {
total: 0,
diff: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
}
},
drive: {
local: {
totalCount: 0,
totalSize: 0,
diffCount: 0,
diffSize: 0
},
remote: {
totalCount: 0,
totalSize: 0,
diffCount: 0,
diffSize: 0
}
}
});
}
}
}
chart.forEach(x => {
delete x.date;
});
res(chart);
});

View File

@ -0,0 +1,239 @@
import Stats, { IStats } from '../../../models/stats';
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
function migrateStats(stats: IStats[]) {
stats.forEach(stat => {
const isOldData =
stat.users.local.inc == null ||
stat.users.local.dec == null ||
stat.users.remote.inc == null ||
stat.users.remote.dec == null ||
stat.notes.local.inc == null ||
stat.notes.local.dec == null ||
stat.notes.remote.inc == null ||
stat.notes.remote.dec == null ||
stat.drive.local.incCount == null ||
stat.drive.local.decCount == null ||
stat.drive.local.incSize == null ||
stat.drive.local.decSize == null ||
stat.drive.remote.incCount == null ||
stat.drive.remote.decCount == null ||
stat.drive.remote.incSize == null ||
stat.drive.remote.decSize == null;
if (!isOldData) return;
stat.users.local.inc = (stat as any).users.local.diff;
stat.users.local.dec = 0;
stat.users.remote.inc = (stat as any).users.remote.diff;
stat.users.remote.dec = 0;
stat.notes.local.inc = (stat as any).notes.local.diff;
stat.notes.local.dec = 0;
stat.notes.remote.inc = (stat as any).notes.remote.diff;
stat.notes.remote.dec = 0;
stat.drive.local.incCount = (stat as any).drive.local.diffCount;
stat.drive.local.decCount = 0;
stat.drive.local.incSize = (stat as any).drive.local.diffSize;
stat.drive.local.decSize = 0;
stat.drive.remote.incCount = (stat as any).drive.remote.diffCount;
stat.drive.remote.decCount = 0;
stat.drive.remote.incSize = (stat as any).drive.remote.diffSize;
stat.drive.remote.decSize = 0;
});
}
export const meta = {
};
export default (params: any) => new Promise(async (res, rej) => {
const daysRange = 30;
const hoursRange = 30;
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
const h = now.getHours();
const [statsPerDay, statsPerHour] = await Promise.all([
Stats.find({
span: 'day',
date: {
$gt: new Date(y, m, d - daysRange)
}
}, {
sort: {
date: -1
},
fields: {
_id: 0
}
}),
Stats.find({
span: 'hour',
date: {
$gt: new Date(y, m, d, h - hoursRange)
}
}, {
sort: {
date: -1
},
fields: {
_id: 0
}
}),
]);
// 後方互換性のため
migrateStats(statsPerDay);
migrateStats(statsPerHour);
const format = (src: IStats[], span: 'day' | 'hour') => {
const chart: Array<Omit<Omit<IStats, '_id'>, 'span'>> = [];
const range =
span == 'day' ? daysRange :
span == 'hour' ? hoursRange :
null;
for (let i = (range - 1); i >= 0; i--) {
const current =
span == 'day' ? new Date(y, m, d - i) :
span == 'hour' ? new Date(y, m, d, h - i) :
null;
const stat = src.find(s => s.date.getTime() == current.getTime());
if (stat) {
chart.unshift(stat);
} else { // 隙間埋め
const mostRecent = src.find(s => s.date.getTime() < current.getTime());
if (mostRecent) {
chart.unshift({
date: current,
users: {
local: {
total: mostRecent.users.local.total,
inc: 0,
dec: 0
},
remote: {
total: mostRecent.users.remote.total,
inc: 0,
dec: 0
}
},
notes: {
local: {
total: mostRecent.notes.local.total,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
},
remote: {
total: mostRecent.notes.remote.total,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
}
},
drive: {
local: {
totalCount: mostRecent.drive.local.totalCount,
totalSize: mostRecent.drive.local.totalSize,
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
},
remote: {
totalCount: mostRecent.drive.remote.totalCount,
totalSize: mostRecent.drive.remote.totalSize,
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
}
}
});
} else {
chart.unshift({
date: current,
users: {
local: {
total: 0,
inc: 0,
dec: 0
},
remote: {
total: 0,
inc: 0,
dec: 0
}
},
notes: {
local: {
total: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
},
remote: {
total: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
renote: 0
}
}
},
drive: {
local: {
totalCount: 0,
totalSize: 0,
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
},
remote: {
totalCount: 0,
totalSize: 0,
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
}
}
});
}
}
}
chart.forEach(x => {
delete (x as any).span;
});
return chart;
};
res({
perDay: format(statsPerDay, 'day'),
perHour: format(statsPerHour, 'hour')
});
});

View File

@ -84,7 +84,7 @@ export default async (params: any, user: ILocalUser, app: IApp) => new Promise(a
if (avatar == null) return rej('avatar not found');
updates.avatarUrl = avatar.metadata.url || `${config.drive_url}/${avatar._id}`;
updates.avatarUrl = avatar.metadata.thumbnailUrl || avatar.metadata.url || `${config.drive_url}/${avatar._id}`;
if (avatar.metadata.properties.avgColor) {
updates.avatarColor = avatar.metadata.properties.avgColor;

View File

@ -46,6 +46,11 @@ router.post('/signin', require('./private/signin').default);
router.use(require('./service/github').routes());
router.use(require('./service/twitter').routes());
// Return 404 for unknown API
router.all('*', async ctx => {
ctx.status = 404;
});
// Register router
app.use(router.routes());

View File

@ -122,8 +122,7 @@ router.get('/notes/:note', async ctx => {
router.get('*', async ctx => {
await send(ctx, `app/base.html`, {
root: client,
maxage: ms('3 days'),
immutable: true
maxage: ms('5m')
});
});

View File

@ -40,7 +40,7 @@ async function save(path: string, name: string, type: string, hash: string, size
const thumbnailKey = `${config.drive.prefix}/${uuid.v4()}/${name}.thumbnail.jpg`;
const baseUrl = config.drive.baseUrl
|| `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`;
|| `${ config.drive.config.useSSL ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`;
await minio.putObject(config.drive.bucket, key, fs.createReadStream(path), size, {
'Content-Type': type,
@ -116,7 +116,8 @@ async function deleteOldFile(user: IRemoteUser) {
const oldFile = await DriveFile.findOne({
_id: {
$nin: [user.avatarId, user.bannerId]
}
},
'metadata.userId': user._id
}, {
sort: {
_id: 1

View File

@ -56,7 +56,7 @@ export default async function(follower: IUser, followee: IUser) {
}
if (isLocalUser(follower) && isRemoteUser(followee)) {
const content = pack(renderUndo(renderFollow(follower, followee)));
const content = pack(renderUndo(renderFollow(follower, followee), follower));
deliver(follower, content, followee.inbox);
}
}

View File

@ -8,7 +8,7 @@ import { publishUserStream } from '../../../stream';
export default async function(followee: IUser, follower: IUser) {
if (isRemoteUser(followee)) {
const content = pack(renderUndo(renderFollow(follower, followee)));
const content = pack(renderUndo(renderFollow(follower, followee), follower));
deliver(follower as ILocalUser, content, followee.inbox);
}

View File

@ -239,8 +239,8 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
async function renderActivity(data: Option, note: INote) {
const content = data.renote && data.text == null
? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote), note)
: renderCreate(await renderNote(note));
? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note)
: renderCreate(await renderNote(note, false), note);
return packAp(content);
}

View File

@ -32,7 +32,7 @@ export default async function(user: IUser, note: INote) {
//#region ローカルの投稿なら削除アクティビティを配送
if (isLocalUser(user)) {
const content = pack(renderDelete(await renderNote(note)));
const content = pack(renderDelete(await renderNote(note), user));
const followings = await Following.find({
followeeId: user._id,

View File

@ -48,17 +48,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
users: {
local: {
total: mostRecentStats.users.local.total,
diff: 0
inc: 0,
dec: 0
},
remote: {
total: mostRecentStats.users.remote.total,
diff: 0
inc: 0,
dec: 0
}
},
notes: {
local: {
total: mostRecentStats.notes.local.total,
diff: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
@ -67,7 +70,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
},
remote: {
total: mostRecentStats.notes.remote.total,
diff: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
@ -79,14 +83,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
local: {
totalCount: mostRecentStats.drive.local.totalCount,
totalSize: mostRecentStats.drive.local.totalSize,
diffCount: 0,
diffSize: 0
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
},
remote: {
totalCount: mostRecentStats.drive.remote.totalCount,
totalSize: mostRecentStats.drive.remote.totalSize,
diffCount: 0,
diffSize: 0
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
}
}
};
@ -105,17 +113,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
users: {
local: {
total: 0,
diff: 0
inc: 0,
dec: 0
},
remote: {
total: 0,
diff: 0
inc: 0,
dec: 0
}
},
notes: {
local: {
total: 0,
diff: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
@ -124,7 +135,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
},
remote: {
total: 0,
diff: 0,
inc: 0,
dec: 0,
diffs: {
normal: 0,
reply: 0,
@ -136,14 +148,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> {
local: {
totalCount: 0,
totalSize: 0,
diffCount: 0,
diffSize: 0
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
},
remote: {
totalCount: 0,
totalSize: 0,
diffCount: 0,
diffSize: 0
incCount: 0,
incSize: 0,
decCount: 0,
decSize: 0
}
}
};
@ -174,46 +190,56 @@ function update(inc: any) {
}
export async function updateUserStats(user: IUser, isAdditional: boolean) {
const amount = isAdditional ? 1 : -1;
const origin = isLocalUser(user) ? 'local' : 'remote';
const inc = {} as any;
inc[`users.${origin}.total`] = amount;
inc[`users.${origin}.diff`] = amount;
inc[`users.${origin}.total`] = isAdditional ? 1 : -1;
if (isAdditional) {
inc[`users.${origin}.inc`] = 1;
} else {
inc[`users.${origin}.dec`] = 1;
}
await update(inc);
}
export async function updateNoteStats(note: INote, isAdditional: boolean) {
const amount = isAdditional ? 1 : -1;
const origin = isLocalUser(note._user) ? 'local' : 'remote';
const inc = {} as any;
inc[`notes.${origin}.total`] = amount;
inc[`notes.${origin}.diff`] = amount;
inc[`notes.${origin}.total`] = isAdditional ? 1 : -1;
if (isAdditional) {
inc[`notes.${origin}.inc`] = 1;
} else {
inc[`notes.${origin}.dec`] = 1;
}
if (note.replyId != null) {
inc[`notes.${origin}.diffs.reply`] = amount;
inc[`notes.${origin}.diffs.reply`] = isAdditional ? 1 : -1;
} else if (note.renoteId != null) {
inc[`notes.${origin}.diffs.renote`] = amount;
inc[`notes.${origin}.diffs.renote`] = isAdditional ? 1 : -1;
} else {
inc[`notes.${origin}.diffs.normal`] = amount;
inc[`notes.${origin}.diffs.normal`] = isAdditional ? 1 : -1;
}
await update(inc);
}
export async function updateDriveStats(file: IDriveFile, isAdditional: boolean) {
const amount = isAdditional ? 1 : -1;
const size = isAdditional ? file.length : -file.length;
const origin = isLocalUser(file.metadata._user) ? 'local' : 'remote';
const inc = {} as any;
inc[`drive.${origin}.totalCount`] = amount;
inc[`drive.${origin}.diffCount`] = amount;
inc[`drive.${origin}.totalSize`] = size;
inc[`drive.${origin}.diffSize`] = size;
inc[`drive.${origin}.totalCount`] = isAdditional ? 1 : -1;
inc[`drive.${origin}.totalSize`] = isAdditional ? file.length : -file.length;
if (isAdditional) {
inc[`drive.${origin}.incCount`] = 1;
inc[`drive.${origin}.incSize`] = file.length;
} else {
inc[`drive.${origin}.decCount`] = 1;
inc[`drive.${origin}.decSize`] = file.length;
}
await update(inc);
}