Compare commits

...

257 Commits

Author SHA1 Message Date
35a1fa5bf0 6.3.0 2018-08-17 19:37:06 +09:00
8d3f71d490 Fix bug 2018-08-17 19:35:05 +09:00
9776d8e06b Merge pull request #2283 from sei0o/patch-2266
fix #2266
2018-08-17 19:24:10 +09:00
10f845ae76 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-17 19:17:36 +09:00
2c8f962889 #2214 #2155 2018-08-17 19:17:23 +09:00
1721a82352 Merge pull request #2284 from acid-chicken/acid-chicken-patch-3
Auto-generate README
2018-08-17 18:50:17 +09:00
59bec546e4 Create README.foot.md 2018-08-17 18:34:35 +09:00
86503f2d69 Create README.head.md 2018-08-17 18:33:49 +09:00
e4b8c688bb fix #2266: デフォルト値を設定 2018-08-17 17:16:27 +09:00
4535ab4c43 fix #2266 2018-08-17 16:35:04 +09:00
dcdb57df9d Merge pull request #2270 from syuilo/l10n_master
New Crowdin translations
2018-08-17 14:57:51 +09:00
cfc2808c56 New translations ja.yml (English) 2018-08-17 14:51:21 +09:00
4a3d74c608 Merge branch 'master' into l10n_master 2018-08-17 14:48:38 +09:00
e18655d18f Merge pull request #2279 from syuilo/enhance-note-footer
Enhance note footer
2018-08-17 14:43:25 +09:00
12b4b78763 New translations ja.yml (Catalan) 2018-08-17 13:21:27 +09:00
550a528fc1 New translations ja.yml (Portuguese) 2018-08-17 13:21:25 +09:00
4e3429a5c7 New translations ja.yml (Korean) 2018-08-17 13:21:22 +09:00
ef98383075 New translations ja.yml (Polish) 2018-08-17 13:21:20 +09:00
d66d1f142f New translations ja.yml (Chinese Simplified) 2018-08-17 13:21:17 +09:00
c896055cb1 New translations ja.yml (Italian) 2018-08-17 13:21:15 +09:00
2e8b2e0cf9 New translations ja.yml (Russian) 2018-08-17 13:21:13 +09:00
59012b5693 New translations ja.yml (English) 2018-08-17 13:21:11 +09:00
dfb51e8d26 New translations ja.yml (Spanish) 2018-08-17 13:21:09 +09:00
5107824352 New translations ja.yml (German) 2018-08-17 13:21:07 +09:00
bf7ec18316 New translations ja.yml (French) 2018-08-17 13:21:04 +09:00
77d82d2d17 Merge pull request #2282 from sei0o/improve-login-failed-message
ログイン失敗時のメッセージを改善
2018-08-17 13:19:41 +09:00
2777460150 Merge pull request #2278 from mei23/mei-0817-announce3
Misskey => Misskey で renote 出来ない件修正
2018-08-17 13:18:11 +09:00
9476a240d9 ログイン失敗時のメッセージを改善 2018-08-17 12:34:07 +09:00
bddb878931 New translations ja.yml (English) 2018-08-17 10:01:12 +09:00
b0768d8a4a New translations ja.yml (English) 2018-08-17 09:51:19 +09:00
46bb7f9efb New translations ja.yml (English) 2018-08-17 09:41:18 +09:00
a507b7c0b0 Enhance note footer 2018-08-17 07:16:56 +09:00
939c0dc5f9 Fix indent 2018-08-17 06:46:32 +09:00
a89c206572 Fix Announce Activity 2018-08-17 06:40:50 +09:00
8b55263e72 New translations ja.yml (Catalan) 2018-08-17 06:11:53 +09:00
f2ad1e4639 New translations ja.yml (Portuguese) 2018-08-17 06:11:51 +09:00
0fbcec1c16 New translations ja.yml (Korean) 2018-08-17 06:11:48 +09:00
ec2b73d076 New translations ja.yml (Polish) 2018-08-17 06:11:46 +09:00
6630bb0b39 New translations ja.yml (Chinese Simplified) 2018-08-17 06:11:43 +09:00
bef0d4c8bd New translations ja.yml (Italian) 2018-08-17 06:11:41 +09:00
a57cb3bd31 New translations ja.yml (Russian) 2018-08-17 06:11:38 +09:00
1e4577a988 New translations ja.yml (English) 2018-08-17 06:11:36 +09:00
fe792b5bbb New translations ja.yml (Spanish) 2018-08-17 06:11:33 +09:00
d4005133d0 New translations ja.yml (German) 2018-08-17 06:11:31 +09:00
abe8e80268 New translations ja.yml (French) 2018-08-17 06:11:28 +09:00
e38e4940b4 Merge pull request #2277 from syuilo/patch-2276
Resolve #2276
2018-08-17 06:06:07 +09:00
48dc1678c3 Resolve #2276 2018-08-17 06:04:09 +09:00
431383ab54 Clean up 2018-08-17 05:33:20 +09:00
7a8d252f63 Merge pull request #2272 from mei23/mei-0817-debuglog
production以外のときに`npm run debug`が効かないのを修正
2018-08-17 04:04:18 +09:00
04525e2997 New translations ja.yml (Catalan) 2018-08-17 03:52:03 +09:00
a2f96f3f20 New translations ja.yml (Portuguese) 2018-08-17 03:52:01 +09:00
a81ecb0b28 New translations ja.yml (Korean) 2018-08-17 03:51:59 +09:00
1122368ee0 New translations ja.yml (Polish) 2018-08-17 03:51:56 +09:00
6c54328391 New translations ja.yml (Chinese Simplified) 2018-08-17 03:51:54 +09:00
1a26816f7a New translations ja.yml (Italian) 2018-08-17 03:51:52 +09:00
8538334d08 New translations ja.yml (Russian) 2018-08-17 03:51:50 +09:00
9387ebc569 New translations ja.yml (English) 2018-08-17 03:51:48 +09:00
c99dce68ed New translations ja.yml (Spanish) 2018-08-17 03:51:46 +09:00
6dea84c6d2 New translations ja.yml (German) 2018-08-17 03:51:44 +09:00
39060374c2 Fix npm run debug not working 2018-08-17 03:51:42 +09:00
d3ebb5d13f New translations ja.yml (French) 2018-08-17 03:51:41 +09:00
4e7c10d3d9 Merge pull request #2269 from syuilo/verified-user-ja
Update verified-user in ja.yml
2018-08-17 03:47:58 +09:00
e93ea66d2d Update verified-user in ja.yml 2018-08-17 03:47:08 +09:00
152dd70ea5 Merge pull request #2268 from syuilo/space-between-words
Add a space between the words
2018-08-17 03:18:52 +09:00
7b94cf9f84 Add a space between the words 2018-08-17 03:08:17 +09:00
d70e27a865 Provide id in announce activity 2018-08-17 02:37:20 +09:00
b780ea336c 6.2.0 2018-08-17 00:39:30 +09:00
bd9f589d32 Merge pull request #2255 from syuilo/l10n_master
New Crowdin translations
2018-08-17 00:38:30 +09:00
d9d18bd8f9 New translations ja.yml (English) 2018-08-17 00:33:59 +09:00
ffdaa6bc56 Use thumbnail 2018-08-17 00:27:36 +09:00
c7f60e337e New translations ja.yml (English) 2018-08-17 00:23:38 +09:00
7f265dbd52 New translations ja.yml (Catalan) 2018-08-17 00:22:15 +09:00
8929c5cabc New translations ja.yml (Portuguese) 2018-08-17 00:22:12 +09:00
4a610f3b0a New translations ja.yml (Korean) 2018-08-17 00:22:09 +09:00
55ec19edb5 New translations ja.yml (Polish) 2018-08-17 00:22:07 +09:00
c319c61832 New translations ja.yml (Chinese Simplified) 2018-08-17 00:22:05 +09:00
66db99b8cd New translations ja.yml (Italian) 2018-08-17 00:22:02 +09:00
ff2162974d New translations ja.yml (Russian) 2018-08-17 00:22:00 +09:00
78e86af086 New translations ja.yml (English) 2018-08-17 00:21:57 +09:00
2dcf89eecf New translations ja.yml (Spanish) 2018-08-17 00:21:55 +09:00
fdf94be998 New translations ja.yml (German) 2018-08-17 00:21:53 +09:00
0e913a5727 New translations ja.yml (French) 2018-08-17 00:21:50 +09:00
f3be077adc Fix bug 2018-08-17 00:19:27 +09:00
a6e0471f8c ✌️ 2018-08-17 00:13:52 +09:00
c5d734f9ad 6.1.0 2018-08-17 00:09:01 +09:00
ee12d887ae typo 2018-08-17 00:07:23 +09:00
b78d24be1e Fix bug 2018-08-17 00:05:57 +09:00
d5379e2b36 autoWatchをデフォルトでfalseに 2018-08-17 00:04:07 +09:00
cf36557084 New translations ja.yml (Catalan) 2018-08-17 00:00:54 +09:00
fd1ee129dc New translations ja.yml (Portuguese) 2018-08-17 00:00:51 +09:00
1471b7a6b5 New translations ja.yml (Korean) 2018-08-17 00:00:49 +09:00
1d39d7efcb New translations ja.yml (Polish) 2018-08-17 00:00:46 +09:00
69ee97f6e2 New translations ja.yml (Chinese Simplified) 2018-08-17 00:00:44 +09:00
12092e6083 New translations ja.yml (Italian) 2018-08-17 00:00:41 +09:00
6e29e40b8b New translations ja.yml (Russian) 2018-08-17 00:00:39 +09:00
842c9e735b New translations ja.yml (English) 2018-08-17 00:00:37 +09:00
2f63a25058 New translations ja.yml (Spanish) 2018-08-17 00:00:33 +09:00
d3b084003c New translations ja.yml (German) 2018-08-17 00:00:31 +09:00
0da9d3d8b0 New translations ja.yml (French) 2018-08-17 00:00:27 +09:00
58f3c6aab7 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-16 23:59:25 +09:00
22e79675ad #2263 2018-08-16 23:59:22 +09:00
e5c350d740 Fix bug 2018-08-16 23:33:11 +09:00
210124ac34 New translations ja.yml (English) 2018-08-16 21:24:31 +09:00
7f9a35d7ac Improve object storage key 2018-08-16 21:23:31 +09:00
71a30f9001 New translations ja.yml (Korean) 2018-08-16 21:02:39 +09:00
95a34d55fb New translations ja.yml (English) 2018-08-16 21:02:36 +09:00
34f052b672 New translations ja.yml (Korean) 2018-08-16 20:51:53 +09:00
0178c2e696 New translations ja.yml (English) 2018-08-16 20:51:51 +09:00
5cb0c07627 New translations ja.yml (English) 2018-08-16 20:24:07 +09:00
d8fdbfe164 New translations ja.yml (English) 2018-08-16 20:11:53 +09:00
74e0b2734d New translations ja.yml (English) 2018-08-16 20:06:07 +09:00
3f5785bd03 New translations ja.yml (English) 2018-08-16 17:43:46 +09:00
15e5c69c15 New translations ja.yml (English) 2018-08-16 17:32:01 +09:00
57019c0b40 New translations ja.yml (English) 2018-08-16 09:01:03 +09:00
9d6641be3a Fix bug 2018-08-16 08:18:41 +09:00
ac15c2e71f Fix bug 2018-08-16 08:11:21 +09:00
1fc9206c6d 6.0.0 2018-08-16 08:02:50 +09:00
a8fb0d477f Merge pull request #2251 from syuilo/provide-thumbnails
Provide drive file thumbnails
2018-08-16 07:59:16 +09:00
0c372b68d4 Merge pull request #2252 from syuilo/greenkeeper/minio-7.0.0
Update minio to the latest version 🚀
2018-08-16 07:58:56 +09:00
e7d9018944 ✌️ 2018-08-16 07:56:53 +09:00
ce16884587 Update example.yml 2018-08-16 07:31:58 +09:00
3345733d00 fix(package): update minio to version 7.0.0 2018-08-15 22:26:17 +00:00
f91cccb6b1 fix(package): update @types/webpack to version 4.4.10 2018-08-16 07:24:19 +09:00
6183262037 wip 2018-08-16 07:17:04 +09:00
1c7a194950 wip 2018-08-16 06:27:35 +09:00
286e15b967 fix(package): update @types/node to version 10.7.1 2018-08-16 06:08:15 +09:00
744d366874 Merge pull request #2248 from syuilo/new-kao
Add new kao
2018-08-16 05:17:56 +09:00
afa62d3d44 Add new kao 2018-08-16 05:17:00 +09:00
270c7997c6 Remove trailing comma 2018-08-16 05:15:51 +09:00
fa95641f88 Use Array.prototype.length to avoid magic number 2018-08-16 05:15:06 +09:00
aa9fe38c25 Merge pull request #2247 from syuilo/clickable-reaction
Make reactions in reactions-viewer clickable
2018-08-16 05:00:13 +09:00
0d33cbbbbb Make reactions in reactions-viewer clickable 2018-08-16 04:57:09 +09:00
bf077da72f Trim code 2018-08-16 04:42:44 +09:00
d8f8e19d06 Merge pull request #2246 from mei23/mei-0816-player
動画プレーヤーの修正
2018-08-16 03:17:41 +09:00
3c3d3e4c0c Fix url-preview.vue 2018-08-16 03:06:59 +09:00
0efbeb36df 5.25.0 2018-08-16 01:29:11 +09:00
73c396cb39 2018-08-16 01:25:35 +09:00
8e75f8a125 Fix 2018-08-16 01:20:52 +09:00
e8a7e95c65 Update summaly 2018-08-16 01:17:01 +09:00
70a6889fe5 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-16 00:59:54 +09:00
6aff7375f6 Update backers 2018-08-16 00:59:48 +09:00
d2ef95a8c3 Make text unclickable 2018-08-16 00:49:40 +09:00
1ae51df74a Update .travis.yml 2018-08-16 00:42:20 +09:00
3098c6a915 Merge pull request #2242 from syuilo/l10n_master
New Crowdin translations
2018-08-16 00:16:31 +09:00
ab3f8fd10c Enhance log message 2018-08-16 00:13:24 +09:00
4bdef3720c Update setup.en.md 2018-08-15 23:55:30 +09:00
c02cecc9e5 New translations ja.yml (English) 2018-08-15 23:30:49 +09:00
08b431723a Refactoring 2018-08-15 20:27:49 +09:00
83dcfec053 Improve MFM 2018-08-15 20:27:36 +09:00
69ac7b739f Improve MFM 2018-08-15 20:23:50 +09:00
9ccf9a2496 Fix #2229 2018-08-15 20:20:46 +09:00
78563ef9a0 Fix #2228 2018-08-15 20:09:56 +09:00
019d157b92 Merge pull request #2198 from syuilo/l10n_master
New Crowdin translations
2018-08-15 19:48:03 +09:00
14de35e3f5 Merge pull request #2234 from acid-chicken/patch-player
Update player whitelist
2018-08-15 19:04:31 +09:00
a860479e88 Update url-preview.vue 2018-08-15 19:00:44 +09:00
b351b3fae5 Update url-preview.vue 2018-08-15 18:49:05 +09:00
89918a9f79 New translations ja.yml (English) 2018-08-15 17:08:24 +09:00
cadd020915 New translations ja.yml (English) 2018-08-15 16:51:16 +09:00
e80933b8ae New translations ja.yml (English) 2018-08-15 16:40:52 +09:00
4c0832884f New translations ja.yml (English) 2018-08-15 16:30:48 +09:00
e4ca940979 New translations ja.yml (English) 2018-08-15 16:20:51 +09:00
3fd9be3967 New translations ja.yml (English) 2018-08-15 16:13:11 +09:00
79ec7aba1d New translations ja.yml (English) 2018-08-15 13:40:56 +09:00
42b1f7eddd New translations ja.yml (English) 2018-08-15 11:30:56 +09:00
889a73caa4 New translations ja.yml (Catalan) 2018-08-15 11:11:41 +09:00
c34a89e962 New translations ja.yml (Portuguese) 2018-08-15 11:11:39 +09:00
2b4bf681e5 New translations ja.yml (Korean) 2018-08-15 11:11:36 +09:00
d1d59e3557 New translations ja.yml (Polish) 2018-08-15 11:11:34 +09:00
668c21830c New translations ja.yml (Chinese Simplified) 2018-08-15 11:11:31 +09:00
7c37ed07f8 New translations ja.yml (Italian) 2018-08-15 11:11:29 +09:00
a135d8fd59 New translations ja.yml (Russian) 2018-08-15 11:11:27 +09:00
0db9aae162 New translations ja.yml (English) 2018-08-15 11:11:25 +09:00
1875c362af New translations ja.yml (Spanish) 2018-08-15 11:11:23 +09:00
9b36dd9565 New translations ja.yml (German) 2018-08-15 11:11:21 +09:00
69452a27de New translations ja.yml (French) 2018-08-15 11:11:18 +09:00
6aa5c5895f Merge pull request #2219 from syuilo/patch-2215
Resolve #2215
2018-08-15 11:07:07 +09:00
12f20c67b1 New translations ja.yml (English) 2018-08-15 09:21:05 +09:00
66b8e5647d New translations ja.yml (English) 2018-08-15 09:11:16 +09:00
188a23fec7 New translations ja.yml (English) 2018-08-15 09:01:12 +09:00
b408b45000 New translations ja.yml (English) 2018-08-15 08:55:29 +09:00
c53cb94250 Resolve #2215 2018-08-15 06:50:49 +09:00
ba2eeabe38 Merge pull request #2216 from syuilo/patch-2201
Resolve #2201
2018-08-15 04:46:52 +09:00
259fac224e Resolve #2201 2018-08-15 04:44:39 +09:00
aad5440c9e New translations ja.yml (English) 2018-08-15 04:41:14 +09:00
5c40f0010f New translations ja.yml (English) 2018-08-15 04:31:06 +09:00
fb1d181424 New translations ja.yml (English) 2018-08-15 04:21:29 +09:00
12cbd8ef5b New translations ja.yml (English) 2018-08-15 04:11:22 +09:00
cfc4385d1f New translations ja.yml (English) 2018-08-15 04:00:59 +09:00
880ef024d0 New translations ja.yml (English) 2018-08-15 03:51:09 +09:00
c6c6edbc0a New translations ja.yml (English) 2018-08-15 03:41:21 +09:00
83ba951bf9 5.24.1 2018-08-15 02:38:47 +09:00
9c22b1a68a Fix 2018-08-15 02:35:25 +09:00
cd6a1d3446 5.24.0 2018-08-15 02:14:57 +09:00
4a9fc0c8ed Better query 2018-08-15 02:08:18 +09:00
fada899b30 Merge pull request #2210 from mei23/mei-0814-ap3
ActivityPub Followers/Following/Outbox の実装
2018-08-15 02:04:08 +09:00
22b099fa8a Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-15 02:01:52 +09:00
e0bc0d2830 Add new kao 2018-08-15 02:01:49 +09:00
90768d30aa fix(package): update seedrandom to version 2.4.4 2018-08-15 01:53:48 +09:00
177c549493 fix(package): update url-loader to version 1.1.0 2018-08-15 01:53:40 +09:00
5e1ee68189 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-15 01:51:46 +09:00
175f6303bc Update theme color 2018-08-15 01:51:43 +09:00
cf9f2a5562 Merge pull request #2211 from skid9000/patch-2
Update doc for twitter integration.
2018-08-14 22:55:02 +09:00
f04526baca Update example.yml 2018-08-14 15:45:36 +02:00
f085ecedb3 Update setup.en.md 2018-08-14 15:41:55 +02:00
0986301788 Implement ActivityPub Followers/Following/Outbox 2018-08-14 20:13:32 +09:00
fe418d8d9a fix(package): update @types/ws to version 6.0.0 2018-08-14 17:07:35 +09:00
6009be34dc fix(package): update @types/node to version 10.7.0 2018-08-14 17:07:23 +09:00
01a0a54a2c fix(package): update @types/mongodb to version 3.1.4 2018-08-14 17:07:15 +09:00
cfcaf77e21 fix(package): update mongodb to version 3.1.3 2018-08-14 17:07:07 +09:00
3b37bdc0b9 fix(package): update vue-style-loader to version 4.1.2 2018-08-14 17:06:54 +09:00
ec07112f94 Fix bug 2018-08-14 16:53:57 +09:00
464faf2673 Merge pull request #2200 from syuilo/use-deque
Use deque instead of linked list
2018-08-14 08:22:23 +09:00
bde20a1a65 Use deque instead of linked list 2018-08-14 08:21:25 +09:00
86c7276da9 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-14 08:16:24 +09:00
fec988bb79 Provide isFirstNote flag 2018-08-14 08:16:21 +09:00
0702d0974b Merge pull request #2199 from syuilo/patch-2176
Resolve #2176
2018-08-14 07:51:45 +09:00
f443d36dbb Resolve #2176 2018-08-14 07:49:59 +09:00
5477f0a865 New translations ja.yml (English) 2018-08-14 05:42:07 +09:00
dc02168f33 Merge #2182 2018-08-14 05:25:02 +09:00
cc5c32b4d2 Clean up 2018-08-14 05:24:51 +09:00
a35680a838 New translations ja.yml (Catalan) 2018-08-14 04:52:05 +09:00
770cba73a6 New translations ja.yml (Portuguese) 2018-08-14 04:52:03 +09:00
401fc758fd New translations ja.yml (Korean) 2018-08-14 04:52:01 +09:00
e8503e6351 New translations ja.yml (Polish) 2018-08-14 04:51:58 +09:00
de23753409 New translations ja.yml (Chinese Simplified) 2018-08-14 04:51:56 +09:00
4857d86cdd New translations ja.yml (Italian) 2018-08-14 04:51:54 +09:00
dc4a072678 New translations ja.yml (Russian) 2018-08-14 04:51:52 +09:00
c6ee5ccd88 New translations ja.yml (English) 2018-08-14 04:51:50 +09:00
68b630cb37 New translations ja.yml (Spanish) 2018-08-14 04:51:48 +09:00
94c0238d3a New translations ja.yml (German) 2018-08-14 04:51:45 +09:00
dbea387433 New translations ja.yml (French) 2018-08-14 04:51:43 +09:00
d35f62d0e4 Merge pull request #2195 from syuilo/instance-management-system
管理画面
2018-08-14 04:42:16 +09:00
09b8e81a77 wip 2018-08-14 04:39:37 +09:00
3b38979a34 wip 2018-08-14 04:30:42 +09:00
0fd8c86c24 fix(package): update mongodb to version 3.1.2 2018-08-14 03:38:01 +09:00
58d0ed1a2e 5.23.2 2018-08-14 02:36:06 +09:00
8939452036 Merge pull request #2192 from acid-chicken/acid-chicken-patch-3
Re: Re: Fix #2177
2018-08-14 02:31:00 +09:00
a2931d6f7e Update ui.header.vue 2018-08-14 02:26:58 +09:00
38b75ad977 Update avatar.vue 2018-08-14 02:10:06 +09:00
dc4f585954 Merge pull request #2191 from syuilo/greenkeeper/parse5-5.1.0
Update parse5 to the latest version 🚀
2018-08-14 01:58:01 +09:00
1fbe5365f7 Update example.yml 2018-08-14 01:57:52 +09:00
04257db938 fix(package): update parse5 to version 5.1.0 2018-08-13 16:54:58 +00:00
ba08d1aa53 wip 2018-08-14 01:48:11 +09:00
c29cb5bfb9 Update package.json 2018-08-14 01:38:29 +09:00
fb1e2efbdd wip 2018-08-14 01:37:23 +09:00
131a454e7c Merge pull request #2190 from mei23/mei-apsendvis2
ActivityPub送信時の公開範囲の実装
2018-08-14 01:36:56 +09:00
92e5cff285 wip 2018-08-14 01:35:36 +09:00
ba9340a26b wip 2018-08-14 01:24:46 +09:00
00119328f2 wip 2018-08-14 01:19:05 +09:00
9021bb5694 wip 2018-08-14 01:05:58 +09:00
f15878cc6f Update avatar.vue
refs: https://github.com/syuilo/misskey/pull/2182#discussion_r209609541
2018-08-13 22:49:32 +09:00
f079041827 ActivityPub visibility on send 2018-08-13 03:49:17 +09:00
4edd9efc0b Update avatar.vue
refs: https://github.com/syuilo/misskey/pull/2182#discussion_r209464350
2018-08-13 03:47:56 +09:00
2913c7ccfb Update avatar.vue 2018-08-13 03:42:12 +09:00
e1f460f90f Update user.header.vue 2018-08-13 03:40:50 +09:00
70f927ea43 Update avatar.vue 2018-08-13 03:39:32 +09:00
80d343bb0b Update avatar.vue 2018-08-13 03:36:42 +09:00
96 changed files with 1899 additions and 442 deletions

25
.autogen/README.foot.md Normal file
View File

@ -0,0 +1,25 @@
:four_leaf_clover: Copyright
----------------------------------------------------------------
> Copyright (c) 2014-2018 syuilo
Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE).
[![][agpl-3.0-badge]][AGPL-3.0]
[agpl-3.0]: https://www.gnu.org/licenses/agpl-3.0.en.html
[agpl-3.0-badge]: https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=flat-square
[travis-link]: https://travis-ci.org/syuilo/misskey
[travis-badge]: http://img.shields.io/travis/syuilo/misskey/master.svg?style=flat-square
[dependencies-link]: https://david-dm.org/syuilo/misskey
[dependencies-badge]: https://img.shields.io/david/syuilo/misskey.svg?style=flat-square
[backer-url]: #backers
[backer-badge]: https://opencollective.com/misskey/backers/badge.svg
[backers-image]: https://opencollective.com/misskey/backers.svg
[sponsor-url]: #sponsors
[sponsor-badge]: https://opencollective.com/misskey/sponsors/badge.svg
[sponsors-image]: https://opencollective.com/misskey/sponsors.svg
[support-url]: https://opencollective.com/misskey#support
[syuilo-link]: https://syuilo.com
[syuilo-icon]: https://avatars2.githubusercontent.com/u/4439005?v=3&s=70

45
.autogen/README.head.md Normal file
View File

@ -0,0 +1,45 @@
<img src="https://github.com/syuilo/misskey/blob/b3f42e62af698a67c2250533c437569559f1fdf9/src/himasaku/resources/himasaku.png?raw=true" align="right" width="320px"/>
[![Misskey](/assets/title.png)](https://misskey.xyz/)
================================================================
[![][travis-badge]][travis-link]
[![][dependencies-badge]][dependencies-link]
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Greenkeeper badge](https://badges.greenkeeper.io/syuilo/misskey.svg)](https://greenkeeper.io/)
**Microblogging. Redefined.**
**[Misskey](https://misskey.xyz)** is a completely open source,
ultimately sophisticated professional microblogging software.
<a href="https://www.patreon.com/syuilo"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="Become a Patron!" width="160" /></a>
![](https://ja.mstdn.wiki/images/e/ed/Deck.jpg)
:sparkles: Features
----------------------------------------------------------------
* Rich text contents
* Reactions
* User lists
* Customizable column view (called MisskeyDeck)
* and widgets!
* Private messages
* ActivityPub support
and more! You can see it with your own eyes at [misskey.xyz](https://misskey.xyz).
:package: Create your instance
----------------------------------------------------------------
If you want to run your own instance of Misskey,
please see [Setup and installation guide](./docs/setup.en.md).
:wrench: Contribute
----------------------------------------------------------------
**[PR](https://github.com/syuilo/misskey/pulls)s welcome!**
If you want to...
* i18n ... please see [Translation guide](./docs/translate.en.md).
* l10n ... please visit https://crowdin.com/project/misskey
:heart: Backers & Sponsors
----------------------------------------------------------------

View File

@ -50,8 +50,11 @@ remoteDriveCapacityMb: 8
# If enabled: # If enabled:
# Server will not cache remote files (Using direct link instead). # Server will not cache remote files (Using direct link instead).
# You can save your storage. # You can save your storage.
# Users cannot see remote images when they turn off "Show media from a remote server" setting. #
preventCache: false # NOTE:
# * Users cannot see remote images when they turn off "Show media from a remote server" setting.
# * Since thumbnails are not provided, traffic increases.
preventCacheRemoteFiles: false
drive: drive:
storage: 'db' storage: 'db'
@ -64,7 +67,7 @@ drive:
# config: # config:
# endPoint: # endPoint:
# port: # port:
# secure: # useSSL:
# accessKey: # accessKey:
# secretKey: # secretKey:
@ -75,7 +78,7 @@ drive:
# config: # config:
# endPoint: s3-us-west-2.amazonaws.com # endPoint: s3-us-west-2.amazonaws.com
# region: us-west-2 # region: us-west-2
# secure: true # useSSL: true
# accessKey: XXX # accessKey: XXX
# secretKey: YYY # secretKey: YYY
@ -87,7 +90,7 @@ drive:
# config: # config:
# endPoint: s3-us-west-2.amazonaws.com # endPoint: s3-us-west-2.amazonaws.com
# region: us-west-2 # region: us-west-2
# secure: true # useSSL: true
# accessKey: XXX # accessKey: XXX
# secretKey: YYY # secretKey: YYY
@ -123,6 +126,7 @@ drive:
# google_maps_api_key: example-google-maps-api-key # google_maps_api_key: example-google-maps-api-key
# Twitter integration # Twitter integration
# You need to set the oauth callback url as : https://<your-misskey-instance>/api/tw/cb
# twitter: # twitter:
# consumer_key: example-twitter-consumer-key # consumer_key: example-twitter-consumer-key
# consumer_secret: example-twitter-consumer-secret-key # consumer_secret: example-twitter-consumer-secret-key

View File

@ -22,7 +22,6 @@ addons:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-4.8 - g++-4.8
- graphicsmagick
cache: cache:
directories: directories:

View File

@ -5,6 +5,15 @@ ChangeLog
This document describes breaking changes only. This document describes breaking changes only.
6.0.0
-----
### Migration
オブジェクトストレージを使用している場合、設定ファイルの`drive.config.secure``drive.config.useSSL`にリネームしてください。
If you use object storage, please rename `drive.config.secure` to `drive.config.useSSL` in config.
5.0.0 5.0.0
----- -----

View File

@ -43,9 +43,34 @@ If you want to...
:heart: Backers & Sponsors :heart: Backers & Sponsors
---------------------------------------------------------------- ----------------------------------------------------------------
| <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=tB1e_r8RlZ5sFL0KV_e8dugapxatNBRK1Z3h67TO1g8%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12378075/0156f769e20f412594fa6b87d85fe228/1?token-time=2145916800&token-hash=IsIJRUXszzoD6-7pDnRY8I05T9nSznc4GTaxj7C9SwU%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D"> | <img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D"> | <table>
|:-:|:-:|:-:|:-:| <tr>
| [Gargron](https://www.patreon.com/mastodon) | [39ff](https://www.patreon.com/user/creators?u=12378075) | [dansup](https://www.patreon.com/dansup) | [Takashi Shibuya](https://www.patreon.com/user/creators?u=12531784) | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=tB1e_r8RlZ5sFL0KV_e8dugapxatNBRK1Z3h67TO1g8%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12378075/0156f769e20f412594fa6b87d85fe228/1?token-time=2145916800&token-hash=IsIJRUXszzoD6-7pDnRY8I05T9nSznc4GTaxj7C9SwU%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12959468/c249e15aebec4424b5c0f427173671b6/1?token-time=2145916800&token-hash=lubpCEdxAkxPlpR2O6bvZ7BIh8Q4nGf-U_mE1qpjVAQ%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/1?token-time=2145916800&token-hash=f03BFb4S2FUx9YEt87TnEmifb4h33OywGBW2akQVtQY%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/2?token-time=2145916800&token-hash=zElv7ZcPL3viGsXbNG_KWiKrbV0vvw1gk0panx8DJoo%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D"></td>
<td><img src="https://c8.patreon.com/2/100/12718187"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12931605/ead494101f364dffa90efe49e36fb494/1?token-time=2145916800&token-hash=NzSFPjIlodXyv41rwK61aZWVZWfI4surJaNj8vWKvqM%3D"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D"></td>
</tr>
<tr>
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
<td><a href="https://www.patreon.com/user/creators?u=12378075">39ff</a></td>
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
<td><a href="https://www.patreon.com/user/creators?u=12531784">Takashi Shibuya</a></td>
<td><a href="https://www.patreon.com/fujishan">fujishan</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
<td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td>
<td><a href="https://www.patreon.com/user?u=12731202">negao</a></td>
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
<td><a href="https://www.patreon.com/user?u=12931605">Reiju</a></td>
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
</tr>
</table>
:four_leaf_clover: Copyright :four_leaf_clover: Copyright
---------------------------------------------------------------- ----------------------------------------------------------------

View File

@ -62,6 +62,13 @@ npm install web-push -g
web-push generate-vapid-keys web-push generate-vapid-keys
``` ```
*(optional)* Create a twitter application
----------------------------------------------------------------
If you want to enable the twitter integration, you need to create a twitter app at [https://developer.twitter.com/en/apply/user](https://developer.twitter.com/en/apply/user).
In the app you need to set the oauth callback url as : https://misskey-instance/api/tw/cb
*5.* Make configuration file *5.* Make configuration file
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. 1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet." my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet."
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "Anmelden" signin: "Anmelden"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "Benutzername" username: "Benutzername"
checking: "Überprüfung..." checking: "Überprüfung..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "Kreisförmige Icons" circle-icons: "Kreisförmige Icons"
gradient-window-header: "Übergang in Fensterköpfen" gradient-window-header: "Übergang in Fensterköpfen"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "Zeige Antworten" show-reply-target: "Zeige Antworten"
show-my-renotes: "Zeige meine Reposts auf der Zeitleiste" show-my-renotes: "Zeige meine Reposts auf der Zeitleiste"
show-renoted-my-notes: "Zeige meine Reposts, die geteilt wurden, auf der Zeitleiste" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Karte anzeigen" show-maps: "Karte anzeigen"
show-maps-desc: "Zeige den Standort zu diesem Beitrag automatisch an." show-maps-desc: "Zeige den Standort zu diesem Beitrag automatisch an."
sound: "Ton" sound: "Ton"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -8,17 +8,17 @@ common:
about: "Thank you for finding Misskey. Misskey is a <b>decentralized microblogging platform</b> born on Earth. Since it exists within the Fediverse (a universe where various social media platforms are organized), it is mutually linked with other social media platforms. Why don't you take a short break from the hustle and bustle of the city, and dive into a new Internet?" about: "Thank you for finding Misskey. Misskey is a <b>decentralized microblogging platform</b> born on Earth. Since it exists within the Fediverse (a universe where various social media platforms are organized), it is mutually linked with other social media platforms. Why don't you take a short break from the hustle and bustle of the city, and dive into a new Internet?"
adblock: adblock:
detected: "Please disable ad blocker." detected: "Please disable ad blocker."
warning: "<strong>Misskey is not running ads</strong>, but some features may be unavailable or malfunctioning if ad blocking features are enabled." warning: "Some features may be unavailable or cause malfunctions if ad blocking features are enabled. <strong>Misskey is not running ads</strong>."
application-authorization: "Application authorizations." application-authorization: "Application authorizations"
close: "Close" close: "Close"
do-not-copy-paste: "Please do not enter or paste the code here. Account may be compromised." do-not-copy-paste: "Please do not enter or paste the code here. Account may be compromised."
got-it: "Got it!" got-it: "Got it!"
customization-tips: customization-tips:
title: "Customization tips" title: "Customization tips"
paragraph1: "Home customization allows you to add/delete, drag and drop and rearrange widgets." paragraph1: "Home customization allows you to add/delete, drag and drop and rearrange widgets."
paragraph2: "You can change the display by <strong>right clicking</strong> on some widgets." paragraph2: "You can change the display by <strong><strong>right</strong> clicking</strong> on some widgets."
paragraph3: "To delete a widget, <strong>drag and drop the widget onto the area labeled \"Trash\"</strong> in the header." paragraph3: "To delete a widget, drag and drop the widget onto <strong>the area labeled \"Trash\"</strong> in the header."
paragraph4: "To finish the customization, click \"Finish\" in the upper right." paragraph4: "To finish the customization, click \"Finish\" on the upper right."
gotit: "Got it!" gotit: "Got it!"
notification: notification:
file-uploaded: "File uploaded!" file-uploaded: "File uploaded!"
@ -72,9 +72,9 @@ common:
a: "What are you doing?" a: "What are you doing?"
b: "What's happening?" b: "What's happening?"
c: "Whats on your mind?" c: "Whats on your mind?"
d: "What do you wish to say?" d: "Would you post any words?"
e: "Write here" e: "Write here"
f: "Waiting for your writing..." f: "Waiting for your writing."
search: "Search" search: "Search"
delete: "Delete" delete: "Delete"
loading: "Loading" loading: "Loading"
@ -84,7 +84,7 @@ common:
my-token-regenerated: "Your token has been regenerated, so you will be signed out." my-token-regenerated: "Your token has been regenerated, so you will be signed out."
i-like-sushi: "I prefer sushi rather than pudding" i-like-sushi: "I prefer sushi rather than pudding"
show-reversi-board-labels: "Show row and column labels in Reversi" show-reversi-board-labels: "Show row and column labels in Reversi"
verified-user: "Verified user" verified-user: "Verified account"
disable-animated-mfm: "Disable animated texts in a post" disable-animated-mfm: "Disable animated texts in a post"
reversi: reversi:
drawn: "Draw" drawn: "Draw"
@ -141,23 +141,23 @@ common:
auth/views/form.vue: auth/views/form.vue:
share-access: "Would you <b>allow</b> <i>{{ app.name }}</i> to access your account?" share-access: "Would you <b>allow</b> <i>{{ app.name }}</i> to access your account?"
permission-ask: "This application requires the following permissions:" permission-ask: "This application requires the following permissions:"
account-read: "Viewing account information:" account-read: "View account information."
account-write: "Modify account informations:" account-write: "Modify account information."
note-write: "Post." note-write: "Post."
like-write: "To react to posts." like-write: "React to posts."
following-write: "Follow or unfollow." following-write: "Follow and unfollow."
drive-read: "Read your drive." drive-read: "Read your drive."
drive-write: "Upload/delete files in your drive." drive-write: "Upload/delete files in your drive."
notification-read: "Read your notifications." notification-read: "Read your notifications."
notification-write: "Manage your notifications." notification-write: "Manage your notifications."
cancel: "Cancel" cancel: "Cancel"
accept: "Grant access." accept: "Allow access."
auth/views/index.vue: auth/views/index.vue:
loading: "Loading" loading: "Loading"
denied: "Application authorization denied." denied: "Application authorization has been denied."
denied-paragraph: "This application will not access your account." denied-paragraph: "This application will not access your account."
already-authorized: "This application has already been authorized." already-authorized: "This application has already been authorized."
allowed: "Application authorizations allowed.+" allowed: "Application authorizations allowed."
callback-url: "Going back to the application." callback-url: "Going back to the application."
please-go-back: "Please go back to the application." please-go-back: "Please go back to the application."
error: "Session does not exist." error: "Session does not exist."
@ -169,7 +169,7 @@ common/views/components/games/reversi/reversi.vue:
common/views/components/games/reversi/reversi.game.vue: common/views/components/games/reversi/reversi.game.vue:
surrender: "Surrender" surrender: "Surrender"
surrendered: "By surrender" surrendered: "By surrender"
is-llotheo: "The lesser one wins" is-llotheo: "The lesser one wins(Llotheo)"
looped-map: "Looped map" looped-map: "Looped map"
can-put-everywhere: "Can put everywhere" can-put-everywhere: "Can put everywhere"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
@ -179,13 +179,13 @@ common/views/components/games/reversi/reversi.index.vue:
rule: "How to play" rule: "How to play"
rule-desc: "Reversi is a strategy board game for two players, played on an 8×8 uncheckered board. There are sixty-four identical game pieces called disks (often spelled \"discs\"), which are light on one side and dark on the other. Players take turns placing disks on the board with their assigned color facing up. During a play, any disks of the opponent's color that are in a straight line and bounded by the disk just placed and another disk of the current player's color are turned over to the current player's color. The object of the game is to have the majority of disks turned to display your color when the last playable empty square is filled." rule-desc: "Reversi is a strategy board game for two players, played on an 8×8 uncheckered board. There are sixty-four identical game pieces called disks (often spelled \"discs\"), which are light on one side and dark on the other. Players take turns placing disks on the board with their assigned color facing up. During a play, any disks of the opponent's color that are in a straight line and bounded by the disk just placed and another disk of the current player's color are turned over to the current player's color. The object of the game is to have the majority of disks turned to display your color when the last playable empty square is filled."
mode-invite: "Invite" mode-invite: "Invite"
mode-invite-desc: "Invite to the game a user." mode-invite-desc: "Game with a specified user."
invitations: "You received invitation!" invitations: "Youve got an invitation!"
my-games: "My games" my-games: "My game"
all-games: "All games" all-games: "All games"
enter-username: "Enter username" enter-username: "Enter a username"
game-state: game-state:
ended: "Ended" ended: "Finished"
playing: "In Progress" playing: "In Progress"
common/views/components/games/reversi/reversi.room.vue: common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "Game settings" settings-of-the-game: "Game settings"
@ -194,14 +194,14 @@ common/views/components/games/reversi/reversi.room.vue:
black-or-white: "Black/White" black-or-white: "Black/White"
black-is: "Black is {}" black-is: "Black is {}"
rules: "Rules" rules: "Rules"
is-llotheo: "The lesser one wins" is-llotheo: "The lesser side wins"
looped-map: "Looped map" looped-map: "Looped map"
can-put-everywhere: "Can put everywhere" can-put-everywhere: "Can put everywhere"
settings-of-the-bot: "Bot settings" settings-of-the-bot: "Bot settings"
this-game-is-started-soon: "The game will begin soon" this-game-is-started-soon: "The game will begin in seconds"
waiting-for-other: "Waiting for the other party's preparation" waiting-for-other: "Waiting for the opponent"
waiting-for-me: "Waiting for the your preparation" waiting-for-me: "Waiting for the your preparation"
waiting-for-both: "Waiting for yours" waiting-for-both: "Prepareing"
cancel: "Cancel" cancel: "Cancel"
ready: "Ready" ready: "Ready"
cancel-ready: "Cancel \"Ready\"" cancel-ready: "Cancel \"Ready\""
@ -226,7 +226,7 @@ common/views/components/connect-failed.troubleshooter.vue:
no-server: "Unable to connect to the Misskey server" no-server: "Unable to connect to the Misskey server"
no-server-desc: "The network connection of your device is normal, but you could not connect to the Misskey server. There is a possibility that the server is either down, or under maintenance, please try again later." no-server-desc: "The network connection of your device is normal, but you could not connect to the Misskey server. There is a possibility that the server is either down, or under maintenance, please try again later."
success: "Successfully connected to the Misskey server" success: "Successfully connected to the Misskey server"
success-desc: "It seems to be able to connect. Please reload the page." success-desc: "Looks like we have a connection. Please reload the page."
flush: "Clean cache" flush: "Clean cache"
set-version: "Specify version" set-version: "Specify version"
common/views/components/messaging.vue: common/views/components/messaging.vue:
@ -239,13 +239,13 @@ common/views/components/messaging-room.vue:
no-history: "There is no further history" no-history: "There is no further history"
resize-form: "Drag to resize" resize-form: "Drag to resize"
new-message: "New message" new-message: "New message"
only-one-file-attached: "Only one file can be attached to a message." only-one-file-attached: "Only ONE file can be attached to a message."
common/views/components/messaging-room.form.vue: common/views/components/messaging-room.form.vue:
input-message-here: "Enter message here" input-message-here: "Enter message here"
send: "Send" send: "Send"
attach-from-local: "Attach files from your device" attach-from-local: "Attach files from your device"
attach-from-drive: "Attach files from your Drive" attach-from-drive: "Attach files from your Drive"
only-one-file-attached: "Only one file can be attached to a message." only-one-file-attached: "Only one file can be attached to the message."
common/views/components/messaging-room.message.vue: common/views/components/messaging-room.message.vue:
is-read: "Read" is-read: "Read"
deleted: "This message has been deleted" deleted: "This message has been deleted"
@ -260,9 +260,9 @@ common/views/components/nav.vue:
feedback: "Feedback" feedback: "Feedback"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
favorite: "Favorite this note" favorite: "Favorite this note"
pin: "Pin to your profile page" pin: "Pin to your profile"
delete: "Delete" delete: "Delete"
delete-confirm: "Are you sure you want to delete this post?" delete-confirm: "Delete this post?"
remote: "Show original note" remote: "Show original note"
common/views/components/poll.vue: common/views/components/poll.vue:
vote-to: "Vote for '{}'" vote-to: "Vote for '{}'"
@ -272,13 +272,13 @@ common/views/components/poll.vue:
show-result: "Show results" show-result: "Show results"
voted: "Voted" voted: "Voted"
common/views/components/poll-editor.vue: common/views/components/poll-editor.vue:
no-only-one-choice: "At least two choices are required for this survey." no-only-one-choice: "At least two choices are required"
choice-n: "Choice {}" choice-n: "Choice {}"
remove: "Delete this choice" remove: "Delete the choice"
add: "+ Add a choice" add: "+ Add a choice"
destroy: "Discard the poll" destroy: "Discard the poll"
common/views/components/reaction-picker.vue: common/views/components/reaction-picker.vue:
choose-reaction: "Express a reaction" choose-reaction: "Send a reaction"
common/views/components/signin.vue: common/views/components/signin.vue:
username: "Username" username: "Username"
password: "Password" password: "Password"
@ -287,17 +287,18 @@ common/views/components/signin.vue:
signin: "Sign in" signin: "Sign in"
or: "Or" or: "Or"
signin-with-twitter: "Log in with Twitter" signin-with-twitter: "Log in with Twitter"
login-failed: "Log in failed. Make sure you have entered your correct username and password."
common/views/components/signup.vue: common/views/components/signup.vue:
username: "Username" username: "Username"
checking: "Checking..." checking: "Confirming..."
available: "Available" available: "Available"
unavailable: "Unavailable" unavailable: "Unavailable"
error: "Network error" error: "Network error"
invalid-format: "Only use letters, numbers and -." invalid-format: "letters, numbers and _ are acceptable."
too-short: "Please enter at least 1 character!" too-short: "Should not be blank!"
too-long: "Please enter up to 20 characters." too-long: "Enter within 20 characters."
password: "Password" password: "Password"
password-placeholder: "We recommend more than 8 characters." password-placeholder: "More than 8 characters are recommended."
weak-password: "Weak password" weak-password: "Weak password"
normal-password: "Fair password" normal-password: "Fair password"
strong-password: "Strong password" strong-password: "Strong password"
@ -327,9 +328,9 @@ common/views/components/uploader.vue:
common/views/components/visibility-chooser.vue: common/views/components/visibility-chooser.vue:
public: "Public" public: "Public"
home: "Home" home: "Home"
home-desc: "Post to the home timeline only" home-desc: "Post to Home only"
followers: "Followers" followers: "Followers"
followers-desc: "Post to followers only" followers-desc: "Post to Followers only"
specified: "Direct" specified: "Direct"
specified-desc: "Post to specified users only" specified-desc: "Post to specified users only"
private: "Private" private: "Private"
@ -340,14 +341,14 @@ common/views/widgets/broadcast.vue:
next: "Next" next: "Next"
common/views/widgets/calendar.vue: common/views/widgets/calendar.vue:
year: "Year {}" year: "Year {}"
month: "Month {}" month: "{},"
day: "Day {}" day: "{}"
today: "Today: " today: "Today: "
this-month: "This month: " this-month: "This month: "
this-year: "This year: " this-year: "This year: "
common/views/widgets/donation.vue: common/views/widgets/donation.vue:
title: "Request for donations" title: "Request for donations"
text: "To keep Misskey up and running, we have to spend money on our domain name, the server costs and so on. Since we don't receive money from advertisements, we count on donations from all of you. If you're interested in helping, contact {}. Thank you for your contribution!" text: "To keep Misskey up and running, there have to happen some expense for the domain name, the server and so on. Since our policy is not to display any advertisements, we count on your donations. If you're interested in helping, contact {}. Thank you for your contribution!"
common/views/widgets/photo-stream.vue: common/views/widgets/photo-stream.vue:
title: "Photo stream" title: "Photo stream"
no-photos: "No photos" no-photos: "No photos"
@ -388,8 +389,8 @@ common/views/widgets/tips.vue:
tips-line20: "The percentage of the calendar widget shows the percentage of time elapsed." tips-line20: "The percentage of the calendar widget shows the percentage of time elapsed."
tips-line21: "You can also use the API to develop bots." tips-line21: "You can also use the API to develop bots."
tips-line23: "Mayu is so cute with its eyebrows." tips-line23: "Mayu is so cute with its eyebrows."
tips-line24: "Misskey started in 2014." tips-line24: "Misskey has been running since 2014."
tips-line25: "You can receive notification even if Misskey is not open in a compatible browser." tips-line25: "In a browser compatible with notification features, you can receive notifications in case Misskey is not open"
common/views/pages/follow.vue: common/views/pages/follow.vue:
signed-in-as: "Signed in as {}" signed-in-as: "Signed in as {}"
following: "Following" following: "Following"
@ -400,13 +401,13 @@ desktop:
banner-crop-title: "Crop the part that appears as a banner" banner-crop-title: "Crop the part that appears as a banner"
banner: "Banner" banner: "Banner"
uploading-banner: "Uploading a new banner" uploading-banner: "Uploading a new banner"
banner-updated: "Updated the banner" banner-updated: "Successfully updated the banner"
choose-banner: "Choose the banner" choose-banner: "Choose the banner"
avatar-crop-title: "Crop the part that appears as an avatar" avatar-crop-title: "Crop the part that appears as an avatar"
avatar: "Avatar" avatar: "Avatar"
uploading-avatar: "Uploading a new avatar" uploading-avatar: "Uploading a new avatar"
avatar-updated: "Updated the avatar" avatar-updated: "Successfully updated the avatar"
choose-avatar: "Choose an avatar image" choose-avatar: "Select an image for the avatar"
desktop/views/components/activity.chart.vue: desktop/views/components/activity.chart.vue:
total: "Black ... Total" total: "Black ... Total"
notes: "Blue ... Notes" notes: "Blue ... Notes"
@ -454,7 +455,7 @@ desktop/views/components/drive.file.vue:
rename-file: "Rename file" rename-file: "Rename file"
input-new-file-name: "Enter new name" input-new-file-name: "Enter new name"
copied: "Copied" copied: "Copied"
copied-url-to-clipboard: "Copied URL to clipboard" copied-url-to-clipboard: "URL has been copied to clipboard"
desktop/views/components/drive.folder.vue: desktop/views/components/drive.folder.vue:
unable-to-process: "The operation could not be completed." unable-to-process: "The operation could not be completed."
circular-reference-detected: "The destination folder is a subfolder of the folder you wish to move." circular-reference-detected: "The destination folder is a subfolder of the folder you wish to move."
@ -470,7 +471,7 @@ desktop/views/components/drive.nav-folder.vue:
desktop/views/components/drive.vue: desktop/views/components/drive.vue:
search: "Search" search: "Search"
load-more: "Load more" load-more: "Load more"
empty-draghover: "Drop it here, don't I look cute?" empty-draghover: "Drop it here! Yep, cuz you know I'm cute, right?"
empty-drive: "Your media storage is empty" empty-drive: "Your media storage is empty"
empty-drive-description: "Right-click to open the menu, or drag and drop a file onto here for uploading." empty-drive-description: "Right-click to open the menu, or drag and drop a file onto here for uploading."
empty-folder: "This folder is empty" empty-folder: "This folder is empty"
@ -480,7 +481,7 @@ desktop/views/components/drive.vue:
url-upload: "Upload from a URL" url-upload: "Upload from a URL"
url-of-file: "URL of file you want to upload" url-of-file: "URL of file you want to upload"
url-upload-requested: "Upload requested" url-upload-requested: "Upload requested"
may-take-time: "It may take some time for the upload to complete." may-take-time: "It may take some time until the upload is complete."
create-folder: "Create a folder" create-folder: "Create a folder"
folder-name: "Folder name" folder-name: "Folder name"
contextmenu: contextmenu:
@ -488,7 +489,7 @@ desktop/views/components/drive.vue:
upload: "Upload a file" upload: "Upload a file"
url-upload: "Upload from a URL" url-upload: "Upload from a URL"
desktop/views/components/media-image.vue: desktop/views/components/media-image.vue:
sensitive: "The content is NSFW" sensitive: "NSFW"
click-to-show: "Click to show" click-to-show: "Click to show"
desktop/views/components/media-video.vue: desktop/views/components/media-video.vue:
sensitive: "The content is NSFW" sensitive: "The content is NSFW"
@ -505,7 +506,7 @@ desktop/views/components/followers.vue:
desktop/views/components/following-window.vue: desktop/views/components/following-window.vue:
following: "Following {}" following: "Following {}"
desktop/views/components/following.vue: desktop/views/components/following.vue:
empty: "You dont follow anyone." empty: "It seems you don't have any following users…"
desktop/views/components/friends-maker.vue: desktop/views/components/friends-maker.vue:
title: "Recommended users:" title: "Recommended users:"
empty: "Couldn't find any recommended users." empty: "Couldn't find any recommended users."
@ -527,8 +528,8 @@ desktop/views/components/messaging-window.vue:
title: "Messaging" title: "Messaging"
desktop/views/components/note-detail.vue: desktop/views/components/note-detail.vue:
more: "Load more conversations" more: "Load more conversations"
private: "This post is private" private: "Post is private"
deleted: "This post has been removed" deleted: "Post has been removed"
reposted-by: "Reposted by {}" reposted-by: "Reposted by {}"
location: "Location" location: "Location"
renote: "Repost" renote: "Repost"
@ -539,8 +540,8 @@ desktop/views/components/notes.note.vue:
renote: "Repost" renote: "Repost"
add-reaction: "Add a reaction" add-reaction: "Add a reaction"
detail: "Show details" detail: "Show details"
private: "This post is private" private: "Post is private"
deleted: "The post has been deleted" deleted: "Post has been deleted"
hide: "Hide" hide: "Hide"
see-more: "See more" see-more: "See more"
desktop/views/components/notes.vue: desktop/views/components/notes.vue:
@ -554,15 +555,15 @@ desktop/views/components/post-form.vue:
add-visible-user: "+Add a user" add-visible-user: "+Add a user"
attach-location-information: "Attach location information" attach-location-information: "Attach location information"
hide-contents: "Hide contents" hide-contents: "Hide contents"
reply-placeholder: "Reply to this note..." reply-placeholder: "Reply to this post..."
quote-placeholder: "Quote this note..." quote-placeholder: "Quote this Post..."
submit: "Post" submit: "Post"
reply: "Reply" reply: "Reply"
renote: "Repost" renote: "Repost"
posted: "Posted!" posted: "Posted!"
replied: "Replied!" replied: "Replied!"
reposted: "Reposted!" reposted: "Reposted!"
note-failed: "Failed to post the note" note-failed: "Failed to post"
reply-failed: "Failed to reply" reply-failed: "Failed to reply"
renote-failed: "Failed to repost" renote-failed: "Failed to repost"
posting: "Posting" posting: "Posting"
@ -575,12 +576,12 @@ desktop/views/components/post-form.vue:
recent-tags: "Recent" recent-tags: "Recent"
click-to-tagging: "Click to tagging" click-to-tagging: "Click to tagging"
visibility: "Visibility" visibility: "Visibility"
geolocation-alert: "Your device does not support geolocalization." geolocation-alert: "Your device does not provide location services."
error: "Error" error: "Error"
enter-username: "Please enter a username..." enter-username: "Please enter a username..."
annotations: "内容への注釈 (オプション)" annotations: "Annotations for the post (optional)"
desktop/views/components/post-form-window.vue: desktop/views/components/post-form-window.vue:
note: "New note" note: "New Post"
reply: "Reply" reply: "Reply"
attaches: "{} media attached" attaches: "{} media attached"
uploading-media: "Uploading {} media" uploading-media: "Uploading {} media"
@ -592,9 +593,9 @@ desktop/views/components/renote-form.vue:
renote: "Repost" renote: "Repost"
reposting: "Reposting..." reposting: "Reposting..."
success: "Reposted!" success: "Reposted!"
failure: "Repost failed" failure: "Failed to Repost"
desktop/views/components/renote-form-window.vue: desktop/views/components/renote-form-window.vue:
title: "Are you sure you want to repost this?" title: "Do you want to Repost it?"
desktop/views/components/settings-window.vue: desktop/views/components/settings-window.vue:
settings: "Settings" settings: "Settings"
desktop/views/components/settings.vue: desktop/views/components/settings.vue:
@ -613,7 +614,7 @@ desktop/views/components/settings.vue:
fetch-on-scroll: "Endless loading on scroll" fetch-on-scroll: "Endless loading on scroll"
fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content." fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content."
auto-popout: "Auto pop-out window" auto-popout: "Auto pop-out window"
auto-popout-desc: "Pops-out a newly opened window (onto a new tab), if possible. This setting is stored in the browser." auto-popout-desc: "If it's possible, pop-out display will be used instead of opening a new window. This setting is stored in your browser."
advanced: "Advanced settings" advanced: "Advanced settings"
api-via-stream: "API request via stream" api-via-stream: "API request via stream"
api-via-stream-desc: "API request is performed via the WebSocket connection instead of native fetch API (for better performance). This setting is stored in the browser." api-via-stream-desc: "API request is performed via the WebSocket connection instead of native fetch API (for better performance). This setting is stored in the browser."
@ -625,11 +626,13 @@ desktop/views/components/settings.vue:
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
gradient-window-header: "Use gradients on window headers" gradient-window-header: "Use gradients on window headers"
post-form-on-timeline: "Display post form at the top of the timeline" post-form-on-timeline: "Display post form at the top of the timeline"
suggest-recent-hashtags: "Show recent popular hashtags on the post form"
show-reply-target: "Display reply target" show-reply-target: "Display reply target"
show-my-renotes: "Show my reposts in the timeline" show-my-renotes: "Show my renotes in the timeline"
show-renoted-my-notes: "Show my posts that have been shared in the timeline" show-renoted-my-notes: "Show renoted my posts in timelines"
show-maps: "Show the map" show-local-renotes: "Show renoted local posts in timelines"
show-maps-desc: "Automatically show the location on the map attached to this post." show-maps: "Display a map to show the location"
show-maps-desc: "If there comes a post contains location information, show a map to display the location."
sound: "Sound" sound: "Sound"
enable-sounds: "Enable sound" enable-sounds: "Enable sound"
enable-sounds-desc: "Play a sound when you receive a post/message. This setting is stored in the browser." enable-sounds-desc: "Play a sound when you receive a post/message. This setting is stored in the browser."
@ -674,34 +677,34 @@ desktop/views/components/settings.vue:
third-parties: "Third-parties" third-parties: "Third-parties"
desktop/views/components/settings.2fa.vue: desktop/views/components/settings.2fa.vue:
intro: "If you set up 2-step verification, you will not only need a password at sign-in, but also a pre-registered physical device (such as your smartphone), which will improve security." intro: "If you set up 2-step verification, you will not only need a password at sign-in, but also a pre-registered physical device (such as your smartphone), which will improve security."
detail: "See details..." detail: "Details"
url: "https://www.google.com/landing/2step/" url: "https://www.google.com/landing/2step/"
caution: "If you lose access to your device, you won't be able to connect to Misskey anymore!" caution: "If you lose access to your registered device, you won't be able to connect to Misskey anymore!"
register: "Register a device" register: "Register a device"
already-registered: "A device is already registered" already-registered: "This device is already registered"
unregister: "Disable" unregister: "Unregister"
unregistered: "Two-factor authentication has been disabled." unregistered: "Two-factor authentication has been disabled."
enter-password: "Enter the password" enter-password: "Enter the password"
authenticator: "First, you need to install Google Authenticator on your device:" authenticator: "First, you need to install Google Authenticator on your device:"
howtoinstall: "How to install" howtoinstall: "How to install"
scan: "And then, scan the QR code:" scan: "And then, scan the QR code:"
done: "Please enter the token displaying on your device:" done: "Please enter the token displayed on your device:"
submit: "Submit" submit: "Submit"
success: "Settings saved!" success: "Settings saved!"
failed: "Failed to setup. Please ensure that the token is correct." failed: "Failed to setup. Please ensure that the token is correct."
info: "From now on, enter the token that is displayed on your device in addition to your password when signing-in to Misskey." info: "From the next time you sign in to Misskey, the token displayed on your device will be necessary too, as well as the password."
desktop/views/components/settings.api.vue: desktop/views/components/settings.api.vue:
intro: "To access the API, set this token as the key 'i' of request parameters." intro: "To access the API, set this token as the key 'i' of request parameters."
caution: "Please do not show this token to third parties (do not enter it somewhere else other than here) otherwise your account could get compromised." caution: "Do not enter this token to any apps nor tell this token to others otherwise your account may get compromised."
regeneration-of-token: "In the unlikely event that this token leaks out, you can regenerate it." regeneration-of-token: "If your token gets leaked, you can regenerate it."
regenerate-token: "Regenerate the token" regenerate-token: "Regenerate the token"
token: "Token:" token: "Token:"
enter-password: "Please enter the password" enter-password: "Please enter the password"
desktop/views/components/settings.apps.vue: desktop/views/components/settings.apps.vue:
no-apps: "No linked applications" no-apps: "No linked applications"
desktop/views/components/settings.drive.vue: desktop/views/components/settings.drive.vue:
max: "Max " max: "Max"
in-use: " in use." in-use: "In use"
desktop/views/components/settings.mute.vue: desktop/views/components/settings.mute.vue:
no-users: "No muted users" no-users: "No muted users"
desktop/views/components/settings.password.vue: desktop/views/components/settings.password.vue:
@ -713,18 +716,18 @@ desktop/views/components/settings.password.vue:
changed: "Password updated" changed: "Password updated"
desktop/views/components/settings.profile.vue: desktop/views/components/settings.profile.vue:
avatar: "Avatar" avatar: "Avatar"
choice-avatar: "Choose an image" choice-avatar: "Select an image"
name: "Name" name: "Name"
location: "Location" location: "Location"
description: "Description" description: "Description"
birthday: "Birthday" birthday: "Birthday"
save: "Update profile" save: "Update profile"
locked-account: "Protect your account" locked-account: "Protect your account"
is-locked: "Make a note private" is-locked: "Make your posts private"
other: "Other" other: "Other"
is-bot: "This account is a Bot" is-bot: "This account is a Bot"
is-cat: "This account is a Cat" is-cat: "This account is a Cat"
profile-updated: "Profile updated" profile-updated: "Your profile has been updated"
desktop/views/components/sub-note-content.vue: desktop/views/components/sub-note-content.vue:
private: "This post is private" private: "This post is private"
deleted: "This post has been deleted" deleted: "This post has been deleted"
@ -740,7 +743,7 @@ desktop/views/components/timeline.vue:
list: "Lists" list: "Lists"
desktop/views/components/ui.header.vue: desktop/views/components/ui.header.vue:
welcome-back: "Welcome back," welcome-back: "Welcome back,"
adjective: "Ms." adjective: "-san"
desktop/views/components/ui.header.account.vue: desktop/views/components/ui.header.account.vue:
profile: "Your profile" profile: "Your profile"
drive: "Media storage" drive: "Media storage"
@ -768,7 +771,7 @@ desktop/views/components/received-follow-requests-window.vue:
reject: "Reject" reject: "Reject"
desktop/views/components/user-lists-window.vue: desktop/views/components/user-lists-window.vue:
title: "User lists" title: "User lists"
create-list: "Create new list" create-list: "Create list"
list-name: "List name" list-name: "List name"
desktop/views/components/user-preview.vue: desktop/views/components/user-preview.vue:
notes: "Posts" notes: "Posts"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "Pop-out" popout: "Pop-out"
close: "Close" close: "Close"
desktop/views/pages/admin/admin.vue:
dashboard: "Dashboard"
drive: "Drive"
users: "Users"
update: "Updates"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "Dashboard"
all-users: "All Users"
original-users: "Users on this instance"
all-notes: "All Posts"
original-notes: "Posts on this instance"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "Suspend a user"
suspend: "Suspend"
suspended: "Successfully suspended."
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "Unsuspend users"
unsuspend: "Unsuspend"
unsuspended: "The user has successfully unsuspended."
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Only media posts" is-media-only: "Only media posts"
is-media-view: "Media view" is-media-view: "Media view"
@ -797,7 +819,7 @@ desktop/views/pages/welcome.vue:
gotit: "Got it!" gotit: "Got it!"
signin: "Log In" signin: "Log In"
signup: "Sign up" signup: "Sign up"
signin-button: "Log in" signin-button: "Logging in..."
signup-button: "Sign up" signup-button: "Sign up"
timeline: "Timeline" timeline: "Timeline"
powered-by-misskey: "Powered by <b>Misskey</b>." powered-by-misskey: "Powered by <b>Misskey</b>."
@ -808,35 +830,35 @@ desktop/views/pages/favorites.vue:
desktop/views/pages/home-customize.vue: desktop/views/pages/home-customize.vue:
title: "Customize home layout" title: "Customize home layout"
desktop/views/pages/note.vue: desktop/views/pages/note.vue:
prev: "Previous note" prev: "Previous post"
next: "Next note" next: "Next post"
desktop/views/pages/selectdrive.vue: desktop/views/pages/selectdrive.vue:
title: "Choose file(s)" title: "Choose file(s)"
ok: "OK" ok: "OK"
cancel: "Cancel" cancel: "Cancel"
upload: "Upload files from your device" upload: "Upload files from your device"
desktop/views/pages/search.vue: desktop/views/pages/search.vue:
not-available: "The search feature is not available." not-available: "The search feature is not available for now."
not-found: "No posts were found for '{}'" not-found: "No posts were found for '{}'"
desktop/views/pages/share.vue: desktop/views/pages/share.vue:
share-with: "Share with {}." share-with: "Share with {}."
desktop/views/pages/tag.vue: desktop/views/pages/tag.vue:
no-posts-found: "No posts \"{}\" found." no-posts-found: "No posts contains \"{}\" found."
desktop/views/pages/user-list.users.vue: desktop/views/pages/user-list.users.vue:
users: "User" users: "User"
add-user: "Add a user" add-user: "Add a user"
username: "Username" username: "Username"
desktop/views/pages/user/user.followers-you-know.vue: desktop/views/pages/user/user.followers-you-know.vue:
title: "Followers you know" title: "Followers you may know"
loading: "Loading" loading: "Loading"
no-users: "No followers you know" no-users: "No followers you know"
desktop/views/pages/user/user.friends.vue: desktop/views/pages/user/user.friends.vue:
title: "Frequent mentions" title: "Frequent mentions"
loading: "Loading" loading: "Loading"
no-users: "No users" no-users: "No frequent mentions"
desktop/views/pages/user/user.vue: desktop/views/pages/user/user.vue:
is-suspended: "This account has been suspended." is-suspended: "This account has been suspended."
is-remote: "This user is a remote user, so the information about them that you see here is not complete. " is-remote: "The user is a remote user. The profile that you see here may not complete."
view-remote: "See their complete profile" view-remote: "See their complete profile"
desktop/views/pages/user/user.home.vue: desktop/views/pages/user/user.home.vue:
last-used-at: "Last active:" last-used-at: "Last active:"
@ -853,7 +875,7 @@ desktop/views/pages/user/user.profile.vue:
muted: "Muting" muted: "Muting"
unmute: "Unmute" unmute: "Unmute"
push-to-a-list: "Add to list" push-to-a-list: "Add to list"
list-pushed: "You added {user} to {list}." list-pushed: "Successfully added {user} to {list}."
desktop/views/pages/user/user.header.vue: desktop/views/pages/user/user.header.vue:
posts: "Notes" posts: "Notes"
following: "Following" following: "Following"
@ -861,18 +883,18 @@ desktop/views/pages/user/user.header.vue:
is-bot: "This account is a Bot" is-bot: "This account is a Bot"
desktop/views/pages/user/user.timeline.vue: desktop/views/pages/user/user.timeline.vue:
default: "Posts" default: "Posts"
with-replies: "Notes and replies" with-replies: "Posts and replies"
with-media: "Media" with-media: "Media"
empty: "This user doesn't seem to have posted anything yet." empty: "This user doesn't seem to have posted anything yet."
desktop/views/widgets/messaging.vue: desktop/views/widgets/messaging.vue:
title: "Messaging" title: "Message"
desktop/views/widgets/notifications.vue: desktop/views/widgets/notifications.vue:
title: "Notifications" title: "Notifications"
settings: "Settings" settings: "Settings"
desktop/views/widgets/polls.vue: desktop/views/widgets/polls.vue:
title: "Polls" title: "Polls"
refresh: "refresh" refresh: "refresh"
nothing: "Nothing" nothing: "No polls found!"
desktop/views/widgets/post-form.vue: desktop/views/widgets/post-form.vue:
title: "Post" title: "Post"
note: "Post" note: "Post"
@ -882,11 +904,11 @@ desktop/views/widgets/profile.vue:
desktop/views/widgets/trends.vue: desktop/views/widgets/trends.vue:
title: "Trend" title: "Trend"
refresh: "refresh" refresh: "refresh"
nothing: "Nothing" nothing: "No trends found!"
desktop/views/widgets/users.vue: desktop/views/widgets/users.vue:
title: "Recommended users" title: "Recommended users"
refresh: "refresh" refresh: "refresh"
no-one: "No one" no-one: "Anyone!"
mobile/views/components/drive.vue: mobile/views/components/drive.vue:
drive: "Media storage" drive: "Media storage"
used: "used" used: "used"
@ -916,7 +938,7 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)" hash: "Hash (md5)"
exif: "EXIF" exif: "EXIF"
mobile/views/components/media-image.vue: mobile/views/components/media-image.vue:
sensitive: "The content is NSFW" sensitive: "NSFW"
click-to-show: "Click to show" click-to-show: "Click to show"
mobile/views/components/media-video.vue: mobile/views/components/media-video.vue:
sensitive: "The content is NSFW" sensitive: "The content is NSFW"
@ -927,7 +949,7 @@ mobile/views/components/follow-button.vue:
request-pending: "Pending follow request" request-pending: "Pending follow request"
follow-request: "Follow request" follow-request: "Follow request"
mobile/views/components/friends-maker.vue: mobile/views/components/friends-maker.vue:
title: "Let's follow users" title: "Let's follow them"
empty: "Featured user was not found." empty: "Featured user was not found."
fetching: "Loading" fetching: "Loading"
refresh: "See more" refresh: "See more"
@ -958,7 +980,7 @@ mobile/views/components/notes.vue:
failed: "Failed to load" failed: "Failed to load"
retry: "Retry" retry: "Retry"
mobile/views/components/notifications.vue: mobile/views/components/notifications.vue:
more: "More" more: "See more"
empty: "No notifications" empty: "No notifications"
mobile/views/components/post-form.vue: mobile/views/components/post-form.vue:
add-visible-user: "Add a user" add-visible-user: "Add a user"
@ -967,7 +989,7 @@ mobile/views/components/post-form.vue:
renote: "Renote" renote: "Renote"
quote-placeholder: "Quote this post... (optional)" quote-placeholder: "Quote this post... (optional)"
reply-placeholder: "Reply to this note..." reply-placeholder: "Reply to this note..."
cw-placeholder: "Comments about content (optional)" cw-placeholder: "Comments for the post (optional)"
location-alert: "Your device does not provide location services" location-alert: "Your device does not provide location services"
error: "Error" error: "Error"
username-prompt: "Enter user name" username-prompt: "Enter user name"
@ -981,7 +1003,7 @@ mobile/views/components/timeline.vue:
load-more: "More" load-more: "More"
mobile/views/components/ui.header.vue: mobile/views/components/ui.header.vue:
welcome-back: "Welcome back, " welcome-back: "Welcome back, "
adjective: "Ms." adjective: "Sir"
mobile/views/components/ui.nav.vue: mobile/views/components/ui.nav.vue:
timeline: "Timeline" timeline: "Timeline"
notifications: "Notifications" notifications: "Notifications"
@ -993,12 +1015,12 @@ mobile/views/components/ui.nav.vue:
user-lists: "Lists" user-lists: "Lists"
widgets: "Widgets" widgets: "Widgets"
game: "Games" game: "Games"
darkmode: "Dark mode" darkmode: "Dark theme"
settings: "Settings" settings: "Settings"
about: "About Misskey" about: "About Misskey"
mobile/views/components/user-timeline.vue: mobile/views/components/user-timeline.vue:
no-notes: "It seems this user hasn't posted anything yet." no-notes: "It seems this user hasn't posted anything yet."
no-notes-with-media: "There are no notes with media attachments" no-notes-with-media: "There are no posts attaching media"
load-more: "More" load-more: "More"
mobile/views/components/users-list.vue: mobile/views/components/users-list.vue:
all: "All" all: "All"
@ -1013,7 +1035,7 @@ mobile/views/pages/drive.vue:
drive: "Drive" drive: "Drive"
more: "Load more" more: "Load more"
mobile/views/pages/signup.vue: mobile/views/pages/signup.vue:
lets-start: "Let's start! 📦" lets-start: "Your account is now ready! 📦"
mobile/views/pages/followers.vue: mobile/views/pages/followers.vue:
followers-of: "Followers of {}" followers-of: "Followers of {}"
mobile/views/pages/following.vue: mobile/views/pages/following.vue:
@ -1082,19 +1104,20 @@ mobile/views/pages/settings.vue:
specify-language: "Select your language" specify-language: "Select your language"
design: "Design and display" design: "Design and display"
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
i-am-under-limited-internet: "I'm under limited internet" i-am-under-limited-internet: "I'm in limited bandwidth"
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
timeline: "Timeline" timeline: "Timeline"
show-reply-target: "Show reply target" show-reply-target: "Show reply target"
show-my-renotes: "Show my reposts" show-my-renotes: "Show my reposts"
show-renoted-my-notes: "Show my reposted posts" show-renoted-my-notes: "Show renoted my posts"
show-local-renotes: "Show renoted local posts"
post-style: "Post design" post-style: "Post design"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Smart" post-style-smart: "Smart"
behavior: "Behavior" behavior: "Behavior"
fetch-on-scroll: "Endless loading on scroll" fetch-on-scroll: "Endless loading on scroll"
disable-via-mobile: "Don't mark the post as 'from mobile'" disable-via-mobile: "Don't mark the post as 'from mobile'"
load-raw-images: "Show attached images in high-quality" load-raw-images: "Show attached images in original quality"
load-remote-media: "Show media from a remote server" load-remote-media: "Show media from a remote server"
twitter: "Twitter integration" twitter: "Twitter integration"
twitter-connect: "Connect to your Twitter account" twitter-connect: "Connect to your Twitter account"
@ -1115,13 +1138,13 @@ mobile/views/pages/user.vue:
follows-you: "Follows you" follows-you: "Follows you"
following: "Following" following: "Following"
followers: "Followers" followers: "Followers"
notes: "Notes" notes: "Posts"
overview: "Overview" overview: "Overview"
timeline: "Timeline" timeline: "Timeline"
media: "Media" media: "Media"
is-suspended: "This account has been suspended." is-suspended: "This account has been suspended."
is-remote: "This user is a remote user, so the information you see here is not complete." is-remote: "The user is a remote user. The profile that you see here may not complete."
view-remote: "See their complete profile" view-remote: "See his/her complete profile"
mobile/views/pages/user/home.vue: mobile/views/pages/user/home.vue:
recent-notes: "Recent notes" recent-notes: "Recent notes"
images: "Images" images: "Images"
@ -1144,8 +1167,8 @@ mobile/views/pages/user/home.photos.vue:
loading: "Loading" loading: "Loading"
no-photos: "No photos" no-photos: "No photos"
docs: docs:
edit-this-page-on-github: "Did you find an error or do you want to contribute to the documentation? " edit-this-page-on-github: "Found a mistake or want to contribute for the documentation?"
edit-this-page-on-github-link: "Edit this page on Github!" edit-this-page-on-github-link: "Edit this page at GitHub!"
api: api:
entities: entities:
properties: "Properties" properties: "Properties"
@ -1156,11 +1179,11 @@ docs:
require-credential: "This endpoint requires the authentication information." require-credential: "This endpoint requires the authentication information."
require-permission: "This endpoint requires {permission} permission." require-permission: "This endpoint requires {permission} permission."
has-limit: "There is a rate limit." has-limit: "There is a rate limit."
duration-limit: "You can't request when a frequency of a request in during {duration} milliseconds exceeds {max} times." duration-limit: "If you have sent your requests more than {max} times in {duration} milliseconds, you will be unable to send more requests."
min-interval-limit: "You can't request before {interval} milliseconds have passed since the previous request." min-interval-limit: "If {interval} milliseconds haven't passed since the last request, you can't send a request."
show-src: "You can view the source code for this endpoint." show-src: "You can view the source code for this endpoint."
show-src-link: "See the code on GitHub" show-src-link: "See the code on GitHub"
generated: "This doc is generated by an API definition." generated: "This document is generated by the API definition."
props: props:
name: "Name" name: "Name"
type: "Type" type: "Type"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado." my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado."
i-like-sushi: "Prefiero sushi a pudín" i-like-sushi: "Prefiero sushi a pudín"
show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi" show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi"
verified-user: "Usuario verificado" verified-user: "公式アカウント"
disable-animated-mfm: "Desactivar texto animado en una publicación" disable-animated-mfm: "Desactivar texto animado en una publicación"
reversi: reversi:
drawn: "Empatado" drawn: "Empatado"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "Entra" signin: "Entra"
or: "O" or: "O"
signin-with-twitter: "Ingresar con Twitter" signin-with-twitter: "Ingresar con Twitter"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "Usuario" username: "Usuario"
checking: "Comprobando..." checking: "Comprobando..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "Usar iconos circulares" circle-icons: "Usar iconos circulares"
gradient-window-header: "Usar degradados en las cabeceras de las páginas" gradient-window-header: "Usar degradados en las cabeceras de las páginas"
post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "Votre token vient d'être généré, vous allez maintenant être déconnecté." 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 (au pudding)" i-like-sushi: "Je préfère les sushis (au pudding)"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi" show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
verified-user: "Utilisateur·trice vérifié·e" verified-user: "公式アカウント"
disable-animated-mfm: "Désactiver les textes animés dans les publications" disable-animated-mfm: "Désactiver les textes animés dans les publications"
reversi: reversi:
drawn: "Partie nulle" drawn: "Partie nulle"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "Se connecter" signin: "Se connecter"
or: "Ou" or: "Ou"
signin-with-twitter: "Se connecter via Twitter" signin-with-twitter: "Se connecter via Twitter"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "Nom d'utilisateur" username: "Nom d'utilisateur"
checking: "Vérification" checking: "Vérification"
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "Afficher les réponses" show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications dans le fil" show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Afficher la carte" show-maps: "Afficher la carte"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "Son" sound: "Son"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "Fermer" close: "Fermer"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Les publications médias uniquement" is-media-only: "Les publications médias uniquement"
is-media-view: "Vue média" is-media-view: "Vue média"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
show-reply-target: "Afficher les réponses" show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications" show-my-renotes: "Afficher mes republications"
show-renoted-my-notes: "Afficher les notes que j'ai repartagé" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "Style de la publication" post-style: "Style de la publication"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Intelligent" post-style-smart: "Intelligent"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -90,7 +90,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
@ -314,8 +314,11 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
invitation-code: "招待コード"
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
available: "利用できます" available: "利用できます"
@ -707,9 +710,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
@ -897,6 +902,29 @@ desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1270,7 +1298,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -12,7 +12,7 @@ common:
application-authorization: "앱의 연계" application-authorization: "앱의 연계"
close: "닫기" close: "닫기"
do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。" do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。"
got-it: "わかった" got-it: "알았습니다"
customization-tips: customization-tips:
title: "사용자 정의 팁" title: "사용자 정의 팁"
paragraph1: "홈 정의는 위젯을 추가 / 삭제하거나 드래그 앤 드롭하여 정렬 할 수 있습니다." paragraph1: "홈 정의는 위젯을 추가 / 삭제하거나 드래그 앤 드롭하여 정렬 할 수 있습니다."
@ -39,7 +39,7 @@ common:
weeks_ago: "{}주전" weeks_ago: "{}주전"
months_ago: "{}개월전" months_ago: "{}개월전"
years_ago: "{}년전" years_ago: "{}년전"
month-and-day: "{month} {day}" month-and-day: "{month} {day}"
trash: "휴지통" trash: "휴지통"
weekday-short: weekday-short:
sunday: "일" sunday: "일"
@ -84,7 +84,7 @@ common:
my-token-regenerated: "당신의 토큰이 업데이트되어 있기 때문에 로그 아웃합니다." my-token-regenerated: "당신의 토큰이 업데이트되어 있기 때문에 로그 아웃합니다."
i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아" i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아"
show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시" show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시"
verified-user: "인증 된 사용자" verified-user: "公式アカウント"
disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할" disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할"
reversi: reversi:
drawn: "무승부" drawn: "무승부"
@ -122,13 +122,13 @@ common:
tips: "팁" tips: "팁"
hashtags: "해시 태그" hashtags: "해시 태그"
deck: deck:
widgets: "ウィジェット" widgets: "위젯"
home: "ホーム" home: ""
local: "ローカル" local: "로컬"
hybrid: "ソーシャル" hybrid: "소셜"
global: "グローバル" global: "글로벌"
notifications: "通知" notifications: "통지"
list: "リスト" list: "목록"
swap-left: "左に移動" swap-left: "左に移動"
swap-right: "右に移動" swap-right: "右に移動"
swap-up: "上に移動" swap-up: "上に移動"
@ -150,10 +150,10 @@ auth/views/form.vue:
drive-write: "ドライブを操作する。" drive-write: "ドライブを操作する。"
notification-read: "通知を見る。" notification-read: "通知を見る。"
notification-write: "通知を操作する。" notification-write: "通知を操作する。"
cancel: "キャンセル" cancel: "취소"
accept: "アクセスを許可" accept: "アクセスを許可"
auth/views/index.vue: auth/views/index.vue:
loading: "読み込み中" loading: "로드 중"
denied: "アプリケーションの連携をキャンセルしました。" denied: "アプリケーションの連携をキャンセルしました。"
denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。" denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。"
already-authorized: "このアプリは既に連携済みです" already-authorized: "このアプリは既に連携済みです"
@ -165,18 +165,18 @@ auth/views/index.vue:
common/views/components/games/reversi/reversi.vue: common/views/components/games/reversi/reversi.vue:
matching: matching:
waiting-for: "{}を待っています" waiting-for: "{}を待っています"
cancel: "キャンセル" cancel: "취소"
common/views/components/games/reversi/reversi.game.vue: common/views/components/games/reversi/reversi.game.vue:
surrender: "投了" surrender: "기권"
surrendered: "投了により" surrendered: "投了により"
is-llotheo: "石の少ない方が勝ち(ロセオ)" is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ" looped-map: "루프 지도"
can-put-everywhere: "どこでも置けるモード" can-put-everywhere: "どこでも置けるモード"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi" title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう" sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"
invite: "招待" invite: "초대"
rule: "遊び方" rule: "게임 방법"
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。" rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
mode-invite: "招待" mode-invite: "招待"
mode-invite-desc: "指定したユーザーと対戦するモードです。" mode-invite-desc: "指定したユーザーと対戦するモードです。"
@ -185,26 +185,26 @@ common/views/components/games/reversi/reversi.index.vue:
all-games: "みんなの対局" all-games: "みんなの対局"
enter-username: "ユーザー名を入力してください" enter-username: "ユーザー名を入力してください"
game-state: game-state:
ended: "終了" ended: "종료"
playing: "進行中" playing: "진행중"
common/views/components/games/reversi/reversi.room.vue: common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "ゲームの設定" settings-of-the-game: "ゲームの設定"
choose-map: "マップを選択" choose-map: "マップを選択"
random: "ランダム" random: "ランダム"
black-or-white: "先手/後手" black-or-white: "先手/後手"
black-is: "{}が黒" black-is: "{}が黒"
rules: "ルール" rules: "규칙"
is-llotheo: "石の少ない方が勝ち(ロセオ)" is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ" looped-map: "루프 지도"
can-put-everywhere: "どこでも置けるモード" can-put-everywhere: "どこでも置けるモード"
settings-of-the-bot: "Botの設定" settings-of-the-bot: "Botの設定"
this-game-is-started-soon: "ゲームは数秒後に開始されます" this-game-is-started-soon: "ゲームは数秒後に開始されます"
waiting-for-other: "相手の準備が完了するのを待っています" waiting-for-other: "相手の準備が完了するのを待っています"
waiting-for-me: "あなたの準備が完了するのを待っています" waiting-for-me: "あなたの準備が完了するのを待っています"
waiting-for-both: "準備中" waiting-for-both: "준비중"
cancel: "キャンセル" cancel: "취소"
ready: "準備完了" ready: "준비 완료"
cancel-ready: "準備続行" cancel-ready: "준비 계속"
common/views/components/connect-failed.vue: common/views/components/connect-failed.vue:
title: "サーバーに接続できません" title: "サーバーに接続できません"
description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。" description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。"
@ -231,7 +231,7 @@ common/views/components/connect-failed.troubleshooter.vue:
set-version: "バージョン指定" set-version: "バージョン指定"
common/views/components/messaging.vue: common/views/components/messaging.vue:
search-user: "ユーザーを探す" search-user: "ユーザーを探す"
you: "あなた" you: "당신"
no-history: "履歴はありません" no-history: "履歴はありません"
common/views/components/messaging-room.vue: common/views/components/messaging-room.vue:
empty: "このユーザーと話したことはありません" empty: "このユーザーと話したことはありません"
@ -242,12 +242,12 @@ common/views/components/messaging-room.vue:
only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです" only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです"
common/views/components/messaging-room.form.vue: common/views/components/messaging-room.form.vue:
input-message-here: "ここにメッセージを入力" input-message-here: "ここにメッセージを入力"
send: "送信" send: "전송"
attach-from-local: "PCからファイルを添付する" attach-from-local: "PCからファイルを添付する"
attach-from-drive: "ドライブからファイルを添付する" attach-from-drive: "ドライブからファイルを添付する"
only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです" only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです"
common/views/components/messaging-room.message.vue: common/views/components/messaging-room.message.vue:
is-read: "既読" is-read: "읽음"
deleted: "このメッセージは削除されました" deleted: "このメッセージは削除されました"
common/views/components/nav.vue: common/views/components/nav.vue:
about: "Misskeyについて" about: "Misskeyについて"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "Twój token został wygenerowany. Zostaniesz wylogowany." my-token-regenerated: "Twój token został wygenerowany. Zostaniesz wylogowany."
i-like-sushi: "Wolę sushi od puddingu" i-like-sushi: "Wolę sushi od puddingu"
show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi" show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi"
verified-user: "Zweryfikowany użytkownik" verified-user: "公式アカウント"
disable-animated-mfm: "Wyłącz animowany tekst we wpisach" disable-animated-mfm: "Wyłącz animowany tekst we wpisach"
reversi: reversi:
drawn: "Remis" drawn: "Remis"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "Zaloguj" signin: "Zaloguj"
or: "または" or: "または"
signin-with-twitter: "Zaloguj się za pomocą Twittera" signin-with-twitter: "Zaloguj się za pomocą Twittera"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "Nazwa użytkownika" username: "Nazwa użytkownika"
checking: "Sprawdzanie…" checking: "Sprawdzanie…"
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "Używaj okrągłych ikon" circle-icons: "Używaj okrągłych ikon"
gradient-window-header: "Używaj gradientów na pasku tytułu okna" gradient-window-header: "Używaj gradientów na pasku tytułu okna"
post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "Pokazuj cel odpowiedzi" show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia na osi czasu" show-my-renotes: "Pokazuj moje udostępnienia na osi czasu"
show-renoted-my-notes: "Pokazuj udostępnienia moich wpisów na osi czasu" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Automatycznie pokazuj mapę" show-maps: "Automatycznie pokazuj mapę"
show-maps-desc: "Mapa będzie automatycznie rozwijana dla wpisów zawierających informacje o lokalizacji." show-maps-desc: "Mapa będzie automatycznie rozwijana dla wpisów zawierających informacje o lokalizacji."
sound: "Dźwięk" sound: "Dźwięk"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "Pop-out" popout: "Pop-out"
close: "Zamknij" close: "Zamknij"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Tylko wpisy z zawartością multimedialną" is-media-only: "Tylko wpisy z zawartością multimedialną"
is-media-view: "Widok multimediów" is-media-view: "Widok multimediów"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "Oś czasu" timeline: "Oś czasu"
show-reply-target: "Pokazuj cel odpowiedzi" show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia" show-my-renotes: "Pokazuj moje udostępnienia"
show-renoted-my-notes: "Pokazuj udostępnienia moich wpisów" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "Styl wpisów" post-style: "Styl wpisów"
post-style-standard: "Standardowy" post-style-standard: "Standardowy"
post-style-smart: "Inteligentny" post-style-smart: "Inteligentny"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -84,7 +84,7 @@ common:
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
verified-user: "認証済みのユーザー" verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
reversi: reversi:
drawn: "引き分け" drawn: "引き分け"
@ -287,6 +287,7 @@ common/views/components/signin.vue:
signin: "サインイン" signin: "サインイン"
or: "または" or: "または"
signin-with-twitter: "Twitterでログイン" signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue: common/views/components/signup.vue:
username: "ユーザー名" username: "ユーザー名"
checking: "確認しています..." checking: "確認しています..."
@ -625,9 +626,11 @@ desktop/views/components/settings.vue:
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開" show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド" sound: "サウンド"
@ -784,6 +787,25 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue: desktop/views/components/window.vue:
popout: "ポップアウト" popout: "ポップアウト"
close: "閉じる" close: "閉じる"
desktop/views/pages/admin/admin.vue:
dashboard: "ダッシュボード"
drive: "ドライブ"
users: "ユーザー"
update: "更新"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全てのノート"
original-notes: "このインスタンスのノート"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/deck/deck.tl-column.vue: desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ" is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー" is-media-view: "メディアビュー"
@ -1087,7 +1109,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン" timeline: "タイムライン"
show-reply-target: "リプライ先を表示する" show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する" show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル" post-style: "投稿の表示スタイル"
post-style-standard: "標準" post-style-standard: "標準"
post-style-smart: "スマート" post-style-smart: "スマート"

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "5.23.0", "version": "6.3.0",
"clientVersion": "1.0.8226", "clientVersion": "1.0.8483",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -31,6 +31,7 @@
"@types/dateformat": "1.0.1", "@types/dateformat": "1.0.1",
"@types/debug": "0.0.30", "@types/debug": "0.0.30",
"@types/deep-equal": "1.0.1", "@types/deep-equal": "1.0.1",
"@types/double-ended-queue": "2.1.0",
"@types/elasticsearch": "5.0.25", "@types/elasticsearch": "5.0.25",
"@types/file-type": "5.2.1", "@types/file-type": "5.2.1",
"@types/gulp": "3.8.36", "@types/gulp": "3.8.36",
@ -57,9 +58,9 @@
"@types/minio": "6.0.2", "@types/minio": "6.0.2",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/mocha": "5.2.3", "@types/mocha": "5.2.3",
"@types/mongodb": "3.1.3", "@types/mongodb": "3.1.4",
"@types/ms": "0.7.30", "@types/ms": "0.7.30",
"@types/node": "10.5.8", "@types/node": "10.7.1",
"@types/portscanner": "2.1.0", "@types/portscanner": "2.1.0",
"@types/pug": "2.0.4", "@types/pug": "2.0.4",
"@types/qrcode": "1.2.0", "@types/qrcode": "1.2.0",
@ -76,10 +77,10 @@
"@types/systeminformation": "3.23.0", "@types/systeminformation": "3.23.0",
"@types/tmp": "0.0.33", "@types/tmp": "0.0.33",
"@types/uuid": "3.4.3", "@types/uuid": "3.4.3",
"@types/webpack": "4.4.9", "@types/webpack": "4.4.10",
"@types/webpack-stream": "3.2.10", "@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.39", "@types/websocket": "0.0.39",
"@types/ws": "5.1.2", "@types/ws": "6.0.0",
"animejs": "2.2.0", "animejs": "2.2.0",
"autosize": "4.0.2", "autosize": "4.0.2",
"autwh": "0.1.0", "autwh": "0.1.0",
@ -97,6 +98,7 @@
"deepcopy": "0.6.3", "deepcopy": "0.6.3",
"diskusage": "0.2.4", "diskusage": "0.2.4",
"dompurify": "1.0.5", "dompurify": "1.0.5",
"double-ended-queue": "2.1.0-0",
"elasticsearch": "15.1.1", "elasticsearch": "15.1.1",
"element-ui": "2.4.6", "element-ui": "2.4.6",
"emojilib": "2.3.0", "emojilib": "2.3.0",
@ -147,7 +149,7 @@
"loader-utils": "1.1.0", "loader-utils": "1.1.0",
"lodash.assign": "4.2.0", "lodash.assign": "4.2.0",
"mecab-async": "0.1.2", "mecab-async": "0.1.2",
"minio": "6.0.0", "minio": "7.0.0",
"mkdirp": "0.5.1", "mkdirp": "0.5.1",
"mocha": "5.2.0", "mocha": "5.2.0",
"moji": "0.5.1", "moji": "0.5.1",
@ -161,7 +163,7 @@
"object-assign-deep": "0.4.0", "object-assign-deep": "0.4.0",
"on-build-webpack": "0.1.0", "on-build-webpack": "0.1.0",
"os-utils": "0.0.14", "os-utils": "0.0.14",
"parse5": "5.0.0", "parse5": "5.1.0",
"portscanner": "2.2.0", "portscanner": "2.2.0",
"progress-bar-webpack-plugin": "1.11.0", "progress-bar-webpack-plugin": "1.11.0",
"promise-sequential": "1.1.1", "promise-sequential": "1.1.1",
@ -178,7 +180,7 @@
"rndstr": "1.0.0", "rndstr": "1.0.0",
"s-age": "1.1.2", "s-age": "1.1.2",
"sass-loader": "7.1.0", "sass-loader": "7.1.0",
"seedrandom": "2.4.3", "seedrandom": "2.4.4",
"sharp": "0.20.5", "sharp": "0.20.5",
"showdown": "1.8.6", "showdown": "1.8.6",
"showdown-highlightjs-extension": "0.1.2", "showdown-highlightjs-extension": "0.1.2",
@ -188,7 +190,7 @@
"style-loader": "0.22.1", "style-loader": "0.22.1",
"stylus": "0.54.5", "stylus": "0.54.5",
"stylus-loader": "3.0.2", "stylus-loader": "3.0.2",
"summaly": "2.1.2", "summaly": "2.1.3",
"systeminformation": "3.42.9", "systeminformation": "3.42.9",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
@ -199,7 +201,7 @@
"typescript": "2.9.2", "typescript": "2.9.2",
"typescript-eslint-parser": "18.0.0", "typescript-eslint-parser": "18.0.0",
"uglify-es": "3.3.9", "uglify-es": "3.3.9",
"url-loader": "1.0.1", "url-loader": "1.1.0",
"uuid": "3.3.2", "uuid": "3.3.2",
"v-animate-css": "0.0.2", "v-animate-css": "0.0.2",
"vue": "2.5.17", "vue": "2.5.17",
@ -208,7 +210,7 @@
"vue-json-tree-view": "2.1.4", "vue-json-tree-view": "2.1.4",
"vue-loader": "15.3.0", "vue-loader": "15.3.0",
"vue-router": "3.0.1", "vue-router": "3.0.1",
"vue-style-loader": "4.1.1", "vue-style-loader": "4.1.2",
"vue-template-compiler": "2.5.17", "vue-template-compiler": "2.5.17",
"vuedraggable": "2.16.0", "vuedraggable": "2.16.0",
"vuex": "3.0.1", "vuex": "3.0.1",

View File

@ -1,5 +1,9 @@
export default () => [ const kaos = [
'(=^・・^=)', '(=^・・^=)',
'v(\'ω\')v', 'v(\'ω\')v',
'🐡( \'-\' 🐡 )フグパンチ!!!!' '🐡( \'-\' 🐡 )フグパンチ!!!!',
][Math.floor(Math.random() * 3)]; '🖕(´・_・`)🖕',
'(。><。)'
];
export default () => kaos[Math.floor(Math.random() * kaos.length)];

View File

@ -1,8 +1,16 @@
<template> <template>
<span class="mk-avatar" :title="user | acct" :style="style" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick"></span> <span class="mk-avatar" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick">
<span class="mk-avatar" :title="user | acct" :style="style" v-else-if="disableLink && disablePreview" @click="onClick"></span> <span class="inner" :style="style"></span>
<router-link class="mk-avatar" :to="user | userPage" :title="user | acct" :target="target" :style="style" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id"></router-link> </span>
<router-link class="mk-avatar" :to="user | userPage" :title="user | acct" :target="target" :style="style" v-else-if="!disableLink && disablePreview"></router-link> <span class="mk-avatar" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick">
<span class="inner" :style="style"></span>
</span>
<router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id">
<span class="inner" :style="style"></span>
</router-link>
<router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview">
<span class="inner" :style="style"></span>
</router-link>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -30,14 +38,17 @@ export default Vue.extend({
lightmode(): boolean { lightmode(): boolean {
return this.$store.state.device.lightmode; return this.$store.state.device.lightmode;
}, },
cat(): boolean {
return this.user.isCat && this.$store.state.settings.circleIcons;
},
style(): any { style(): any {
return { return {
backgroundColor: this.lightmode backgroundColor: this.lightmode
? `rgb(${ this.user.avatarColor.slice(0, 3).join(',') })` ? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`
: this.user.avatarColor && this.user.avatarColor.length == 3 : this.user.avatarColor && this.user.avatarColor.length == 3
? `rgb(${ this.user.avatarColor.join(',') })` ? `rgb(${this.user.avatarColor.join(',')})`
: null, : null,
backgroundImage: this.lightmode ? null : `url(${ this.user.avatarUrl })`, backgroundImage: this.lightmode ? null : `url(${this.user.avatarUrl})`,
borderRadius: this.$store.state.settings.circleIcons ? '100%' : null borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
}; };
} }
@ -51,10 +62,47 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.mk-avatar
root(isDark)
display inline-block display inline-block
vertical-align bottom vertical-align bottom
background-size cover
background-position center center &:not(.cat)
transition border-radius 1s ease overflow hidden
border-radius 8px
&.cat::before,
&.cat::after
background #df548f
border solid 4px isDark ? #e0eefd : #202224
box-sizing border-box
content ''
display inline-block
height 50%
width 50%
&.cat::before
border-radius 0 75% 75%
transform rotate(37.5deg) skew(30deg)
&.cat::after
border-radius 75% 0 75% 75%
transform rotate(-37.5deg) skew(-30deg)
.inner
background-position center center
background-size cover
bottom 0
left 0
position absolute
right 0
top 0
transition border-radius 1s ease
z-index 1
.mk-avatar[data-darkmode]
root(true)
.mk-avatar:not([data-darkmode])
root(false)
</style> </style>

View File

@ -2,7 +2,7 @@
<header class="bvonvjxbwzaiskogyhbwgyxvcgserpmu"> <header class="bvonvjxbwzaiskogyhbwgyxvcgserpmu">
<mk-avatar class="avatar" :user="note.user" v-if="$store.state.device.postStyle == 'smart'"/> <mk-avatar class="avatar" :user="note.user" v-if="$store.state.device.postStyle == 'smart'"/>
<router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link> <router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
<span class="is-verified" v-if="note.user.isVerified" title="%i18n:common.verified-user%">%fa:bookmark%</span> <span class="is-verified" v-if="note.user.isVerified" title="%i18n:common.verified-user%">%fa:star%</span>
<span class="is-admin" v-if="note.user.isAdmin">admin</span> <span class="is-admin" v-if="note.user.isAdmin">admin</span>
<span class="is-bot" v-if="note.user.isBot">bot</span> <span class="is-bot" v-if="note.user.isBot">bot</span>
<span class="is-cat" v-if="note.user.isCat">cat</span> <span class="is-cat" v-if="note.user.isCat">cat</span>

View File

@ -1,16 +1,16 @@
<template> <template>
<div class="mk-reactions-viewer"> <div class="mk-reactions-viewer">
<template v-if="reactions"> <template v-if="reactions">
<span v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span> <span :class="{notReacted}" @click="react('like')" v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span>
<span v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span> <span :class="{notReacted}" @click="react('love')" v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span>
<span v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span> <span :class="{notReacted}" @click="react('laugh')" v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span>
<span v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span> <span :class="{notReacted}" @click="react('hmm')" v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span>
<span v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span> <span :class="{notReacted}" @click="react('surprise')" v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span>
<span v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span> <span :class="{notReacted}" @click="react('congrats')" v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span>
<span v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span> <span :class="{notReacted}" @click="react('angry')" v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span>
<span v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span> <span :class="{notReacted}" @click="react('confused')" v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span>
<span v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span> <span :class="{notReacted}" @click="react('rip')" v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span>
<span v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span> <span :class="{notReacted}" @click="react('pudding')" v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span>
</template> </template>
</div> </div>
</template> </template>
@ -22,6 +22,17 @@ export default Vue.extend({
computed: { computed: {
reactions(): number { reactions(): number {
return this.note.reactionCounts; return this.note.reactionCounts;
},
notReacted(): boolean {
return this.note.myReaction == null;
}
},
methods: {
react(reaction: string) {
(this as any).api('notes/reactions/create', {
noteId: this.note.id,
reaction: reaction
});
} }
} }
}); });
@ -40,6 +51,9 @@ root(isDark)
> span > span
margin-right 8px margin-right 8px
&.notReacted
cursor pointer
> .mk-reaction-icon > .mk-reaction-icon
font-size 1.4em font-size 1.4em

View File

@ -12,7 +12,7 @@
</ui-input> </ui-input>
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/> <ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/>
<ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button> <ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button>
<p style="margin: 8px 0;" v-if="twitterIntegration">%i18n:@or%<a :href="`${apiUrl}/signin/twitter`">%i18n:@signin-with-twitter%</a></p> <p style="margin: 8px 0;" v-if="twitterIntegration">%i18n:@or% <a :href="`${apiUrl}/signin/twitter`">%i18n:@signin-with-twitter%</a></p>
</form> </form>
</template> </template>
@ -60,7 +60,7 @@ export default Vue.extend({
}).then(() => { }).then(() => {
location.reload(); location.reload();
}).catch(() => { }).catch(() => {
alert('something happened'); alert('%i18n:@login-failed%');
this.signing = false; this.signing = false;
}); });
} }

View File

@ -1,5 +1,10 @@
<template> <template>
<form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()"> <form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()">
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<span>%i18n:@invitation-code%</span>
<span slot="prefix">%fa:id-card-alt%</span>
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
</ui-input>
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername"> <ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername">
<span>%i18n:@username%</span> <span>%i18n:@username%</span>
<span slot="prefix">@</span> <span slot="prefix">@</span>
@ -46,11 +51,13 @@ export default Vue.extend({
username: '', username: '',
password: '', password: '',
retypedPassword: '', retypedPassword: '',
invitationCode: '',
url, url,
recaptchaSitekey, recaptchaSitekey,
usernameState: null, usernameState: null,
passwordStrength: '', passwordStrength: '',
passwordRetypeState: null passwordRetypeState: null,
meta: null
} }
}, },
computed: { computed: {
@ -61,6 +68,11 @@ export default Vue.extend({
this.usernameState != 'max-range'); this.usernameState != 'max-range');
} }
}, },
created() {
(this as any).os.getMeta().then(meta => {
this.meta = meta;
});
},
methods: { methods: {
onChangeUsername() { onChangeUsername() {
if (this.username == '') { if (this.username == '') {
@ -110,6 +122,7 @@ export default Vue.extend({
(this as any).api('signup', { (this as any).api('signup', {
username: this.username, username: this.username,
password: this.password, password: this.password,
invitationCode: this.invitationCode,
'g-recaptcha-response': recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null 'g-recaptcha-response': recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null
}).then(() => { }).then(() => {
(this as any).api('signin', { (this as any).api('signin', {

View File

@ -129,6 +129,7 @@ export default Vue.extend({
'newretrowave.com', 'newretrowave.com',
'nhk.or.jp', 'nhk.or.jp',
'nicovideo.jp', 'nicovideo.jp',
'nico.ms',
'noisetrade.com', 'noisetrade.com',
'nood.tv', 'nood.tv',
'npr.org', 'npr.org',
@ -144,6 +145,7 @@ export default Vue.extend({
'songkick.com', 'songkick.com',
'soundcloud.com', 'soundcloud.com',
'spinninrecords.com', 'spinninrecords.com',
'spotify.com',
'stitcher.com', 'stitcher.com',
'stream.me', 'stream.me',
'switchboard.live', 'switchboard.live',
@ -158,12 +160,12 @@ export default Vue.extend({
'web.tv', 'web.tv',
'youtube.com', 'youtube.com',
'youtu.be' 'youtu.be'
].some(x => x == url.hostname || url.hostname.endsWith(`.${x}`)))) ].some(x => x == url.hostname || url.hostname.endsWith(`.${x}`)))
this.player = info.player; this.player = info.player;
} } // info.url
}); }) // json
} }); // fetch
} } // created
}); });
</script> </script>

View File

@ -44,7 +44,12 @@ import Vue from 'vue';
import * as anime from 'animejs'; import * as anime from 'animejs';
export default Vue.extend({ export default Vue.extend({
props: ['source', 'compact', 'v'], props: ['source', 'compact'],
data() {
return {
v: this.$store.state.device.visibility || 'public'
}
},
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
const popover = this.$refs.popover as any; const popover = this.$refs.popover as any;
@ -92,6 +97,7 @@ export default Vue.extend({
}, },
methods: { methods: {
choose(visibility) { choose(visibility) {
this.$store.commit('device/setVisibility', visibility);
this.$emit('chosen', visibility); this.$emit('chosen', visibility);
this.$destroy(); this.$destroy();
}, },

View File

@ -24,6 +24,7 @@ import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue'; import MkIndex from './views/pages/index.vue';
import MkDeck from './views/pages/deck/deck.vue'; import MkDeck from './views/pages/deck/deck.vue';
import MkAdmin from './views/pages/admin/admin.vue';
import MkUser from './views/pages/user/user.vue'; import MkUser from './views/pages/user/user.vue';
import MkFavorites from './views/pages/favorites.vue'; import MkFavorites from './views/pages/favorites.vue';
import MkSelectDrive from './views/pages/selectdrive.vue'; import MkSelectDrive from './views/pages/selectdrive.vue';
@ -55,6 +56,7 @@ init(async (launch) => {
routes: [ routes: [
{ path: '/', name: 'index', component: MkIndex }, { path: '/', name: 'index', component: MkIndex },
{ path: '/deck', name: 'deck', component: MkDeck }, { path: '/deck', name: 'deck', component: MkDeck },
{ path: '/admin', name: 'admin', component: MkAdmin },
{ path: '/i/customize-home', component: MkHomeCustomize }, { path: '/i/customize-home', component: MkHomeCustomize },
{ path: '/i/favorites', component: MkFavorites }, { path: '/i/favorites', component: MkFavorites },
{ path: '/i/messaging/:user', component: MkMessagingRoom }, { path: '/i/messaging/:user', component: MkMessagingRoom },

View File

@ -16,7 +16,7 @@
<p>%i18n:@banner%</p> <p>%i18n:@banner%</p>
</div> </div>
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`"> <div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
<img :src="file.url" alt="" @load="onThumbnailLoaded"/> <img :src="file.thumbnailUrl" alt="" @load="onThumbnailLoaded"/>
</div> </div>
<p class="name"> <p class="name">
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span> <span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>

View File

@ -37,7 +37,7 @@ export default Vue.extend({
style(): any { style(): any {
return { return {
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent', 'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url})` 'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.thumbnailUrl})`
}; };
} }
}, },

View File

@ -55,15 +55,15 @@
</div> </div>
<footer> <footer>
<mk-reactions-viewer :note="p"/> <mk-reactions-viewer :note="p"/>
<button @click="reply" title=""> <button class="replyButton" @click="reply" title="">
<template v-if="p.reply">%fa:reply-all%</template> <template v-if="p.reply">%fa:reply-all%</template>
<template v-else>%fa:reply%</template> <template v-else>%fa:reply%</template>
<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p> <p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button> </button>
<button @click="renote" title="%i18n:@renote%"> <button class="renoteButton" @click="renote" title="%i18n:@renote%">
%fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p> %fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p>
</button> </button>
<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%"> <button class="reactionButton" :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p> %fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
</button> </button>
<button @click="menu" ref="menuButton"> <button @click="menu" ref="menuButton">
@ -372,15 +372,24 @@ root(isDark)
cursor pointer cursor pointer
&:hover &:hover
color isDark ? #9198af : #666 color isDark ? #a1a8bf : #444
&.replyButton:hover
color #0af
&.renoteButton:hover
color #8d0
&.reactionButton:hover
color #fa0
> .count > .count
display inline display inline
margin 0 0 0 8px margin 0 0 0 8px
color #999 color #999
&.reacted &.reacted, &.reacted:hover
color $theme-color color #fa0
> .replies > .replies
> * > *

View File

@ -42,15 +42,15 @@
</div> </div>
<footer> <footer>
<mk-reactions-viewer :note="p" ref="reactionsViewer"/> <mk-reactions-viewer :note="p" ref="reactionsViewer"/>
<button @click="reply" title="%i18n:@reply%"> <button class="replyButton" @click="reply" title="%i18n:@reply%">
<template v-if="p.reply">%fa:reply-all%</template> <template v-if="p.reply">%fa:reply-all%</template>
<template v-else>%fa:reply%</template> <template v-else>%fa:reply%</template>
<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p> <p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button> </button>
<button @click="renote" title="%i18n:@renote%"> <button class="renoteButton" @click="renote" title="%i18n:@renote%">
%fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p> %fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p>
</button> </button>
<button :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%"> <button class="reactionButton" :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p> %fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
</button> </button>
<button @click="menu" ref="menuButton"> <button @click="menu" ref="menuButton">
@ -487,20 +487,24 @@ root(isDark)
cursor pointer cursor pointer
&:hover &:hover
color isDark ? #9198af : #666 color isDark ? #a1a8bf : #444
&.replyButton:hover
color #0af
&.renoteButton:hover
color #8d0
&.reactionButton:hover
color #fa0
> .count > .count
display inline display inline
margin 0 0 0 8px margin 0 0 0 8px
color #999 color #999
&.reacted &.reacted, &.reacted:hover
color $theme-color color #fa0
&:last-child
position absolute
right 0
margin 0
> .detail > .detail
padding-top 4px padding-top 4px

View File

@ -135,6 +135,12 @@ export default Vue.extend({
return; return;
} }
} }
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion //#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知 // 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知

View File

@ -10,7 +10,7 @@
<span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span> <span v-for="u in visibleUsers">{{ u | userName }}<a @click="removeVisibleUser(u)">[x]</a></span>
<a @click="addVisibleUser">%i18n:@add-visible-user%</a> <a @click="addVisibleUser">%i18n:@add-visible-user%</a>
</div> </div>
<div class="hashtags" v-if="recentHashtags.length > 0"> <div class="hashtags" v-if="recentHashtags.length > 0 && $store.state.settings.suggestRecentHashtags">
<b>%i18n:@recent-tags%:</b> <b>%i18n:@recent-tags%:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" title="%@click-to-tagging%">#{{ tag }}</a> <a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" title="%@click-to-tagging%">#{{ tag }}</a>
</div> </div>
@ -23,7 +23,7 @@
<div class="medias" :class="{ with: poll }" v-show="files.length != 0"> <div class="medias" :class="{ with: poll }" v-show="files.length != 0">
<x-draggable :list="files" :options="{ animation: 150 }"> <x-draggable :list="files" :options="{ animation: 150 }">
<div v-for="file in files" :key="file.id"> <div v-for="file in files" :key="file.id">
<div class="img" :style="{ backgroundImage: `url(${file.url})` }" :title="file.name"></div> <div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div>
<img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/> <img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/>
</div> </div>
</x-draggable> </x-draggable>
@ -99,7 +99,7 @@ export default Vue.extend({
useCw: false, useCw: false,
cw: null, cw: null,
geo: null, geo: null,
visibility: 'public', visibility: this.$store.state.device.visibility || 'public',
visibleUsers: [], visibleUsers: [],
autocomplete: null, autocomplete: null,
draghover: false, draghover: false,
@ -326,8 +326,7 @@ export default Vue.extend({
setVisibility() { setVisibility() {
const w = (this as any).os.new(MkVisibilityChooser, { const w = (this as any).os.new(MkVisibilityChooser, {
source: this.$refs.visibilityButton, source: this.$refs.visibilityButton
v: this.visibility
}); });
w.$once('chosen', v => { w.$once('chosen', v => {
this.visibility = v; this.visibility = v;

View File

@ -48,9 +48,11 @@
<mk-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi" text="%i18n:common.i-like-sushi%"/> <mk-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi" text="%i18n:common.i-like-sushi%"/>
</div> </div>
<mk-switch v-model="$store.state.settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="%i18n:@post-form-on-timeline%"/> <mk-switch v-model="$store.state.settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="%i18n:@post-form-on-timeline%"/>
<mk-switch v-model="$store.state.settings.suggestRecentHashtags" @change="onChangeSuggestRecentHashtags" text="%i18n:@suggest-recent-hashtags%"/>
<mk-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget" text="%i18n:@show-reply-target%"/> <mk-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget" text="%i18n:@show-reply-target%"/>
<mk-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes" text="%i18n:@show-my-renotes%"/> <mk-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes" text="%i18n:@show-my-renotes%"/>
<mk-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="%i18n:@show-renoted-my-notes%"/> <mk-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="%i18n:@show-renoted-my-notes%"/>
<mk-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes" text="%i18n:@show-local-renotes%"/>
<mk-switch v-model="$store.state.settings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%"> <mk-switch v-model="$store.state.settings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%">
<span>%i18n:@show-maps-desc%</span> <span>%i18n:@show-maps-desc%</span>
</mk-switch> </mk-switch>
@ -335,6 +337,12 @@ export default Vue.extend({
value: v value: v
}); });
}, },
onChangeSuggestRecentHashtags(v) {
this.$store.dispatch('settings/set', {
key: 'suggestRecentHashtags',
value: v
});
},
onChangeShowReplyTarget(v) { onChangeShowReplyTarget(v) {
this.$store.dispatch('settings/set', { this.$store.dispatch('settings/set', {
key: 'showReplyTarget', key: 'showReplyTarget',
@ -353,6 +361,12 @@ export default Vue.extend({
value: v value: v
}); });
}, },
onChangeShowLocalRenotes(v) {
this.$store.dispatch('settings/set', {
key: 'showLocalRenotes',
value: v
});
},
onChangeShowMaps(v) { onChangeShowMaps(v) {
this.$store.dispatch('settings/set', { this.$store.dispatch('settings/set', {
key: 'showMaps', key: 'showMaps',

View File

@ -100,7 +100,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined, untilDate: this.date ? this.date.getTime() : undefined,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -122,7 +123,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -159,6 +159,9 @@ root(isDark)
position absolute position absolute
height 48px height 48px
> .center
right 0
> .icon > .icon
margin auto margin auto
display block display block
@ -175,8 +178,7 @@ root(isDark)
> .center > .center
left 0 left 0
> .right, > .right
> .center
right 0 right 0
> * > *

View File

@ -47,7 +47,8 @@ export default Vue.extend({
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -67,7 +68,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -10,13 +10,13 @@
<div class="description">{{ u.description }}</div> <div class="description">{{ u.description }}</div>
<div class="status"> <div class="status">
<div> <div>
<p>%i18n:@notes%</p><a>{{ u.notesCount }}</a> <p>%i18n:@notes%</p><span>{{ u.notesCount }}</span>
</div> </div>
<div> <div>
<p>%i18n:@following%</p><a>{{ u.followingCount }}</a> <p>%i18n:@following%</p><span>{{ u.followingCount }}</span>
</div> </div>
<div> <div>
<p>%i18n:@followers%</p><a>{{ u.followersCount }}</a> <p>%i18n:@followers%</p><span>{{ u.followersCount }}</span>
</div> </div>
</div> </div>
<mk-follow-button v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u"/> <mk-follow-button v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u"/>
@ -149,7 +149,7 @@ root(isDark)
font-size 0.7em font-size 0.7em
color #aaa color #aaa
> a > span
font-size 1em font-size 1em
color $theme-color color $theme-color

View File

@ -0,0 +1,49 @@
<template>
<div>
<h1>%i18n:@dashboard%</h1>
<div v-if="stats">
<p><b>%i18n:@all-users%</b>: <span>{{ stats.usersCount | number }}</span></p>
<p><b>%i18n:@original-users%</b>: <span>{{ stats.originalUsersCount | number }}</span></p>
<p><b>%i18n:@all-notes%</b>: <span>{{ stats.notesCount | number }}</span></p>
<p><b>%i18n:@original-notes%</b>: <span>{{ stats.originalNotesCount | number }}</span></p>
</div>
<div>
<button class="ui" @click="invite">%i18n:@invite%</button>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
stats: null,
inviteCode: null
};
},
created() {
(this as any).api('stats').then(stats => {
this.stats = stats;
});
},
methods: {
invite() {
(this as any).api('admin/invite').then(x => {
this.inviteCode = x.code;
});
}
}
});
</script>
<style lang="stylus" scoped>
h1
margin 0 0 1em 0
padding 0 0 8px 0
font-size 1em
color #555
border-bottom solid 1px #eee
</style>

View File

@ -0,0 +1,51 @@
<template>
<div>
<header>%i18n:@suspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="suspendUser" :disabled="suspending">%i18n:@suspend%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import parseAcct from "../../../../../../misc/acct/parse";
export default Vue.extend({
data() {
return {
username: null,
suspending: false
};
},
methods: {
async suspendUser() {
this.suspending = true;
const user = await (this as any).os.api(
"users/show",
parseAcct(this.username)
);
await (this as any).os.api("admin/suspend-user", {
userId: user.id
});
this.suspending = false;
(this as any).os.apis.dialog({ text: "%i18n:@suspended%" });
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
header
margin 10px 0
button
margin 16px 0
</style>

View File

@ -0,0 +1,51 @@
<template>
<div>
<header>%i18n:@unsuspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import parseAcct from "../../../../../../misc/acct/parse";
export default Vue.extend({
data() {
return {
username: null,
unsuspending: false
};
},
methods: {
async unsuspendUser() {
this.unsuspending = true;
const user = await (this as any).os.api(
"users/show",
parseAcct(this.username)
);
await (this as any).os.api("admin/unsuspend-user", {
userId: user.id
});
this.unsuspending = false;
(this as any).os.apis.dialog({ text: "%i18n:@unsuspended%" });
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
header
margin 10px 0
button
margin 16px 0
</style>

View File

@ -0,0 +1,102 @@
<template>
<div class="mk-admin">
<nav>
<ul>
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
</ul>
</nav>
<main>
<div v-if="page == 'dashboard'">
<x-dashboard/>
</div>
<div v-if="page == 'users'">
<x-suspend-user/>
<x-unsuspend-user/>
</div>
<div v-if="page == 'drive'"></div>
<div v-if="page == 'update'"></div>
</main>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XDashboard from "./admin.dashboard.vue";
import XSuspendUser from "./admin.suspend-user.vue";
import XUnsuspendUser from "./admin.unsuspend-user.vue";
export default Vue.extend({
components: {
XDashboard,
XSuspendUser,
XUnsuspendUser
},
data() {
return {
page: 'dashboard'
};
},
methods: {
nav(page: string) {
this.page = page;
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
.mk-admin
display flex
height 100%
margin 32px
> nav
flex 0 0 250px
width 100%
height 100%
padding 16px 0 0 0
overflow auto
border-right solid 1px #ddd
> ul
list-style none
> li
display block
padding 10px 16px
margin 0
color #666
cursor pointer
user-select none
transition margin-left 0.2s ease
> [data-fa]
margin-right 4px
&:hover
color #555
&.active
margin-left 8px
color $theme-color !important
> main
width 100%
padding 16px 32px
header
margin 10px 0
button
margin 16px 0
position absolute
right 0
</style>

View File

@ -70,7 +70,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
mediaOnly: this.mediaOnly, mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -91,7 +92,8 @@ export default Vue.extend({
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
mediaOnly: this.mediaOnly, mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -140,6 +140,12 @@ export default Vue.extend({
return; return;
} }
} }
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion //#endregion
if (this.isScrollTop()) { if (this.isScrollTop()) {

View File

@ -98,7 +98,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
mediaOnly: this.mediaOnly, mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -119,7 +120,8 @@ export default Vue.extend({
mediaOnly: this.mediaOnly, mediaOnly: this.mediaOnly,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -176,6 +176,10 @@ root(isDark)
height 120px height 120px
box-shadow 1px 1px 3px rgba(#000, 0.2) box-shadow 1px 1px 3px rgba(#000, 0.2)
> &.cat::before,
> &.cat::after
border-width 8px
> .body > .body
padding 16px 16px 16px 154px padding 16px 16px 16px 154px
color isDark ? #c5ced6 : #555 color isDark ? #c5ced6 : #555

View File

@ -43,7 +43,7 @@ export default Vue.extend({
thumbnail(): any { thumbnail(): any {
return { return {
'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent', 'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
'background-image': `url(${this.file.url})` 'background-image': `url(${this.file.thumbnailUrl})`
}; };
} }
}, },

View File

@ -27,7 +27,7 @@ export default Vue.extend({
}, },
computed: { computed: {
style(): any { style(): any {
let url = `url(${this.image.url})`; let url = `url(${this.image.thumbnailUrl})`;
if (this.$store.state.device.loadRemoteMedia || this.$store.state.device.lightmode) { if (this.$store.state.device.loadRemoteMedia || this.$store.state.device.lightmode) {
url = null; url = null;

View File

@ -139,6 +139,12 @@ export default Vue.extend({
return; return;
} }
} }
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion //#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知 // 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知

View File

@ -21,7 +21,7 @@
<div class="attaches" v-show="files.length != 0"> <div class="attaches" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }"> <x-draggable class="files" :list="files" :options="{ animation: 150 }">
<div class="file" v-for="file in files" :key="file.id"> <div class="file" v-for="file in files" :key="file.id">
<div class="img" :style="`background-image: url(${file.url})`" @click="detachMedia(file)"></div> <div class="img" :style="`background-image: url(${file.thumbnailUrl})`" @click="detachMedia(file)"></div>
</div> </div>
</x-draggable> </x-draggable>
</div> </div>
@ -45,7 +45,7 @@
<input ref="file" class="file" type="file" accept="image/*" multiple="multiple" @change="onChangeFile"/> <input ref="file" class="file" type="file" accept="image/*" multiple="multiple" @change="onChangeFile"/>
</div> </div>
</div> </div>
<div class="hashtags" v-if="recentHashtags.length > 0"> <div class="hashtags" v-if="recentHashtags.length > 0 && $store.state.settings.suggestRecentHashtags">
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)">#{{ tag }}</a> <a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)">#{{ tag }}</a>
</div> </div>
</div> </div>
@ -94,7 +94,7 @@ export default Vue.extend({
files: [], files: [],
poll: false, poll: false,
geo: null, geo: null,
visibility: 'public', visibility: this.$store.state.device.visibility || 'public',
visibleUsers: [], visibleUsers: [],
useCw: false, useCw: false,
cw: null, cw: null,
@ -240,8 +240,7 @@ export default Vue.extend({
setVisibility() { setVisibility() {
const w = (this as any).os.new(MkVisibilityChooser, { const w = (this as any).os.new(MkVisibilityChooser, {
source: this.$refs.visibilityButton, source: this.$refs.visibilityButton,
compact: true, compact: true
v: this.visibility
}); });
w.$once('chosen', v => { w.$once('chosen', v => {
this.visibility = v; this.visibility = v;

View File

@ -59,7 +59,8 @@ export default Vue.extend({
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -82,7 +83,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -95,7 +95,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined, untilDate: this.date ? this.date.getTime() : undefined,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => { }).then(notes => {
if (notes.length == fetchLimit + 1) { if (notes.length == fetchLimit + 1) {
notes.pop(); notes.pop();
@ -117,7 +118,8 @@ export default Vue.extend({
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes, includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}); });
promise.then(notes => { promise.then(notes => {

View File

@ -21,6 +21,7 @@
<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch> <ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch> <ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch> <ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
<ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
</div> </div>
<div> <div>
@ -221,6 +222,13 @@ export default Vue.extend({
}); });
}, },
onChangeShowLocalRenotes(v) {
this.$store.dispatch('settings/set', {
key: 'showLocalRenotes',
value: v
});
},
checkForUpdate() { checkForUpdate() {
this.checkingForUpdate = true; this.checkingForUpdate = true;
checkForUpdate((this as any).os, true, true).then(newer => { checkForUpdate((this as any).os, true, true).then(newer => {

View File

@ -61,7 +61,6 @@ export default Vue.extend({
birthday: null, birthday: null,
avatarId: null, avatarId: null,
bannerId: null, bannerId: null,
isBot: false,
isCat: false, isCat: false,
saving: false, saving: false,
avatarUploading: false, avatarUploading: false,
@ -77,7 +76,6 @@ export default Vue.extend({
this.birthday = this.$store.state.i.profile.birthday; this.birthday = this.$store.state.i.profile.birthday;
this.avatarId = this.$store.state.i.avatarId; this.avatarId = this.$store.state.i.avatarId;
this.bannerId = this.$store.state.i.bannerId; this.bannerId = this.$store.state.i.bannerId;
this.isBot = this.$store.state.i.isBot;
this.isCat = this.$store.state.i.isCat; this.isCat = this.$store.state.i.isCat;
}, },
@ -136,7 +134,6 @@ export default Vue.extend({
birthday: this.birthday || null, birthday: this.birthday || null,
avatarId: this.avatarId, avatarId: this.avatarId,
bannerId: this.bannerId, bannerId: this.bannerId,
isBot: this.isBot,
isCat: this.isCat isCat: this.isCat
}).then(i => { }).then(i => {
this.saving = false; this.saving = false;

View File

@ -11,11 +11,13 @@ const defaultSettings = {
fetchOnScroll: true, fetchOnScroll: true,
showMaps: true, showMaps: true,
showPostFormOnTopOfTl: false, showPostFormOnTopOfTl: false,
suggestRecentHashtags: true,
circleIcons: true, circleIcons: true,
gradientWindowHeader: false, gradientWindowHeader: false,
showReplyTarget: true, showReplyTarget: true,
showMyRenotes: true, showMyRenotes: true,
showRenotedMyNotes: true, showRenotedMyNotes: true,
showLocalRenotes: true,
loadRemoteMedia: true, loadRemoteMedia: true,
disableViaMobile: false, disableViaMobile: false,
memo: null, memo: null,
@ -108,6 +110,10 @@ export default (os: MiOS) => new Vuex.Store({
src: x.src, src: x.src,
arg: x.arg arg: x.arg
}; };
},
setVisibility(state, visibility) {
state.visibility = visibility;
} }
} }
}, },

View File

@ -1,5 +1,5 @@
{ {
"copyright": "Copyright (c) 2014-2018 syuilo", "copyright": "Copyright (c) 2014-2018 syuilo",
"themeColor": "#f66e4f", "themeColor": "#f6584f",
"themeColorForeground": "#fff" "themeColorForeground": "#fff"
} }

View File

@ -1,10 +1,11 @@
import * as childProcess from 'child_process'; import * as childProcess from 'child_process';
import * as Deque from 'double-ended-queue';
import Xev from 'xev'; import Xev from 'xev';
const ev = new Xev(); const ev = new Xev();
export default function() { export default function() {
const log: any[] = []; const log = new Deque<any>();
const p = childProcess.fork(__dirname + '/notes-stats-child.js'); const p = childProcess.fork(__dirname + '/notes-stats-child.js');
@ -15,7 +16,7 @@ export default function() {
}); });
ev.on('requestNotesStatsLog', id => { ev.on('requestNotesStatsLog', id => {
ev.emit('notesStatsLog:' + id, log); ev.emit('notesStatsLog:' + id, log.toArray());
}); });
process.on('exit', code => { process.on('exit', code => {

View File

@ -1,6 +1,7 @@
import * as os from 'os'; import * as os from 'os';
import * as sysUtils from 'systeminformation'; import * as sysUtils from 'systeminformation';
import * as diskusage from 'diskusage'; import * as diskusage from 'diskusage';
import * as Deque from 'double-ended-queue';
import Xev from 'xev'; import Xev from 'xev';
const osUtils = require('os-utils'); const osUtils = require('os-utils');
@ -12,10 +13,10 @@ const interval = 1000;
* Report server stats regularly * Report server stats regularly
*/ */
export default function() { export default function() {
const log: any[] = []; const log = new Deque<any>();
ev.on('requestServerStatsLog', id => { ev.on('requestServerStatsLog', id => {
ev.emit('serverStatsLog:' + id, log); ev.emit('serverStatsLog:' + id, log.toArray());
}); });
async function tick() { async function tick() {

View File

@ -28,7 +28,7 @@ import { Config } from './config/types';
const clusterLog = debug('misskey:cluster'); const clusterLog = debug('misskey:cluster');
const ev = new Xev(); const ev = new Xev();
if (process.env.NODE_ENV != 'production') { if (process.env.NODE_ENV != 'production' && process.env.DEBUG == null) {
debug.enable('misskey'); debug.enable('misskey');
} }
@ -48,7 +48,7 @@ main();
* Init process * Init process
*/ */
function main() { function main() {
process.title = `Misskey (${ cluster.isMaster ? 'master' : 'worker' })`; process.title = `Misskey (${cluster.isMaster ? 'master' : 'worker'})`;
if (cluster.isMaster || program.disableClustering) { if (cluster.isMaster || program.disableClustering) {
masterMain(); masterMain();
@ -112,7 +112,7 @@ async function workerMain() {
async function init(): Promise<Config> { async function init(): Promise<Config> {
Logger.info('Welcome to Misskey!'); Logger.info('Welcome to Misskey!');
(new Logger('Deps')).info(`Node.js ${process.version}`); new Logger('Deps').info(`Node.js ${process.version}`);
MachineInfo.show(); MachineInfo.show();
EnvironmentInfo.show(); EnvironmentInfo.show();
new DependencyInfo().showAll(); new DependencyInfo().showAll();
@ -154,11 +154,10 @@ async function init(): Promise<Config> {
function checkMongoDb(config: Config) { function checkMongoDb(config: Config) {
const mongoDBLogger = new Logger('MongoDB'); const mongoDBLogger = new Logger('MongoDB');
mongoDBLogger.info(`Host: ${config.mongodb.host}`); const u = config.mongodb.user ? encodeURIComponent(config.mongodb.user) : null;
mongoDBLogger.info(`Port: ${config.mongodb.port}`); const p = config.mongodb.pass ? encodeURIComponent(config.mongodb.pass) : null;
mongoDBLogger.info(`DB: ${config.mongodb.db}`); const uri = `mongodb://${u && p ? `${u}:****@` : ''}${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}`;
if (config.mongodb.user) mongoDBLogger.info(`User: ${config.mongodb.user}`); mongoDBLogger.info(`Connecting to ${uri}`);
if (config.mongodb.pass) mongoDBLogger.info(`Pass: ****`);
require('./db/mongodb'); require('./db/mongodb');
mongoDBLogger.succ('Connectivity confirmed'); mongoDBLogger.succ('Connectivity confirmed');
} }

View File

@ -15,6 +15,6 @@ export default function(text: string) {
return { return {
type: 'bold', type: 'bold',
content: bold, content: bold,
bold: bold.substr(2, bold.length - 4) bold: match[1]
} as TextElementBold; } as TextElementBold;
} }

View File

@ -18,7 +18,7 @@ export default function(text: string) {
return { return {
type: 'code', type: 'code',
content: code, content: code,
code: code.substr(3, code.length - 6).trim(), code: match[1],
html: genHtml(code.substr(3, code.length - 6).trim()) html: genHtml(match[1].trim())
} as TextElementCode; } as TextElementCode;
} }

View File

@ -9,12 +9,12 @@ export type TextElementEmoji = {
}; };
export default function(text: string) { export default function(text: string) {
const match = text.match(/^:[a-zA-Z0-9+-_]+:/); const match = text.match(/^:([a-zA-Z0-9+-_]+):/);
if (!match) return null; if (!match) return null;
const emoji = match[0]; const emoji = match[0];
return { return {
type: 'emoji', type: 'emoji',
content: emoji, content: emoji,
emoji: emoji.substr(1, emoji.length - 2) emoji: match[1]
} as TextElementEmoji; } as TextElementEmoji;
} }

View File

@ -14,11 +14,12 @@ export type TextElementInlineCode = {
export default function(text: string) { export default function(text: string) {
const match = text.match(/^`(.+?)`/); const match = text.match(/^`(.+?)`/);
if (!match) return null; if (!match) return null;
if (match[1].includes('´')) return null;
const code = match[0]; const code = match[0];
return { return {
type: 'inline-code', type: 'inline-code',
content: code, content: code,
code: code.substr(1, code.length - 2).trim(), code: match[1],
html: genHtml(code.substr(1, code.length - 2).trim()) html: genHtml(match[1])
} as TextElementInlineCode; } as TextElementInlineCode;
} }

View File

@ -15,6 +15,6 @@ export default function(text: string) {
return { return {
type: 'quote', type: 'quote',
content: quote, content: quote,
quote: quote.substr(1, quote.length - 2).trim(), quote: match[1].trim(),
} as TextElementQuote; } as TextElementQuote;
} }

View File

@ -9,7 +9,7 @@ export type TextElementSearch = {
}; };
export default function(text: string) { export default function(text: string) {
const match = text.match(/^(.+?) (検索|Search)(\n|$)/i); const match = text.match(/^(.+?)( | )(検索|\[検索\]|Search|\[Search\])(\n|$)/i);
if (!match) return null; if (!match) return null;
return { return {
type: 'search', type: 'search',

View File

@ -31,6 +31,7 @@ export type IMetadata = {
comment: string; comment: string;
uri?: string; uri?: string;
url?: string; url?: string;
thumbnailUrl?: string;
src?: string; src?: string;
deletedAt?: Date; deletedAt?: Date;
withoutChunks?: boolean; withoutChunks?: boolean;
@ -164,6 +165,7 @@ export const pack = (
_target = Object.assign(_target, _file.metadata); _target = Object.assign(_target, _file.metadata);
_target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`; _target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
_target.thumbnailUrl = _file.metadata.thumbnailUrl ? _file.metadata.thumbnailUrl : _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}?thumbnail`;
_target.isRemote = _file.metadata.isRemote; _target.isRemote = _file.metadata.isRemote;
if (_target.properties == null) _target.properties = {}; if (_target.properties == null) _target.properties = {};

View File

@ -11,4 +11,5 @@ export type IMeta = {
usersCount: number; usersCount: number;
originalUsersCount: number; originalUsersCount: number;
}; };
disableRegistration: boolean;
}; };

View File

@ -0,0 +1,12 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
const RegistrationTicket = db.get<IRegistrationTicket>('registrationTickets');
RegistrationTicket.createIndex('code', { unique: true });
export default RegistrationTicket;
export interface IRegistrationTicket {
_id: mongo.ObjectID;
createdAt: Date;
code: string;
}

View File

@ -40,11 +40,13 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
if (!note.to.includes('https://www.w3.org/ns/activitystreams#Public')) { if (!note.to.includes('https://www.w3.org/ns/activitystreams#Public')) {
if (note.cc.includes('https://www.w3.org/ns/activitystreams#Public')) { if (note.cc.includes('https://www.w3.org/ns/activitystreams#Public')) {
visibility = 'home'; visibility = 'home';
} else if (note.to.includes(`${actor.uri}/followers`)) { // TODO: person.followerと照合するべき
visibility = 'followers';
} else { } else {
visibility = 'specified'; visibility = 'specified';
visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri))); visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri)));
} }
} if (activity.cc.length == 0) visibility = 'followers'; }
//#endergion //#endergion
await post(actor, { await post(actor, {

View File

@ -1,4 +1,15 @@
export default (object: any) => ({ import config from '../../../config';
type: 'Announce', import { INote } from '../../../models/note';
object
}); export default (object: any, note: INote) => {
const attributedTo = `${config.url}/users/${note.userId}`;
return {
id: `${config.url}/notes/${note._id}`,
type: 'Announce',
published: note.createdAt.toISOString(),
to: ['https://www.w3.org/ns/activitystreams#Public'],
cc: [attributedTo, `${attributedTo}/followers`],
object
};
};

View File

@ -0,0 +1,16 @@
import config from '../../../config';
import * as mongo from 'mongodb';
import User, { isLocalUser } from '../../../models/user';
/**
* Convert (local|remote)(Follower|Followee)ID to URL
* @param id Follower|Followee ID
*/
export default async function renderFollowUser(id: mongo.ObjectID): Promise<any> {
const user = await User.findOne({
_id: id
});
return isLocalUser(user) ? `${config.url}/users/${user._id}` : user.uri;
}

View File

@ -50,9 +50,21 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
? note.mentionedRemoteUsers.map(x => x.uri) ? note.mentionedRemoteUsers.map(x => x.uri)
: []; : [];
const cc = ['public', 'home', 'followers'].includes(note.visibility) let to: string[] = [];
? [`${attributedTo}/followers`].concat(mentions) let cc: string[] = [];
: [];
if (note.visibility == 'public') {
to = ['https://www.w3.org/ns/activitystreams#Public'];
cc = [`${attributedTo}/followers`].concat(mentions);
} else if (note.visibility == 'home') {
to = [`${attributedTo}/followers`];
cc = ['https://www.w3.org/ns/activitystreams#Public'].concat(mentions);
} else if (note.visibility == 'followers') {
to = [`${attributedTo}/followers`];
cc = mentions;
} else {
to = mentions;
}
const mentionedUsers = note.mentions ? await User.find({ const mentionedUsers = note.mentions ? await User.find({
_id: { _id: {
@ -74,7 +86,7 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
summary: note.cw, summary: note.cw,
content: toHtml(note), content: toHtml(note),
published: note.createdAt.toISOString(), published: note.createdAt.toISOString(),
to: 'https://www.w3.org/ns/activitystreams#Public', to,
cc, cc,
inReplyTo, inReplyTo,
attachment: (await promisedFiles).map(renderDocument), attachment: (await promisedFiles).map(renderDocument),

View File

@ -0,0 +1,23 @@
/**
* Render OrderedCollectionPage
* @param id URL of self
* @param totalItems Number of total items
* @param orderedItems Items
* @param partOf URL of base
* @param prev URL of prev page (optional)
* @param next URL of next page (optional)
*/
export default function(id: string, totalItems: any, orderedItems: any, partOf: string, prev: string, next: string) {
const page = {
id,
partOf,
type: 'OrderedCollectionPage',
totalItems,
orderedItems
} as any;
if (prev) page.prev = prev;
if (next) page.next = next;
return page;
}

View File

@ -1,6 +1,19 @@
export default (id: string, totalItems: any, orderedItems: any) => ({ /**
id, * Render OrderedCollection
type: 'OrderedCollection', * @param id URL of self
totalItems, * @param totalItems Total number of items
orderedItems * @param first URL of first page (optional)
}); * @param last URL of last page (optional)
*/
export default function(id: string, totalItems: any, first: string, last: string) {
const page: any = {
id,
type: 'OrderedCollection',
totalItems,
};
if (first) page.first = first;
if (last) page.last = last;
return page;
}

View File

@ -19,6 +19,8 @@ export default async (user: ILocalUser) => {
id, id,
inbox: `${id}/inbox`, inbox: `${id}/inbox`,
outbox: `${id}/outbox`, outbox: `${id}/outbox`,
followers: `${id}/followers`,
following: `${id}/following`,
sharedInbox: `${config.url}/inbox`, sharedInbox: `${config.url}/inbox`,
url: `${config.url}/@${user.username}`, url: `${config.url}/@${user.username}`,
preferredUsername: user.username, preferredUsername: user.username,

View File

@ -10,8 +10,9 @@ import User, { isLocalUser, ILocalUser, IUser } from '../models/user';
import renderNote from '../remote/activitypub/renderer/note'; import renderNote from '../remote/activitypub/renderer/note';
import renderKey from '../remote/activitypub/renderer/key'; import renderKey from '../remote/activitypub/renderer/key';
import renderPerson from '../remote/activitypub/renderer/person'; import renderPerson from '../remote/activitypub/renderer/person';
import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection'; import Outbox from './activitypub/outbox';
import config from '../config'; import Followers from './activitypub/followers';
import Following from './activitypub/following';
// Init router // Init router
const router = new Router(); const router = new Router();
@ -64,30 +65,14 @@ router.get('/notes/:note', async (ctx, next) => {
ctx.body = pack(await renderNote(note)); ctx.body = pack(await renderNote(note));
}); });
// outbot // outbox
router.get('/users/:user/outbox', async ctx => { router.get('/users/:user/outbox', Outbox);
const userId = new mongo.ObjectID(ctx.params.user);
const user = await User.findOne({ // followers
_id: userId, router.get('/users/:user/followers', Followers);
host: null
});
if (user === null) { // following
ctx.status = 404; router.get('/users/:user/following', Following);
return;
}
const notes = await Note.find({ userId: user._id }, {
limit: 10,
sort: { _id: -1 }
});
const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes);
ctx.body = pack(rendered);
});
// publickey // publickey
router.get('/users/:user/publickey', async ctx => { router.get('/users/:user/publickey', async ctx => {

View File

@ -0,0 +1,80 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
import Following from '../../models/following';
import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
export default async (ctx: Koa.Context) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'cursor' parameter
const [cursor = null, cursorErr] = $.type(ID).optional.get(ctx.request.query.cursor);
// Get 'page' parameter
const pageErr = !$.str.optional.or(['true', 'false']).ok(ctx.request.query.page);
const page: boolean = ctx.request.query.page === 'true';
// Validate parameters
if (cursorErr || pageErr) {
ctx.status = 400;
return;
}
// Verify user
const user = await User.findOne({
_id: userId,
host: null
});
if (user === null) {
ctx.status = 404;
return;
}
const limit = 10;
const partOf = `${config.url}/users/${userId}/followers`;
if (page) {
// Construct query
const query = {
followeeId: user._id
} as any;
// カーソルが指定されている場合
if (cursor) {
query._id = {
$lt: cursor
};
}
// Get followers
const followings = await Following
.find(query, {
limit: limit + 1,
sort: { _id: -1 }
});
// 「次のページ」があるかどうか
const inStock = followings.length === limit + 1;
if (inStock) followings.pop();
const renderedFollowers = await Promise.all(followings.map(following => renderFollowUser(following.followerId)));
const rendered = renderOrderedCollectionPage(
`${partOf}?page=true${cursor ? `&cursor=${cursor}` : ''}`,
user.followersCount, renderedFollowers, partOf,
null,
inStock ? `${partOf}?page=true&cursor=${followings[followings.length - 1]._id}` : null
);
ctx.body = pack(rendered);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`, null);
ctx.body = pack(rendered);
}
};

View File

@ -0,0 +1,80 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
import Following from '../../models/following';
import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
export default async (ctx: Koa.Context) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'cursor' parameter
const [cursor = null, cursorErr] = $.type(ID).optional.get(ctx.request.query.cursor);
// Get 'page' parameter
const pageErr = !$.str.optional.or(['true', 'false']).ok(ctx.request.query.page);
const page: boolean = ctx.request.query.page === 'true';
// Validate parameters
if (cursorErr || pageErr) {
ctx.status = 400;
return;
}
// Verify user
const user = await User.findOne({
_id: userId,
host: null
});
if (user === null) {
ctx.status = 404;
return;
}
const limit = 10;
const partOf = `${config.url}/users/${userId}/following`;
if (page) {
// Construct query
const query = {
followerId: user._id
} as any;
// カーソルが指定されている場合
if (cursor) {
query._id = {
$lt: cursor
};
}
// Get followings
const followings = await Following
.find(query, {
limit: limit + 1,
sort: { _id: -1 }
});
// 「次のページ」があるかどうか
const inStock = followings.length === limit + 1;
if (inStock) followings.pop();
const renderedFollowees = await Promise.all(followings.map(following => renderFollowUser(following.followeeId)));
const rendered = renderOrderedCollectionPage(
`${partOf}?page=true${cursor ? `&cursor=${cursor}` : ''}`,
user.followingCount, renderedFollowees, partOf,
null,
inStock ? `${partOf}?page=true&cursor=${followings[followings.length - 1]._id}` : null
);
ctx.body = pack(rendered);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`, null);
ctx.body = pack(rendered);
}
};

View File

@ -0,0 +1,103 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import Note from '../../models/note';
import renderNote from '../../remote/activitypub/renderer/note';
export default async (ctx: Koa.Context) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'sinceId' parameter
const [sinceId, sinceIdErr] = $.type(ID).optional.get(ctx.request.query.since_id);
// Get 'untilId' parameter
const [untilId, untilIdErr] = $.type(ID).optional.get(ctx.request.query.until_id);
// Get 'page' parameter
const pageErr = !$.str.optional.or(['true', 'false']).ok(ctx.request.query.page);
const page: boolean = ctx.request.query.page === 'true';
// Validate parameters
if (sinceIdErr || untilIdErr || pageErr || [sinceId, untilId].filter(x => x != null).length > 1) {
ctx.status = 400;
return;
}
// Verify user
const user = await User.findOne({
_id: userId,
host: null
});
if (user === null) {
ctx.status = 404;
return;
}
const limit = 20;
const partOf = `${config.url}/users/${userId}/outbox`;
if (page) {
//#region Construct query
const sort = {
_id: -1
};
const query = {
userId: user._id,
$and: [{
$or: [ { visibility: 'public' }, { visibility: 'home' } ]
}, { // exclude renote, but include quote
$or: [{
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}]
}]
} as any;
if (sinceId) {
sort._id = 1;
query._id = {
$gt: sinceId
};
} else if (untilId) {
query._id = {
$lt: untilId
};
}
//#endregion
// Issue query
const notes = await Note
.find(query, {
limit: limit,
sort: sort
});
if (sinceId) notes.reverse();
const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
const rendered = renderOrderedCollectionPage(
`${partOf}?page=true${sinceId ? `&since_id=${sinceId}` : ''}${untilId ? `&until_id=${untilId}` : ''}`,
user.notesCount, renderedNotes, partOf,
notes.length > 0 ? `${partOf}?page=true&since_id=${notes[0]._id}` : null,
notes.length > 0 ? `${partOf}?page=true&until_id=${notes[notes.length - 1]._id}` : null
);
ctx.body = pack(rendered);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.notesCount,
`${partOf}?page=true`,
`${partOf}?page=true&since_id=000000000000000000000000`
);
ctx.body = pack(rendered);
}
};

View File

@ -1,6 +1,6 @@
import { performance } from 'perf_hooks'; import { performance } from 'perf_hooks';
import limitter from './limitter'; import limitter from './limitter';
import { IUser } from '../../models/user'; import { IUser, isLocalUser } from '../../models/user';
import { IApp } from '../../models/app'; import { IApp } from '../../models/app';
import endpoints from './endpoints'; import endpoints from './endpoints';
@ -21,6 +21,10 @@ export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any)
return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED'); return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED');
} }
if (ep.meta.requireAdmin && !(isLocalUser(user) && user.isAdmin)) {
return rej('YOU_ARE_NOT_ADMIN');
}
if (app && ep.meta.kind) { if (app && ep.meta.kind) {
if (!app.permission.some(p => p === ep.meta.kind)) { if (!app.permission.some(p => p === ep.meta.kind)) {
return rej('PERMISSION_DENIED'); return rej('PERMISSION_DENIED');
@ -53,7 +57,7 @@ export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any)
const time = after - before; const time = after - before;
if (time > 1000) { if (time > 1000) {
console.warn(`SLOW API CALL DETECTED: ${ep.name} (${ time }ms)`); console.warn(`SLOW API CALL DETECTED: ${ep.name} (${time}ms)`);
} }
} catch (e) { } catch (e) {
rej(e); rej(e);

View File

@ -14,6 +14,11 @@ export interface IEndpointMeta {
*/ */
requireCredential?: boolean; requireCredential?: boolean;
/**
* 管理者のみ使えるエンドポイントか否か
*/
requireAdmin?: boolean;
/** /**
* エンドポイントのリミテーションに関するやつ * エンドポイントのリミテーションに関するやつ
* 省略した場合はリミテーションは無いものとして解釈されます。 * 省略した場合はリミテーションは無いものとして解釈されます。

View File

@ -0,0 +1,26 @@
import rndstr from 'rndstr';
import RegistrationTicket from '../../../../models/registration-tickets';
export const meta = {
desc: {
ja: '招待コードを発行します。'
},
requireCredential: true,
requireAdmin: true,
params: {}
};
export default (params: any) => new Promise(async (res, rej) => {
const code = rndstr({ length: 5, chars: '0-9' });
await RegistrationTicket.insert({
createdAt: new Date(),
code: code
});
res({
code: code
});
});

View File

@ -0,0 +1,46 @@
import $ from 'cafy';
import ID from '../../../../misc/cafy-id';
import getParams from '../../get-params';
import User from '../../../../models/user';
export const meta = {
desc: {
ja: '指定したユーザーを凍結します。',
en: 'Suspend a user.'
},
requireCredential: true,
requireAdmin: true,
params: {
userId: $.type(ID).note({
desc: {
ja: '対象のユーザーID',
en: 'The user ID which you want to suspend'
}
}),
}
};
export default (params: any) => new Promise(async (res, rej) => {
const [ps, psErr] = getParams(meta, params);
if (psErr) return rej(psErr);
const user = await User.findOne({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
}
await User.findOneAndUpdate({
_id: user._id
}, {
$set: {
isSuspended: true
}
});
res();
});

View File

@ -0,0 +1,46 @@
import $ from 'cafy';
import ID from '../../../../misc/cafy-id';
import getParams from '../../get-params';
import User from '../../../../models/user';
export const meta = {
desc: {
ja: '指定したユーザーの凍結を解除します。',
en: 'Unsuspend a user.'
},
requireCredential: true,
requireAdmin: true,
params: {
userId: $.type(ID).note({
desc: {
ja: '対象のユーザーID',
en: 'The user ID which you want to unsuspend'
}
}),
}
};
export default (params: any) => new Promise(async (res, rej) => {
const [ps, psErr] = getParams(meta, params);
if (psErr) return rej(psErr);
const user = await User.findOne({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
}
await User.findOneAndUpdate({
_id: user._id
}, {
$set: {
isSuspended: false
}
});
res();
});

View File

@ -28,6 +28,7 @@ export default () => new Promise(async (res, rej) => {
model: os.cpus()[0].model, model: os.cpus()[0].model,
cores: os.cpus().length cores: os.cpus().length
}, },
broadcasts: meta.broadcasts broadcasts: meta.broadcasts,
disableRegistration: meta.disableRegistration
}); });
}); });

View File

@ -59,6 +59,13 @@ export const meta = {
} }
}), }),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({ mediaOnly: $.bool.optional.note({
desc: { desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します' ja: 'true にすると、メディアが添付された投稿だけ取得します'
@ -180,6 +187,22 @@ export default async (params: any, user: ILocalUser) => {
}); });
} }
if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) { if (ps.mediaOnly) {
query.$and.push({ query.$and.push({
mediaIds: { $exists: true, $ne: [] } mediaIds: { $exists: true, $ne: [] }

View File

@ -60,6 +60,13 @@ export const meta = {
} }
}), }),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({ mediaOnly: $.bool.optional.note({
desc: { desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します' ja: 'true にすると、メディアが添付された投稿だけ取得します'
@ -170,6 +177,22 @@ export default async (params: any, user: ILocalUser) => {
}); });
} }
if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) { if (ps.mediaOnly) {
query.$and.push({ query.$and.push({
mediaIds: { $exists: true, $ne: [] } mediaIds: { $exists: true, $ne: [] }

View File

@ -4,6 +4,7 @@ import Mute from '../../../../models/mute';
import { pack } from '../../../../models/note'; import { pack } from '../../../../models/note';
import UserList from '../../../../models/user-list'; import UserList from '../../../../models/user-list';
import { ILocalUser } from '../../../../models/user'; import { ILocalUser } from '../../../../models/user';
import getParams from '../../get-params';
export const meta = { export const meta = {
desc: { desc: {
@ -11,56 +12,84 @@ export const meta = {
en: 'Get timeline of a user list.' en: 'Get timeline of a user list.'
}, },
requireCredential: true requireCredential: true,
params: {
listId: $.type(ID).note({
desc: {
ja: 'リストのID'
}
}),
limit: $.num.optional.range(1, 100).note({
default: 10,
desc: {
ja: '最大数'
}
}),
sinceId: $.type(ID).optional.note({
desc: {
ja: '指定すると、この投稿を基点としてより新しい投稿を取得します'
}
}),
untilId: $.type(ID).optional.note({
desc: {
ja: '指定すると、この投稿を基点としてより古い投稿を取得します'
}
}),
sinceDate: $.num.optional.note({
desc: {
ja: '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
}
}),
untilDate: $.num.optional.note({
desc: {
ja: '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
}
}),
includeMyRenotes: $.bool.optional.note({
default: true,
desc: {
ja: '自分の行ったRenoteを含めるかどうか'
}
}),
includeRenotedMyNotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされた自分の投稿を含めるかどうか'
}
}),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({
desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します'
}
}),
}
}; };
export default async (params: any, user: ILocalUser) => { export default async (params: any, user: ILocalUser) => {
// Get 'limit' parameter const [ps, psErr] = getParams(meta, params);
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); if (psErr) throw psErr;
if (limitErr) throw 'invalid limit param';
// Get 'sinceId' parameter
const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
if (sinceIdErr) throw 'invalid sinceId param';
// Get 'untilId' parameter
const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
if (untilIdErr) throw 'invalid untilId param';
// Get 'sinceDate' parameter
const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
if (sinceDateErr) throw 'invalid sinceDate param';
// Get 'untilDate' parameter
const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
if (untilDateErr) throw 'invalid untilDate param';
// Check if only one of sinceId, untilId, sinceDate, untilDate specified
if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) {
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
}
// Get 'includeMyRenotes' parameter
const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
// Get 'includeRenotedMyNotes' parameter
const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
// Get 'mediaOnly' parameter
const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
if (mediaOnlyErr) throw 'invalid mediaOnly param';
// Get 'listId' parameter
const [listId, listIdErr] = $.type(ID).get(params.listId);
if (listIdErr) throw 'invalid listId param';
const [list, mutedUserIds] = await Promise.all([ const [list, mutedUserIds] = await Promise.all([
// リストを取得 // リストを取得
// Fetch the list // Fetch the list
UserList.findOne({ UserList.findOne({
_id: listId, _id: ps.listId,
userId: user._id userId: user._id
}), }),
@ -122,7 +151,7 @@ export default async (params: any, user: ILocalUser) => {
// つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。 // つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。
// for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws // for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws
if (includeMyRenotes === false) { if (ps.includeMyRenotes === false) {
query.$and.push({ query.$and.push({
$or: [{ $or: [{
userId: { $ne: user._id } userId: { $ne: user._id }
@ -138,7 +167,7 @@ export default async (params: any, user: ILocalUser) => {
}); });
} }
if (includeRenotedMyNotes === false) { if (ps.includeRenotedMyNotes === false) {
query.$and.push({ query.$and.push({
$or: [{ $or: [{
'_renote.userId': { $ne: user._id } '_renote.userId': { $ne: user._id }
@ -154,29 +183,45 @@ export default async (params: any, user: ILocalUser) => {
}); });
} }
if (mediaOnly) { if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) {
query.$and.push({ query.$and.push({
mediaIds: { $exists: true, $ne: [] } mediaIds: { $exists: true, $ne: [] }
}); });
} }
if (sinceId) { if (ps.sinceId) {
sort._id = 1; sort._id = 1;
query._id = { query._id = {
$gt: sinceId $gt: ps.sinceId
}; };
} else if (untilId) { } else if (ps.untilId) {
query._id = { query._id = {
$lt: untilId $lt: ps.untilId
}; };
} else if (sinceDate) { } else if (ps.sinceDate) {
sort._id = 1; sort._id = 1;
query.createdAt = { query.createdAt = {
$gt: new Date(sinceDate) $gt: new Date(ps.sinceDate)
}; };
} else if (untilDate) { } else if (ps.untilDate) {
query.createdAt = { query.createdAt = {
$lt: new Date(untilDate) $lt: new Date(ps.untilDate)
}; };
} }
//#endregion //#endregion
@ -184,7 +229,7 @@ export default async (params: any, user: ILocalUser) => {
// Issue query // Issue query
const timeline = await Note const timeline = await Note
.find(query, { .find(query, {
limit: limit, limit: ps.limit,
sort: sort sort: sort
}); });

View File

@ -16,17 +16,13 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
if (usernameErr) return rej('invalid username param'); if (usernameErr) return rej('invalid username param');
if (userId === undefined && username === undefined) { if (userId === undefined && username === undefined) {
return rej('userId or pair of username and host is required'); return rej('userId or username is required');
} }
// Get 'host' parameter // Get 'host' parameter
const [host, hostErr] = $.str.optional.get(params.host); const [host, hostErr] = $.str.optional.get(params.host);
if (hostErr) return rej('invalid host param'); if (hostErr) return rej('invalid host param');
if (userId === undefined && host === undefined) {
return rej('userId or pair of username and host is required');
}
// Get 'includeReplies' parameter // Get 'includeReplies' parameter
const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies); const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
if (includeRepliesErr) return rej('invalid includeReplies param'); if (includeRepliesErr) return rej('invalid includeReplies param');

View File

@ -6,6 +6,7 @@ import User, { IUser, validateUsername, validatePassword, pack } from '../../../
import generateUserToken from '../common/generate-native-user-token'; import generateUserToken from '../common/generate-native-user-token';
import config from '../../../config'; import config from '../../../config';
import Meta from '../../../models/meta'; import Meta from '../../../models/meta';
import RegistrationTicket from '../../../models/registration-tickets';
if (config.recaptcha) { if (config.recaptcha) {
recaptcha.init({ recaptcha.init({
@ -29,6 +30,29 @@ export default async (ctx: Koa.Context) => {
const username = body['username']; const username = body['username'];
const password = body['password']; const password = body['password'];
const invitationCode = body['invitationCode'];
const meta = await Meta.findOne({});
if (meta.disableRegistration) {
if (invitationCode == null || typeof invitationCode != 'string') {
ctx.status = 400;
return;
}
const ticket = await RegistrationTicket.findOne({
code: invitationCode
});
if (ticket == null) {
ctx.status = 400;
return;
}
RegistrationTicket.remove({
_id: ticket._id
});
}
// Validate username // Validate username
if (!validateUsername(username)) { if (!validateUsername(username)) {
@ -92,7 +116,7 @@ export default async (ctx: Koa.Context) => {
weight: null weight: null
}, },
settings: { settings: {
autoWatch: true autoWatch: false
} }
}); });

View File

@ -1,5 +1,3 @@
import * as fs from 'fs';
import * as Koa from 'koa'; import * as Koa from 'koa';
import * as send from 'koa-send'; import * as send from 'koa-send';
import * as mongodb from 'mongodb'; import * as mongodb from 'mongodb';
@ -51,23 +49,16 @@ export default async function(ctx: Koa.Context) {
}; };
if ('thumbnail' in ctx.query) { if ('thumbnail' in ctx.query) {
// 画像以外 const thumb = await DriveFileThumbnail.findOne({
if (!file.contentType.startsWith('image/')) { 'metadata.originalId': fileId
const readable = fs.createReadStream(`${__dirname}/assets/thumbnail-not-available.png`); });
ctx.set('Content-Type', 'image/png');
ctx.body = readable; if (thumb != null) {
} else if (file.contentType == 'image/gif') { ctx.set('Content-Type', 'image/jpeg');
// GIF const bucket = await getDriveFileThumbnailBucket();
await sendRaw(); ctx.body = bucket.openDownloadStream(thumb._id);
} else { } else {
const thumb = await DriveFileThumbnail.findOne({ 'metadata.originalId': fileId }); await sendRaw();
if (thumb != null) {
ctx.set('Content-Type', 'image/jpeg');
const bucket = await getDriveFileThumbnailBucket();
ctx.body = bucket.openDownloadStream(thumb._id);
} else {
await sendRaw();
}
} }
} else { } else {
if ('download' in ctx.query) { if ('download' in ctx.query) {

View File

@ -1,6 +1,5 @@
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
import * as fs from 'fs'; import * as fs from 'fs';
import * as stream from 'stream';
import * as mongodb from 'mongodb'; import * as mongodb from 'mongodb';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
@ -17,30 +16,52 @@ import { publishUserStream, publishDriveStream } from '../../stream';
import { isLocalUser, IUser, IRemoteUser } from '../../models/user'; import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
import delFile from './delete-file'; import delFile from './delete-file';
import config from '../../config'; import config from '../../config';
import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
const log = debug('misskey:drive:add-file'); const log = debug('misskey:drive:add-file');
async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> { async function save(path: string, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
let thumbnail: Buffer;
if (['image/jpeg', 'image/png', 'image/webp'].includes(type)) {
thumbnail = await sharp(path)
.resize(300)
.jpeg({
quality: 50,
progressive: true
})
.toBuffer();
}
if (config.drive && config.drive.storage == 'minio') { if (config.drive && config.drive.storage == 'minio') {
const minio = new Minio.Client(config.drive.config); const minio = new Minio.Client(config.drive.config);
const id = uuid.v4(); const key = `${config.drive.prefix}/${uuid.v4()}/${name}`;
const obj = `${config.drive.prefix}/${id}`; const thumbnailKey = `${config.drive.prefix}/${uuid.v4()}/${name}.thumbnail.jpg`;
const baseUrl = config.drive.baseUrl 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.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`;
await minio.putObject(config.drive.bucket, obj, readable, size, { await minio.putObject(config.drive.bucket, key, fs.createReadStream(path), size, {
'Content-Type': type, 'Content-Type': type,
'Cache-Control': 'max-age=31536000, immutable' 'Cache-Control': 'max-age=31536000, immutable'
}); });
if (thumbnail) {
await minio.putObject(config.drive.bucket, thumbnailKey, thumbnail, size, {
'Content-Type': 'image/jpeg',
'Cache-Control': 'max-age=31536000, immutable'
});
}
Object.assign(metadata, { Object.assign(metadata, {
withoutChunks: true, withoutChunks: true,
storage: 'minio', storage: 'minio',
storageProps: { storageProps: {
id: id key: key,
thumbnailKey: thumbnailKey
}, },
url: `${ baseUrl }/${ obj }` url: `${ baseUrl }/${ key }`,
thumbnailUrl: thumbnail ? `${ baseUrl }/${ thumbnailKey }` : null
}); });
const file = await DriveFile.insert({ const file = await DriveFile.insert({
@ -57,12 +78,36 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
// Get MongoDB GridFS bucket // Get MongoDB GridFS bucket
const bucket = await getDriveFileBucket(); const bucket = await getDriveFileBucket();
return new Promise<IDriveFile>((resolve, reject) => { const file = await new Promise<IDriveFile>((resolve, reject) => {
const writeStream = bucket.openUploadStream(name, { contentType: type, metadata }); const writeStream = bucket.openUploadStream(name, {
contentType: type,
metadata
});
writeStream.once('finish', resolve); writeStream.once('finish', resolve);
writeStream.on('error', reject); writeStream.on('error', reject);
readable.pipe(writeStream);
fs.createReadStream(path).pipe(writeStream);
}); });
if (thumbnail) {
const thumbnailBucket = await getDriveFileThumbnailBucket();
await new Promise<IDriveFile>((resolve, reject) => {
const writeStream = thumbnailBucket.openUploadStream(name, {
contentType: 'image/jpeg',
metadata: {
originalId: file._id
}
});
writeStream.once('finish', resolve);
writeStream.on('error', reject);
writeStream.end(thumbnail);
});
}
return file;
} }
} }
@ -321,7 +366,7 @@ export default async function(
} }
} }
} else { } else {
driveFile = await (save(fs.createReadStream(path), detectedName, mime, hash, size, metadata)); driveFile = await (save(path, detectedName, mime, hash, size, metadata));
} }
log(`drive file has been created ${driveFile._id}`); log(`drive file has been created ${driveFile._id}`);

View File

@ -6,8 +6,18 @@ import config from '../../config';
export default async function(file: IDriveFile, isExpired = false) { export default async function(file: IDriveFile, isExpired = false) {
if (file.metadata.storage == 'minio') { if (file.metadata.storage == 'minio') {
const minio = new Minio.Client(config.drive.config); const minio = new Minio.Client(config.drive.config);
const obj = `${config.drive.prefix}/${file.metadata.storageProps.id}`;
// 後方互換性のため、file.metadata.storageProps.key があるかどうかチェックしています。
// 将来的には const obj = file.metadata.storageProps.key; とします。
const obj = file.metadata.storageProps.key ? file.metadata.storageProps.key : `${config.drive.prefix}/${file.metadata.storageProps.id}`;
await minio.removeObject(config.drive.bucket, obj); await minio.removeObject(config.drive.bucket, obj);
if (file.metadata.thumbnailUrl) {
// 後方互換性のため、file.metadata.storageProps.thumbnailKey があるかどうかチェックしています。
// 将来的には const thumbnailObj = file.metadata.storageProps.thumbnailKey; とします。
const thumbnailObj = file.metadata.storageProps.thumbnailKey ? file.metadata.storageProps.thumbnailKey : `${config.drive.prefix}/${file.metadata.storageProps.id}-thumbnail`;
await minio.removeObject(config.drive.bucket, thumbnailObj);
}
} }
// チャンクをすべて削除 // チャンクをすべて削除

View File

@ -95,6 +95,8 @@ type Option = {
}; };
export default async (user: IUser, data: Option, silent = false) => new Promise<INote>(async (res, rej) => { export default async (user: IUser, data: Option, silent = false) => new Promise<INote>(async (res, rej) => {
const isFirstNote = user.notesCount === 0;
if (data.createdAt == null) data.createdAt = new Date(); if (data.createdAt == null) data.createdAt = new Date();
if (data.visibility == null) data.visibility = 'public'; if (data.visibility == null) data.visibility = 'public';
if (data.viaMobile == null) data.viaMobile = false; if (data.viaMobile == null) data.viaMobile = false;
@ -164,6 +166,10 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
// Pack the note // Pack the note
const noteObj = await pack(note); const noteObj = await pack(note);
if (isFirstNote) {
noteObj.isFirstNote = true;
}
const nm = new NotificationManager(user, note); const nm = new NotificationManager(user, note);
const nmRelatedPromises = []; const nmRelatedPromises = [];
@ -229,7 +235,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
async function renderActivity(data: Option, note: INote) { async function renderActivity(data: Option, note: INote) {
const content = data.renote && data.text == null const content = data.renote && data.text == null
? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote)) ? renderAnnounce(data.renote.uri ? data.renote.uri : await renderNote(data.renote), note)
: renderCreate(await renderNote(note)); : renderCreate(await renderNote(note));
return packAp(content); return packAp(content);
@ -322,8 +328,18 @@ async function insertNote(user: IUser, data: Option, tokens: ReturnType<typeof p
: [], : [],
// 以下非正規化データ // 以下非正規化データ
_reply: data.reply ? { userId: data.reply.userId } : null, _reply: data.reply ? {
_renote: data.renote ? { userId: data.renote.userId } : null, userId: data.reply.userId,
user: {
host: data.reply._user.host
}
} : null,
_renote: data.renote ? {
userId: data.renote.userId,
user: {
host: data.renote._user.host
}
} : null,
_user: { _user: {
host: user.host, host: user.host,
inbox: isRemoteUser(user) ? user.inbox : undefined inbox: isRemoteUser(user) ? user.inbox : undefined