Compare commits

..

199 Commits

Author SHA1 Message Date
syuilo
340ce7fa4c 10.38.0 2018-11-04 00:26:00 +09:00
syuilo
ac86fee9b4 Merge pull request #3080 from syuilo/l10n_develop
New Crowdin translations
2018-11-04 00:13:09 +09:00
syuilo
6dfa283d7a New translations ja-JP.yml (English) 2018-11-04 00:11:31 +09:00
syuilo
0cce8a4d21 🎨 2018-11-04 00:10:13 +09:00
syuilo
1c6d9ab2ef New translations ja-JP.yml (Norwegian) 2018-11-04 00:05:11 +09:00
syuilo
6ca265e579 New translations ja-JP.yml (Dutch) 2018-11-04 00:04:59 +09:00
syuilo
c612c4bf18 New translations ja-JP.yml (Japanese, Kansai) 2018-11-04 00:04:50 +09:00
syuilo
481a791a60 New translations ja-JP.yml (Spanish) 2018-11-04 00:04:39 +09:00
syuilo
cb516c2943 New translations ja-JP.yml (Russian) 2018-11-04 00:04:29 +09:00
syuilo
c0abd6f0c0 New translations ja-JP.yml (Portuguese) 2018-11-04 00:04:17 +09:00
syuilo
47695ed685 New translations ja-JP.yml (Polish) 2018-11-04 00:04:07 +09:00
syuilo
4ca8020ef5 New translations ja-JP.yml (Korean) 2018-11-04 00:03:56 +09:00
syuilo
bfac83d5b8 New translations ja-JP.yml (Italian) 2018-11-04 00:03:47 +09:00
syuilo
4cd2e55fd3 New translations ja-JP.yml (German) 2018-11-04 00:03:37 +09:00
syuilo
61c7e7bc48 New translations ja-JP.yml (French) 2018-11-04 00:03:28 +09:00
syuilo
bef41718e2 New translations ja-JP.yml (English) 2018-11-04 00:03:16 +09:00
syuilo
5b4b52bb97 New translations ja-JP.yml (Chinese Simplified) 2018-11-04 00:03:08 +09:00
syuilo
8901b6d774 New translations ja-JP.yml (Catalan) 2018-11-04 00:02:57 +09:00
syuilo
e3a24e9215 [Client] Improve admin panel 2018-11-03 23:57:14 +09:00
syuilo
a515c1f53e Improve API documentation 2018-11-03 22:49:36 +09:00
syuilo
2e22874dec Refactoring 2018-11-03 22:40:12 +09:00
syuilo
30f0b1c30d Add missing semicolons 2018-11-03 22:38:12 +09:00
syuilo
600aea4dbb [MFM] Fix emoji syntax parsing 2018-11-03 22:35:24 +09:00
syuilo
f5d53d784d [Client] Improve admin panel 2018-11-03 22:21:20 +09:00
syuilo
1061e1f7ae i18n 2018-11-03 22:20:09 +09:00
syuilo
1d5fc04aa6 🎨 2018-11-03 22:03:06 +09:00
syuilo
d1cf0c7998 Clean up 2018-11-03 22:01:58 +09:00
syuilo
84218abf2b [Client] Make possible to change password in mobile
モバイル版からパスワードの変更を行えるように
2018-11-03 21:53:03 +09:00
syuilo
5bebdb2511 🎨 2018-11-03 20:10:55 +09:00
syuilo
9c8e9b4165 🎨 2018-11-03 20:03:21 +09:00
syuilo
7b786bfde3 Improve usability of Admin panel 2018-11-03 19:57:44 +09:00
syuilo
42a08642a4 Misskeyのバージョンもクライアントの環境変数に突っ込むように 2018-11-03 17:04:33 +09:00
syuilo
e88f7ca7b2 [Client] Fix some charts 2018-11-03 16:44:05 +09:00
syuilo
c26ed1421b [API] Increase chart limit 2018-11-03 16:43:50 +09:00
syuilo
ed2f94a3c1 oops 2018-11-03 15:28:11 +09:00
syuilo
daba7fe87c [MFM] Fix title syntax parsing 2018-11-03 15:28:00 +09:00
syuilo
afc9caf7bf Improve performance 2018-11-03 15:21:07 +09:00
syuilo
67697a7aa6 Merge pull request #3067 from syuilo/l10n_develop
New Crowdin translations
2018-11-03 15:14:13 +09:00
syuilo
1623d9e70c 🎨 2018-11-03 15:05:00 +09:00
syuilo
c304351335 🎨 2018-11-03 13:39:17 +09:00
syuilo
c1520763c6 🎨 2018-11-03 13:30:57 +09:00
syuilo
4853bc9414 Update src/client/app/admin/views/charts.vue 2018-11-03 13:08:49 +09:00
dependabot[bot]
e7c865f8e3 Bump @types/request from 2.47.1 to 2.48.0 (#3054)
Bumps [@types/request](https://github.com/DefinitelyTyped/DefinitelyTyped) from 2.47.1 to 2.48.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:38:17 +09:00
dependabot[bot]
46cb377bc2 Bump css-loader from 1.0.0 to 1.0.1 (#3070)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v1.0.0...v1.0.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:37:54 +09:00
dependabot[bot]
373a5ba3e1 Bump @types/node from 10.12.0 to 10.12.2 (#3072)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped) from 10.12.0 to 10.12.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:37:38 +09:00
dependabot[bot]
3bedef67c8 Bump elasticsearch from 15.1.1 to 15.2.0 (#3073)
Bumps [elasticsearch](https://github.com/elastic/elasticsearch-js) from 15.1.1 to 15.2.0.
- [Release notes](https://github.com/elastic/elasticsearch-js/releases)
- [Changelog](https://github.com/elastic/elasticsearch-js/blob/master/docs/changelog.asciidoc)
- [Commits](https://github.com/elastic/elasticsearch-js/compare/v15.1.1...v15.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:37:28 +09:00
dependabot[bot]
17ea19ada8 Bump typescript from 3.1.4 to 3.1.5 (#3069)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.1.4...v3.1.5)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:37:11 +09:00
dependabot[bot]
1f5b2285fd Bump file-type from 10.2.0 to 10.3.0 (#3071)
Bumps [file-type](https://github.com/sindresorhus/file-type) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/sindresorhus/file-type/releases)
- [Commits](https://github.com/sindresorhus/file-type/compare/v10.2.0...v10.3.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-03 12:36:59 +09:00
syuilo
17f0001966 New translations ja-JP.yml (English) 2018-11-03 11:51:00 +09:00
syuilo
04ba09a6af New translations ja-JP.yml (Norwegian) 2018-11-03 11:43:16 +09:00
syuilo
70d2744319 New translations ja-JP.yml (Dutch) 2018-11-03 11:43:06 +09:00
syuilo
6b2f0929ec New translations ja-JP.yml (Japanese, Kansai) 2018-11-03 11:42:55 +09:00
syuilo
f2629bd3f2 New translations ja-JP.yml (Spanish) 2018-11-03 11:42:46 +09:00
syuilo
9e6c29c3c0 New translations ja-JP.yml (Russian) 2018-11-03 11:42:38 +09:00
syuilo
abda973094 New translations ja-JP.yml (Portuguese) 2018-11-03 11:42:27 +09:00
syuilo
86b08dd5bd New translations ja-JP.yml (Polish) 2018-11-03 11:42:17 +09:00
syuilo
617e331f0f New translations ja-JP.yml (Korean) 2018-11-03 11:42:06 +09:00
syuilo
cc438a9372 New translations ja-JP.yml (Italian) 2018-11-03 11:41:58 +09:00
syuilo
b0fb218bfd New translations ja-JP.yml (German) 2018-11-03 11:41:50 +09:00
syuilo
fc85a607e6 New translations ja-JP.yml (French) 2018-11-03 11:41:42 +09:00
syuilo
fb244c45e3 New translations ja-JP.yml (English) 2018-11-03 11:41:34 +09:00
syuilo
c123784c54 New translations ja-JP.yml (Chinese Simplified) 2018-11-03 11:41:24 +09:00
syuilo
342a5276fc New translations ja-JP.yml (Catalan) 2018-11-03 11:41:15 +09:00
syuilo
51a32846ee Update src/client/app/admin/views/ap-log.vue 2018-11-03 11:39:56 +09:00
syuilo
35865429a8 🎨 2018-11-03 11:39:18 +09:00
syuilo
aadd5b95b8 Improve admin dashboard 2018-11-03 11:38:00 +09:00
syuilo
f9f2ca51ac Improve stats API 2018-11-03 11:37:44 +09:00
syuilo
1cb93a8c10 🎨 2018-11-03 11:37:17 +09:00
syuilo
7e5dbb2ba5 Fix bug 2018-11-03 11:36:11 +09:00
syuilo
2772e3d80e New translations ja-JP.yml (English) 2018-11-03 03:51:41 +09:00
syuilo
223c578734 Improve admin dashboard 2018-11-03 03:30:28 +09:00
syuilo
d01315dee2 🎨 2018-11-03 03:08:41 +09:00
syuilo
7dafb4ce4c New translations ja-JP.yml (Norwegian) 2018-11-03 03:04:52 +09:00
syuilo
9671db9b14 New translations ja-JP.yml (Dutch) 2018-11-03 03:04:41 +09:00
syuilo
bec559f67c New translations ja-JP.yml (Japanese, Kansai) 2018-11-03 03:04:33 +09:00
syuilo
14053c1394 New translations ja-JP.yml (Spanish) 2018-11-03 03:04:24 +09:00
syuilo
55e4b1c828 New translations ja-JP.yml (Russian) 2018-11-03 03:04:17 +09:00
syuilo
dda3421159 New translations ja-JP.yml (Portuguese) 2018-11-03 03:04:08 +09:00
syuilo
45e7488e60 New translations ja-JP.yml (Polish) 2018-11-03 03:03:55 +09:00
syuilo
30c7bd66b7 New translations ja-JP.yml (Korean) 2018-11-03 03:03:45 +09:00
syuilo
af4f5bdac0 New translations ja-JP.yml (Italian) 2018-11-03 03:03:37 +09:00
syuilo
3d1a8cc341 New translations ja-JP.yml (German) 2018-11-03 03:03:28 +09:00
syuilo
0e52fb2544 New translations ja-JP.yml (French) 2018-11-03 03:03:18 +09:00
syuilo
e6d6c0a17c New translations ja-JP.yml (English) 2018-11-03 03:03:10 +09:00
syuilo
cfd2d47e00 New translations ja-JP.yml (Chinese Simplified) 2018-11-03 03:03:00 +09:00
syuilo
83301a879d New translations ja-JP.yml (Catalan) 2018-11-03 03:02:51 +09:00
syuilo
d7881ba129 Improve admin page 2018-11-03 03:00:23 +09:00
syuilo
b9fef1edf7 New translations ja-JP.yml (Norwegian) 2018-11-03 02:14:35 +09:00
syuilo
2c606f7b23 New translations ja-JP.yml (Dutch) 2018-11-03 02:14:27 +09:00
syuilo
03797607ed New translations ja-JP.yml (Japanese, Kansai) 2018-11-03 02:14:19 +09:00
syuilo
254b7f500d New translations ja-JP.yml (Spanish) 2018-11-03 02:14:09 +09:00
syuilo
51edd51bf2 New translations ja-JP.yml (Russian) 2018-11-03 02:14:00 +09:00
syuilo
0d403f4a3f New translations ja-JP.yml (Portuguese) 2018-11-03 02:13:52 +09:00
syuilo
0fa134addd New translations ja-JP.yml (Polish) 2018-11-03 02:13:44 +09:00
syuilo
7002270084 New translations ja-JP.yml (Korean) 2018-11-03 02:13:37 +09:00
syuilo
1c5452d047 New translations ja-JP.yml (Italian) 2018-11-03 02:13:26 +09:00
syuilo
f0d62c07bf New translations ja-JP.yml (German) 2018-11-03 02:13:18 +09:00
syuilo
496ca55bba New translations ja-JP.yml (French) 2018-11-03 02:13:11 +09:00
syuilo
79cfba226b New translations ja-JP.yml (English) 2018-11-03 02:13:00 +09:00
syuilo
f69b60dffe New translations ja-JP.yml (Chinese Simplified) 2018-11-03 02:12:51 +09:00
syuilo
513385133f New translations ja-JP.yml (Catalan) 2018-11-03 02:12:43 +09:00
syuilo
6f1e2f6636 Improve admin page 2018-11-03 02:06:34 +09:00
syuilo
8ae94c034d Update hashtags.ts 2018-11-02 23:46:57 +09:00
syuilo
cd9696f25e Update src/server/api/endpoints/aggregation/hashtags.ts 2018-11-02 23:32:40 +09:00
syuilo
d62a6bab41 Remove needless properties 2018-11-02 23:27:47 +09:00
syuilo
20df002746 🍕 2018-11-02 23:23:01 +09:00
syuilo
fa6b01546e New translations ja-JP.yml (English) 2018-11-02 23:22:06 +09:00
syuilo
91b37a6e52 New translations ja-JP.yml (Norwegian) 2018-11-02 23:14:33 +09:00
syuilo
d8171d7c8b New translations ja-JP.yml (Dutch) 2018-11-02 23:14:23 +09:00
syuilo
fa96e2daf1 New translations ja-JP.yml (Japanese, Kansai) 2018-11-02 23:14:15 +09:00
syuilo
87708c3b84 New translations ja-JP.yml (Spanish) 2018-11-02 23:14:06 +09:00
syuilo
6319023cc9 New translations ja-JP.yml (Russian) 2018-11-02 23:13:58 +09:00
syuilo
efad9d1b60 New translations ja-JP.yml (Portuguese) 2018-11-02 23:13:48 +09:00
syuilo
a1dea657fa New translations ja-JP.yml (Polish) 2018-11-02 23:13:38 +09:00
syuilo
6b1b75717b New translations ja-JP.yml (Korean) 2018-11-02 23:13:31 +09:00
syuilo
efe08e0bd3 New translations ja-JP.yml (Italian) 2018-11-02 23:13:22 +09:00
syuilo
62892c4894 New translations ja-JP.yml (German) 2018-11-02 23:13:15 +09:00
syuilo
0c2a62da11 New translations ja-JP.yml (French) 2018-11-02 23:13:07 +09:00
syuilo
5bc9e9aadd New translations ja-JP.yml (English) 2018-11-02 23:12:56 +09:00
syuilo
112c33d35b New translations ja-JP.yml (Chinese Simplified) 2018-11-02 23:12:48 +09:00
syuilo
864da3030f New translations ja-JP.yml (Catalan) 2018-11-02 23:12:38 +09:00
syuilo
f2e719b361 [Client] Admin page improved 2018-11-02 23:05:53 +09:00
syuilo
6aab515389 New translations ja-JP.yml (English) 2018-11-02 22:59:53 +09:00
syuilo
819b535ab0 [API] Implement admin/add-emoji 2018-11-02 15:04:02 +09:00
syuilo
60e95ac2ac Clean up 2018-11-02 14:53:55 +09:00
syuilo
9b94ddff0a Clean up 2018-11-02 13:49:09 +09:00
syuilo
174f8022eb Refactor 2018-11-02 13:47:44 +09:00
syuilo
ddc3c5ba68 Better index 2018-11-02 12:49:18 +09:00
syuilo
a7e6b766be Resolve #2623 2018-11-02 12:49:08 +09:00
syuilo
befc35a3ac Update src/server/api/endpoints/meta.ts 2018-11-02 12:16:03 +09:00
syuilo
2e9bbf389e Better index 2018-11-02 12:08:28 +09:00
MeiMei
80b5fda292 Remote custom emojis (#3074)
* Remote custom emojis

* んほおおおおお
2018-11-02 08:59:40 +09:00
syuilo
c48cbd95f6 Fix bug 2018-11-02 03:41:09 +09:00
syuilo
931bdc6aac Refactoring, Clean up and bug fixes 2018-11-02 03:32:24 +09:00
syuilo
7f81506c8b New translations ja-JP.yml (French) 2018-11-01 22:01:38 +09:00
syuilo
b4b9e76c8d Refactoring 2018-11-01 21:28:39 +09:00
syuilo
e5a3dcf868 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-01 21:01:55 +09:00
syuilo
825648535c Refactoring 2018-11-01 21:01:47 +09:00
Acid Chicken (硫酸鶏)
5cbc908ba3 Fix typo 2018-11-01 19:32:11 +09:00
syuilo
895cf53ee1 Fix bug 2018-11-01 18:05:14 +09:00
syuilo
e41f74e77c 10.37.0 2018-11-01 11:52:33 +09:00
syuilo
c21caad1c5 Custom emoji (#3061)
* wip

* wip

* wip
2018-11-01 11:51:49 +09:00
syuilo
86fcd3a378 Fix bug 2018-11-01 10:00:15 +09:00
syuilo
2b3687b3cb 10.36.1 2018-11-01 09:35:24 +09:00
syuilo
5d61c7c691 Refactor and use original image for banner 2018-11-01 09:30:51 +09:00
syuilo
1bb266e7c7 Update package-lock.json 2018-11-01 09:19:31 +09:00
syuilo
1fca8d322c Clean up 2018-11-01 09:19:22 +09:00
syuilo
325cd03a59 Improve performance 2018-11-01 09:08:00 +09:00
syuilo
2f7e6baa05 Clean up 2018-11-01 09:02:54 +09:00
syuilo
d252e066fe Improve performance 2018-11-01 09:00:18 +09:00
dependabot[bot]
fe7bd9ab3c Bump typescript-eslint-parser from 20.0.0 to 20.1.1 (#3057)
Bumps [typescript-eslint-parser](https://github.com/eslint/typescript-eslint-parser) from 20.0.0 to 20.1.1.
- [Release notes](https://github.com/eslint/typescript-eslint-parser/releases)
- [Changelog](https://github.com/eslint/typescript-eslint-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/typescript-eslint-parser/compare/v20.0.0...v20.1.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-01 08:24:13 +09:00
dependabot[bot]
84e3f41305 Bump ts-loader from 5.2.2 to 5.3.0 (#3055)
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 5.2.2 to 5.3.0.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v5.2.2...v5.3.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-01 08:24:05 +09:00
dependabot[bot]
3e8cccad0d Bump jsdom from 12.2.0 to 13.0.0 (#3058)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 12.2.0 to 13.0.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/12.2.0...13.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-01 08:23:38 +09:00
Acid Chicken (硫酸鶏)
a2b94d67f7 Update README.md [AUTOGEN] (#3060) 2018-11-01 08:23:11 +09:00
dependabot[bot]
6ab61e73b0 Bump apexcharts from 2.1.6 to 2.1.9 (#3056)
Bumps [apexcharts](https://github.com/apexcharts/apexcharts.js) from 2.1.6 to 2.1.9.
- [Release notes](https://github.com/apexcharts/apexcharts.js/releases)
- [Changelog](https://github.com/apexcharts/apexcharts.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apexcharts/apexcharts.js/compare/v2.1.6...v2.1.9)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-01 08:22:53 +09:00
Acid Chicken (硫酸鶏)
051c6973af Update README.md [AUTOGEN] (#3059) 2018-11-01 08:20:56 +09:00
syuilo
806a49ec3d 10.36.0 2018-11-01 00:12:13 +09:00
syuilo
3829fe128a Update src/server/api/endpoints/users/relation.ts 2018-11-01 00:11:52 +09:00
syuilo
649177985d [API] Implement users/relation 2018-11-01 00:11:21 +09:00
syuilo
c15148b23c [API] Include detailed user information for block/mute response 2018-10-31 23:34:35 +09:00
syuilo
261a3f5d91 Better rate limitting 2018-10-31 23:03:14 +09:00
syuilo
256ba78ba5 Fix 2018-10-31 22:55:17 +09:00
syuilo
04aff8866e [MFM] Better hashtag detection 2018-10-31 22:38:05 +09:00
syuilo
1a51b98700 Refactor 2018-10-31 22:35:02 +09:00
syuilo
f64100226d Revert "Clean up"
This reverts commit 8948a0d3a4.
2018-10-31 22:10:25 +09:00
syuilo
b7805e48a6 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-10-31 22:08:27 +09:00
syuilo
0d9556620d Update package-lock.json 2018-10-31 22:08:19 +09:00
Acid Chicken (硫酸鶏)
a51828a7a2 Update test.yml (#3052) 2018-10-31 22:07:26 +09:00
Acid Chicken (硫酸鶏)
7e2009f408 Update config.yml (#3051) 2018-10-31 22:00:21 +09:00
syuilo
008d950a39 10.35.1 2018-10-31 18:07:59 +09:00
syuilo
22d5862afb 🎨 2018-10-31 18:07:00 +09:00
syuilo
de569147a5 Fix #3041 2018-10-31 17:56:21 +09:00
syuilo
a82c3db750 Merge pull request #3038 from syuilo/l10n_develop
New Crowdin translations
2018-10-31 13:44:10 +09:00
dependabot[bot]
80706d10af Bump @types/speakeasy from 2.0.2 to 2.0.3 (#3012)
Bumps [@types/speakeasy](https://github.com/DefinitelyTyped/DefinitelyTyped) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-10-31 13:43:45 +09:00
dependabot[bot]
93f01ed4df Bump typescript from 3.1.3 to 3.1.4 (#3049)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.1.3...v3.1.4)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-10-31 13:42:47 +09:00
dependabot[bot]
a3a28e5557 Bump file-type from 10.1.0 to 10.2.0 (#3039)
Bumps [file-type](https://github.com/sindresorhus/file-type) from 10.1.0 to 10.2.0.
- [Release notes](https://github.com/sindresorhus/file-type/releases)
- [Commits](https://github.com/sindresorhus/file-type/compare/v10.1.0...v10.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-10-31 13:42:31 +09:00
syuilo
8948a0d3a4 Clean up 2018-10-31 13:28:05 +09:00
syuilo
d849ea9b41 Clean up 2018-10-31 13:23:12 +09:00
syuilo
0144575f3f Improve performance 2018-10-31 13:20:24 +09:00
syuilo
bdbe646ca7 Improve performance 2018-10-31 13:14:45 +09:00
syuilo
1a1483a242 Update package-lock.json 2018-10-31 12:29:38 +09:00
syuilo
962346785b New translations ja-JP.yml (English) 2018-10-31 11:31:00 +09:00
syuilo
6a7b0df810 New translations ja-JP.yml (Norwegian) 2018-10-31 11:22:11 +09:00
syuilo
4142de9195 New translations ja-JP.yml (Dutch) 2018-10-31 11:22:07 +09:00
syuilo
9195e1be00 New translations ja-JP.yml (Japanese, Kansai) 2018-10-31 11:22:03 +09:00
syuilo
75382d13fd New translations ja-JP.yml (Spanish) 2018-10-31 11:21:59 +09:00
syuilo
d444280a28 New translations ja-JP.yml (Russian) 2018-10-31 11:21:52 +09:00
syuilo
52fc0fe04a New translations ja-JP.yml (Portuguese) 2018-10-31 11:21:48 +09:00
syuilo
216bebadf1 New translations ja-JP.yml (Polish) 2018-10-31 11:21:44 +09:00
syuilo
a5592931cb New translations ja-JP.yml (Korean) 2018-10-31 11:21:39 +09:00
syuilo
a2228417ff New translations ja-JP.yml (Italian) 2018-10-31 11:21:35 +09:00
syuilo
3e1e292c3e New translations ja-JP.yml (German) 2018-10-31 11:21:31 +09:00
syuilo
f2f039ae9e New translations ja-JP.yml (French) 2018-10-31 11:21:27 +09:00
syuilo
29dde1eda0 New translations ja-JP.yml (English) 2018-10-31 11:21:21 +09:00
syuilo
45d3792ce0 New translations ja-JP.yml (Chinese Simplified) 2018-10-31 11:21:17 +09:00
syuilo
875d0aaebb New translations ja-JP.yml (Catalan) 2018-10-31 11:21:13 +09:00
syuilo
d0220764cc New translations ja-JP.yml (French) 2018-10-30 05:31:25 +09:00
syuilo
75c1df9531 New translations ja-JP.yml (French) 2018-10-30 05:11:49 +09:00
syuilo
bca7156d6b New translations ja-JP.yml (French) 2018-10-30 05:02:28 +09:00
260 changed files with 6160 additions and 3947 deletions

View File

@@ -9,6 +9,7 @@ mongodb:
db: test-misskey
user: admin
pass: ''
# __REDIS__
redis:
host: localhost
port: 6379

View File

@@ -97,14 +97,22 @@ jobs:
- run:
name: Build
command: |
docker build .
docker build . | tee docker.log
tail -n 1 docker.log | read __Successfully __built tag
- when:
condition: <<parameters.with_deploy>>
steps:
- run:
name: Deploy
command: |
docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD && docker push misskey/misskey
if [ "$DOCKERHUB_USERNAME$DOCKERHUB_PASSWORD" ]
then
docker tag $tag misskey/misskey
docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD
docker push misskey/misskey
else
echo -e '\033[0;33mAborted deploying to Docker Hub\033[0;39m'
fi
workflows:
version: 2

View File

@@ -88,7 +88,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=zwSu01tOtn5xTUucDZHuPsCxF2HBEMVs9ROJKTlEV_o%3D" alt="nemu"></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" alt="Naoki Kosaka"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3?token-time=2145916800&token-hash=qsdn0-e6yLaLI6hUX9JAkyTR6a5UdnSp7T1foniBvGQ%3D" alt="YUKIMOCHI"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/8241184/39e18850e87a449e9c9a71acb3310ebd/2?token-time=2145916800&token-hash=iUXOQzRyJDv3PJxwS7Mjwg1459dzh2trOq6NFtXu_OM%3D" alt="Acid Chicken"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=UERBN4OyP7Nh5XwwdDg0N0IE5cD6_qUQMO81Z5Wizso%3D" alt="Hiratake"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/10789744/97175095d8f04c0f86225ff47cb98d40/1?token-time=2145916800&token-hash=P4BIzCX2I1CkEP66ottfhsC8Wr6BUSamjA-vq3pLqFI%3D" alt="Naoki Hirayama"></td>
@@ -98,7 +98,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<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" alt="Takashi Shibuya"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
<td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td>
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
<td><a href="https://www.patreon.com/acid_chicken">Acid Chicken</a></td>
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
<td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td>
@@ -111,7 +111,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
</tr><tr>
</tr></table>
**Last updated:** Sat, 27 Oct 2018 04:36:06 UTC
**Last updated:** Wed, 31 Oct 2018 23:21:06 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "Nach links schichten"
pop-right: "Rechts andocken"
dev: "Fehler beim Erstellen der Applikation. Bitte versuche es erneut."
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Mitteilungen"
apps: "In App öffnen"
mute: "Stummschalten"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Sicherheit"
signin: "サインイン履歴"
password: "Passwort"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
reset: "Passwort ändern"
enter-current-password: "Derzeitiges Passwort eingeben"
enter-new-password: "Neues Passwort eingeben"
enter-new-password-again: "Neues Passwort erneut eingeben"
not-match: "Passwörter stimmen nicht überein."
changed: "Passwort geändert"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "Stack to the left"
pop-right: "Dock on the right"
dev: "Failed to create the application. Please try again."
ai-chan-kawaii: "Ai-chan kawaii!"
auth/views/form.vue:
share-access: "Would you <b>allow</b> <i>{{ app.name }}</i> to access your account?"
permission-ask: "This application requires the following permissions:"
@@ -249,7 +250,7 @@ common/views/components/games/reversi/reversi.room.vue:
this-game-is-started-soon: "The game will begin in seconds"
waiting-for-other: "Waiting for the opponent"
waiting-for-me: "Waiting for the your preparation"
waiting-for-both: "Prepareing"
waiting-for-both: "Preparing"
cancel: "Cancel"
ready: "Ready"
cancel-ready: "Cancel \"Ready\""
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Profile"
notification: "Notification"
apps: "Apps"
mute: "Mute"
mute-and-block: "Mute / Block"
blocking: "Blocking"
security: "Security"
signin: "Sign in history"
password: "Password"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "Max"
in-use: "In use"
stats: "Statistics"
desktop/views/components/settings.mute.vue:
no-users: "No muted users"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "Mute / Block"
mute: "Mute"
block: "Blocking"
no-muted-users: "No muted users"
no-blocked-users: "No blocked users"
common/views/components/password-settings.vue:
reset: "Change password"
enter-current-password: "Enter the current password"
enter-new-password: "Enter the new password"
enter-new-password-again: "Enter new password again"
enter-new-password-again: "Enter the new password again"
not-match: "The new passwords do not match"
changed: "Password updated"
changed: "Password changed"
desktop/views/components/sub-note-content.vue:
private: "This post is private"
deleted: "This post has been deleted"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "Pop-out"
close: "Close"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "Dashboard"
instance: "Instance"
emoji: "Emoji"
users: "Users"
update: "Updates"
update: "Update"
announcements: "Announcements"
hashtags: "Hashtags"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Back to Misskey"
admin/views/dashboard.vue:
dashboard: "Dashboard"
all-users: "All Users"
original-users: "Users on this instance"
all-notes: "All the posts"
original-notes: "Posts on this instance"
accounts: "Accounts"
notes: "Notes"
drive: "Drive"
instances: "Instances"
this-instance: "This instance"
federated: "Federated"
invite: "Invite"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "Chart"
per-day: "per Day"
per-hour: "per Hour"
federation: "Federation"
notes: "Posts"
users: "Users"
drive: "Drive"
network: "Network"
charts:
federation-instances: "The number of instances: increase/decrease"
federation-instances-total: "Total number of instances"
notes: "The number of posts: increase/decrease (Combined)"
local-notes: "The number of posts: increase/decrease (Local)"
remote-notes: "The number of posts: increase/decrease (Remote)"
notes-total: "Total posts"
users: "The number of users: increase/decrease"
users-total: "Total users"
drive: "Capacity used as the storage: increase/decrease"
drive-total: "Total usage of Drive"
drive-files: "The number of files on the storage: increase/decrease"
drive-files-total: "Total number of files on Drive"
network-requests: "Requests"
network-time: "Response time"
network-usage: "Traffic"
admin/views/users.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/admin/admin.verify-user.vue:
verify-user: "User account verification settings"
verify: "Verify account"
verified: "The account is now being verified"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "User account unverification settings"
unverify: "Unverify account"
unverified: "The account is now being unverified"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "Add emoji"
name: "Emoji name"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "Aliases"
aliases-desc: "スペースで区切って複数設定できます。"
url: "Image URL"
add: "Add"
admin/views/announcements.vue:
announcements: "Announcements"
desktop/views/pages/admin/admin.hashtags.vue:
save: "Save"
remove: "Remove"
add: "Add"
title: "Title"
text: "Content"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Only media posts"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "Sounds"
enable-sounds: "Enable sounds"
mark-as-read-all-unread-notes: "Mark all posts as read"
password: "Password"
mobile/views/pages/user.vue:
follows-you: "Follows you"
following: "Following"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "A la izqda."
pop-right: "A la dcha."
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "¿Deseas <b>permitir</b> a <i>{{ app.name }}</i> acceder a tu cuenta?"
permission-ask: "La aplicación requiere los siguientes permisos:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Perfil"
notification: "Notificación"
apps: "Aplicaciones"
mute: "Silenciar"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Seguridad"
signin: "Historial de inicios de sesión"
password: "Contraseña"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "No hay usuarios silenciados"
desktop/views/components/settings.password.vue:
reset: "Cambiar contraseña"
enter-current-password: "Ingresar contraseña actual"
enter-new-password: "Ingresar nueva contraseña"
enter-new-password-again: "Ingresar nueva contraseña de nuevo"
not-match: "Las nuevas contraseñas no se corresponden consigo mismas"
changed: "Contraseña actualizada"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -28,11 +28,11 @@ common:
BSoD:
fatal-error: ":( 致命的な問題が発生しました。"
update-browser-os: "お使いのブラウザ(またはOS)のバージョンを更新すると解決する可能性があります。"
error-code: "エラーコード"
browser-version: "ブラウザ バージョン"
client-version: "クライアント バージョン"
error-code: "Code derreur"
browser-version: "Version du navigateur"
client-version: "La version du client"
email-support: "問題が解決しない場合は、上記の情報をお書き添えの上 syuilotan@yahoo.co.jp までご連絡ください。"
thanks: "Thank you for using Misskey."
thanks: "Merci davoir choisi dutiliser Misskey."
got-it: "J'ai compris !"
customization-tips:
title: "Conseils de personnalisation"
@@ -62,7 +62,7 @@ common:
years_ago: "Il y a {} an·s"
month-and-day: "{month} mois/{day} jour"
trash: "Corbeille"
drive: "ドライブ"
drive: "Drive"
weekday-short:
sunday: "D"
monday: "L"
@@ -124,12 +124,12 @@ common:
reduce-motion: "Réduire les animations dans linterface utilisateur"
this-setting-is-this-device-only: "Uniquement sur cet appareil"
do-not-use-in-production: 'Il sagit dune version de développement. Ne pas utiliser dans un environnement de production.'
is-remote-user: "このユーザー情報はコピーです。"
is-remote-user: "Ces informations utilisateur ont été copiées."
is-remote-post: "この投稿情報はコピーです。"
view-on-remote: "正確な情報を見る"
view-on-remote: "Consulter le profil complet"
error:
title: '問題が発生しました'
retry: 'やり直す'
title: 'Une erreur est survenue'
retry: 'Réessayer'
reversi:
drawn: "Partie nulle"
my-turn: "Cest votre tour"
@@ -185,7 +185,8 @@ common:
rename: "Renommer"
stack-left: "Vers la gauche"
pop-right: "Vers la droite"
dev: "アプリの作成に失敗しました。再度お試しください。"
dev: "Échec lors de la création de lapplication. Veuillez réessayer."
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "Désirez-vous <b>autoriser</b> <i>{{ app.name }}</i> à avoir accès à votre compte ?"
permission-ask: "Cette application nécessite les autorisations suivantes :"
@@ -542,24 +543,24 @@ desktop/views/components/charts.vue:
title: "Graphiques"
per-day: "par jour"
per-hour: "par heure"
federation: "フェデレーション"
federation: "Fédération"
notes: "Publications"
users: "Utilisateurs"
drive: "Drive"
network: "Réseau"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
federation-instances-total: "Nombre total dinstances"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "Total des notes"
users: "Nombre dutilisateurs·trices : augmentation/diminution"
users-total: "ユーザーの積算"
users-total: "Nombre total des utilisateurs·rices"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-total: "Utilisation totale du lecteur"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
drive-files-total: "Nombre total de fichiers sur le lecteur"
network-requests: "Requêtes"
network-time: "Temps de réponse"
network-usage: "Traffic"
@@ -679,10 +680,10 @@ desktop/views/components/note.vue:
reposted-by: "Partagé par {}"
reply: "Répondre"
renote: "Partager"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
add-reaction: "Ajouter votre réaction"
detail: "Détails"
private: "Cette publication est privée"
deleted: "Cette publication a été supprimée"
desktop/views/components/notes.vue:
error: "Échec du chargement."
retry: "Réessayer"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Notification"
apps: "Applications"
mute: "Mettre en sourdine"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Sécurité"
signin: "Historique de connexion"
password: "Mot de Passe"
@@ -765,7 +767,7 @@ desktop/views/components/settings.vue:
deck-default: "デッキをデフォルトのUIにする"
display: "Affichage et design"
customize: "Personnaliser l'Accueil"
wallpaper: "壁紙"
wallpaper: "Arrière plan"
choose-wallpaper: "Sélectionner un fond d'écran"
delete-wallpaper: "Supprimer le fond d'écran"
dark-mode: "Mode nuit"
@@ -777,14 +779,14 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur"
show-reply-target: "Afficher les réponses"
timeline: "タイムライン"
timeline: "Chronologie"
show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "Afficher mes republications dans les fils"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Afficher la carte"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: ""
deck-column-align-center: "Centrer"
deck-column-align-left: "À gauche"
sound: "Son"
enable-sounds: "Activer le son"
enable-sounds-desc: "Jouer un son lorsque vous recevez un message. Ce paramètre est sauvegardé dans le navigateur."
@@ -825,7 +827,7 @@ desktop/views/components/settings.vue:
tools: "Outils"
task-manager: "Gestionnaire de tâches"
third-parties: "Services tiers"
navbar-position: "ナビゲーションバーの位置"
navbar-position: "Position de la barre de navigation"
navbar-position-top: "En haut"
navbar-position-left: "à gauche"
navbar-position-right: "à droite"
@@ -850,32 +852,36 @@ desktop/views/components/settings.2fa.vue:
common/views/components/api-settings.vue:
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
regenerate-token: "トークンを再生成"
token: "Token:"
enter-password: "パスワードを入力してください"
regeneration-of-token: "Si votre jeton est compromis, vous pouvez le régénérer."
regenerate-token: "Régénérer le jeton"
token: "Jeton :"
enter-password: "Entrez le mot de passe"
console:
title: 'APIコンソール'
endpoint: 'エンドポイント'
parameter: 'パラメータ'
send: '送信'
sending: '応答待ち'
response: '結果'
title: 'Console API'
endpoint: 'Point de terminaison'
parameter: 'Paramètres'
send: 'Envoyer'
sending: 'Envoi en cours'
response: 'Résultat'
desktop/views/components/settings.apps.vue:
no-apps: "Aucune application autorisée"
common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "Aucun utilisateurs mis en sourdine"
desktop/views/components/settings.password.vue:
reset: "Changer votre mot de passe"
enter-current-password: "Entrez votre mot de passe actuel"
enter-new-password: "Entrez votre nouveau mot de passe"
enter-new-password-again: "Entrez à nouveau le nouveau mot de passe"
not-match: "Le nouveau mot de passe ne correspond pas."
changed: "Mot de passe modifié avec succès"
in-use: "utilisé"
stats: "Statistiques"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
@@ -941,55 +947,96 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "Fermer"
desktop/views/pages/admin/admin.vue:
dashboard: "Tableau de bord"
users: "Utilisateur·rice·s"
update: "Mises à jour"
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
dashboard: "Tableau de bord"
all-users: "Toutes les utilisateurrices"
original-users: "Utilisateur·rice·s sur cette instance"
all-notes: "Toutes les publications"
original-notes: "Publications sur cette instance"
invite: "Invitation"
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
suspend-user: "Suspendre un·e utilisateur·rice"
suspend: "Suspendre"
suspended: "Suspendu avec succès"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "Lever la suspension dutilisateur·rice·s"
unsuspend: "Suspension levée"
unsuspended: "La suspension de lutilisateur·rice a été levée avec succès"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "Paramètres de vérification du compte utilisateur"
verify: "Vérification du compte"
verified: "Le compte a été vérifié"
desktop/views/pages/admin/admin.unverify-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
unverify-user: "ユーザーの公式アカウント解除"
unverify: "Ôter la vérification du compte"
unverified: "Ce compte n'est pas vérifié"
desktop/views/pages/admin/admin.announcements.vue:
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Les publications médias uniquement"
is-media-view: "Vue média"
edit: "Options"
desktop/views/pages/deck/deck.user-column.vue:
posts: "投稿"
following: "フォロー"
followers: "フォロワー"
images: "画像"
activity: "アクティビティ"
timeline: "タイムライン"
pinned-notes: "ピン留めされた投稿"
push-to-a-list: "リストに追加"
posts: "Publications"
following: "Suit"
followers: "Abonné·e·s"
images: "Images"
activity: "Activité"
timeline: "Chronologie"
pinned-notes: "Publications épinglées"
push-to-a-list: "Ajouter à la liste"
desktop/views/pages/stats/stats.vue:
all-users: "Toutes les utilisateurrices"
original-users: "Utilisateur·rice·s sur cette instance"
@@ -1042,7 +1089,7 @@ desktop/views/pages/user/user.friends.vue:
no-users: "Pas d'utilisateurs"
desktop/views/pages/user/user.vue:
is-suspended: "Ce compte a été suspendu."
last-used-at: "最終アクセス"
last-used-at: "Actif·ive pour la dernière fois"
desktop/views/pages/user/user.photos.vue:
title: "Photos"
loading: "Chargement en cours"
@@ -1055,9 +1102,9 @@ desktop/views/pages/user/user.profile.vue:
mute: "Mettre en sourdine"
muted: "Muting"
unmute: "Enlever la sourdine"
block: "ブロックする"
unblock: "ブロック解除"
block-confirm: "このユーザーをブロックしますか?"
block: "Bloquer"
unblock: "Débloquer"
block-confirm: "Bloquer cet utilisateur ?"
push-to-a-list: "Ajouter à la liste"
list-pushed: "Vous avez ajouté {user} à la liste {list}."
desktop/views/pages/user/user.header.vue:
@@ -1065,10 +1112,10 @@ desktop/views/pages/user/user.header.vue:
following: "Suit"
followers: "Abonné·e·s"
is-bot: "Ce compte est un Bot"
years-old: ""
year: ""
month: ""
day: ""
years-old: "ans dâge"
year: "Année"
month: "Mois"
day: "Jour"
desktop/views/pages/user/user.timeline.vue:
default: "Publications"
with-replies: "Publications et réponses"
@@ -1127,8 +1174,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "CW"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mark-as-sensitive: "Marquer comme sensible"
unmark-as-sensitive: "Ne pas marquer comme sensible"
mobile/views/components/media-image.vue:
sensitive: "Le contenu est NSFW"
click-to-show: "Cliquer pour afficher"
@@ -1288,8 +1335,8 @@ mobile/views/pages/settings.vue:
timeline: "Fil d'actualité"
show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
show-renoted-my-notes: "Afficher mes publications partagées"
show-local-renotes: "Afficher les publications partagées localement"
post-style: "Style de la publication"
post-style-standard: "Standard"
post-style-smart: "Intelligent"
@@ -1322,7 +1369,8 @@ mobile/views/pages/settings.vue:
signout: "Déconnexion"
sound: "Sons"
enable-sounds: "Activer les sons"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
mark-as-read-all-unread-notes: "Marquer toutes les publications comme lues"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "Vous suit"
following: "Abonnements"
@@ -1332,10 +1380,10 @@ mobile/views/pages/user.vue:
timeline: "Fil d'actualité"
media: "Media"
is-suspended: "This account has been suspended."
mute: "ミュート"
unmute: "ミュート解除"
block: "ブロック"
unblock: "ブロック解除"
mute: "Mettre en sourdine"
unmute: "Enlever la sourdine"
block: "Bloquer"
unblock: "Débloquer"
mobile/views/pages/user/home.vue:
recent-notes: "Notes récentes"
images: "Images"
@@ -1382,28 +1430,28 @@ docs:
dev/views/index.vue:
manage-apps: "Gestion des applications"
dev/views/apps.vue:
manage-apps: "アプリを管理"
create-app: "アプリ作成"
app-missing: "アプリなし"
manage-apps: "Gestion des applications"
create-app: "Créer une app"
app-missing: "Aucune application"
dev/views/new-app.vue:
create-app: "アプリケーションの作成"
app-name: "アプリケーション名"
app-name-desc: "あなたのアプリの名称。"
app-name-ex: "ex) Misskey for iOS"
app-overview: "アプリの概要"
app-desc: "あなたのアプリの簡単な説明や紹介。"
app-desc-ex: "ex) Misskey iOSクライアント。"
create-app: "Création dune application"
app-name: "Nom de lapplication"
app-name-desc: "Le nom de votre application"
app-name-ex: "p. ex. Misskey pour iOS"
app-overview: "Description courte de lapplication"
app-desc: "Brève description introductive à votre application."
app-desc-ex: "p. ex) Misskey pour iOS"
callback-url: "コールバックURL (オプション)"
callback-url-desc: "ユーザーが認証フォームで認証した際にリダイレクトするURLを設定できます。"
authority: "権限"
authority: "Autorisations "
authority-desc: "ここで要求した機能だけがAPIからアクセスできます。"
authority-warning: "アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。"
account-read: "アカウントの情報を見る。"
account-write: "アカウントの情報を操作する。"
note-write: "投稿する。"
reaction-write: "リアクションしたりリアクションをキャンセルする。"
following-write: "フォローしたりフォロー解除する。"
drive-read: "ドライブを見る。"
drive-write: "ドライブを操作する。"
notification-read: "通知を見る。"
notification-write: "通知を操作する。"
account-read: "Afficher les informations du compte"
account-write: "Modifications des informations du compte"
note-write: "Publications."
reaction-write: "Ajout et suppression de réactions."
following-write: "Sabonner et se désabonner."
drive-read: "Lecture du Drive."
drive-write: "Téléversement/suppression des fichiers de votre Lecteur."
notification-read: "Lire vos notifications."
notification-write: "Gestion de vos notifications."

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -201,6 +201,7 @@ common:
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
@@ -981,7 +982,7 @@ common/views/components/mute-and-block.vue:
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -1069,48 +1070,88 @@ desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
back-to-misskey: "Misskeyに戻る"
desktop/views/pages/admin/admin.dashboard.vue:
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
announcements: "お知らせ"
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
desktop/views/pages/admin/admin.hashtags.vue:
admin/views/announcements.vue:
announcements: "お知らせ"
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
@@ -1529,6 +1570,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねんで!"
pop-right: "右に出すで!"
dev: "アプリの作成あかんかったわ。もっぺんやってみて。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があんさんのアカウントにアクセスすんのを<b>許可</b>してもええか?"
permission-ask: "このアプリは次の権限を要求してんで:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "守護神セキュリティ"
signin: "こんな感じでサインインしたらしいで"
password: "パスワード"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使うとる"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはおらんで"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "のパスワードを入れてや"
enter-new-password: "さらのパスワード入れてや"
enter-new-password-again: "もういっぺんさらのパスワードを入れてや"
not-match: "パスワードがおうとらん"
changed: "パスワード変えたわ"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は見せられへんわ"
deleted: "この投稿なんか無くなってもうたわ"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "さいなら"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "知っといてや"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "知り合い全員や"
original-users: "ここの人らだけ"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
invite: "来てや"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結した"
desktop/views/pages/admin/admin.unsuspend-user.vue:
suspended: "凍結しました"
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除した"
desktop/views/pages/admin/admin.verify-user.vue:
unsuspended: "凍結を解除しました"
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにした"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウントにせーへん"
unverify: "公式アカウントにはさせへんで"
unverified: "公式アカウントを解除したで"
desktop/views/pages/admin/admin.announcements.vue:
announcements: "知っといてや"
desktop/views/pages/admin/admin.hashtags.vue:
verified: "公式アカウントにしました"
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿だけや"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンド鳴らす"
mark-as-read-all-unread-notes: "全部もう読んだわ"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされとるで"
following: "フォロー"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Profiel"
notification: "Melding"
apps: "Apps"
mute: "Dempen"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Beveiliging"
signin: "Inloggeschiedenis"
password: "Wachtwoord"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "Geen gedempte gebruikers"
desktop/views/components/settings.password.vue:
reset: "Wachtwoord wijzigen"
enter-current-password: "Voer je huidige wachtwoord in"
enter-new-password: "Voer je nieuwe wachtwoord in"
enter-new-password-again: "Voer je nieuwe wachtwoord nogmaals in"
not-match: "Het nieuwe wachtwoord komt niet overeen"
changed: "Wachtwoord bijgewerkt"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "Uitvouwen"
close: "Sluiten"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "Volgt jou"
following: "Volgend"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "Til høyre"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "Notifikasjon"
apps: "Apper"
mute: "Demp"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "Passord"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "Lukk"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
users: "Brukere"
update: "Oppdater"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
invite: "Inviter"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "Suspender"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "Lyder"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "Følger"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "Przypnij do lewej"
pop-right: "Odepnij w prawo"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "Czy chcesz <b>zezwolić</b> <i>{{ app.name }}</i> na dostęp do Twojego konta?"
permission-ask: "Ta aplikacja wymaga następujących uprawnień:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "Profil"
notification: "Powiadomienia"
apps: "Aplikacje"
mute: "Wyciszanie"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "Bezpieczeństwo"
signin: "Historia logowań"
password: "Hasło"
@@ -867,15 +869,19 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "Brak wyciszonych użytkowników"
desktop/views/components/settings.password.vue:
reset: "Zmień hasło"
enter-current-password: "Wprowadź obecne hasło"
enter-new-password: "Wprowadź nowe hasło"
enter-new-password-again: "Wprowadź ponownie nowe hasło"
not-match: "Nowe hasła nie pasują do siebie"
changed: "Pomyślnie zmieniono hasło"
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/sub-note-content.vue:
private: "ten wpis jest prywatny"
deleted: "ten wpis został usunięty"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "Pop-out"
close: "Zamknij"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Tylko wpisy z zawartością multimedialną"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "Śledzi Cię"
following: "Śledzeni"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "Acoplar à direita"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "Você <b>permite</b> que <i>{{ app.name }}</i> acesse sua conta?"
permission-ask: "Este aplicativo precisa das seguintes permissões:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
users: "Usuários"
update: "Actualizações"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "Todos os usuários"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "Sons"
enable-sounds: "Ativar sons"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "Te segue"
following: "Seguindo"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

View File

@@ -186,6 +186,7 @@ common:
stack-left: "左に重ねる"
pop-right: "右に出す"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -741,7 +742,8 @@ desktop/views/components/settings.vue:
profile: "プロフィール"
notification: "通知"
apps: "アプリ"
mute: "ミュート"
mute-and-block: "ミュート/ブロック"
blocking: "ブロック"
security: "セキュリティ"
signin: "サインイン履歴"
password: "パスワード"
@@ -867,9 +869,13 @@ common/views/components/drive-settings.vue:
max: "容量"
in-use: "使用中"
stats: "統計"
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "ミュートとブロック"
mute: "ミュート"
block: "ブロック"
no-muted-users: "ミュートしているユーザーはいません"
no-blocked-users: "ブロックしているユーザーはいません"
common/views/components/password-settings.vue:
reset: "パスワードを変更する"
enter-current-password: "現在のパスワードを入力してください"
enter-new-password: "新しいパスワードを入力してください"
@@ -941,41 +947,82 @@ desktop/views/components/users-list-item.vue:
desktop/views/components/window.vue:
popout: "ポップアウト"
close: "閉じる"
desktop/views/pages/admin/admin.vue:
admin/views/index.vue:
dashboard: "ダッシュボード"
instance: "インスタンス"
emoji: "カスタム絵文字"
users: "ユーザー"
update: "更新"
announcements: "お知らせ"
hashtags: "ハッシュタグ"
desktop/views/pages/admin/admin.dashboard.vue:
back-to-misskey: "Misskeyに戻る"
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
accounts: "アカウント"
notes: "投稿"
drive: "ドライブ"
instances: "インスタンス"
this-instance: "このインスタンス"
federated: "連合"
invite: "招待"
banner-url: "Banner URL"
disableRegistration: "Disable new user registration"
disableLocalTimeline: "Disable the local timeline"
desktop/views/pages/admin/admin.suspend-user.vue:
admin/views/charts.vue:
title: "チャート"
per-day: "1日ごと"
per-hour: "1時間ごと"
federation: "フェデレーション"
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
charts:
federation-instances: "インスタンスの増減"
federation-instances-total: "インスタンスの積算"
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の積算"
users: "ユーザーの増減"
users-total: "ユーザーの積算"
drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/users.vue:
suspend-user: "ユーザーの凍結"
suspend: "凍結"
suspended: "凍結しました"
desktop/views/pages/admin/admin.unsuspend-user.vue:
unsuspend-user: "ユーザーの凍結の解除"
unsuspend: "凍結の解除"
unsuspended: "凍結を解除しました"
desktop/views/pages/admin/admin.verify-user.vue:
verify-user: "ユーザーの公式アカウント設定"
verify: "公式アカウントにする"
verified: "公式アカウントにしました"
desktop/views/pages/admin/admin.unverify-user.vue:
unverify-user: "ユーザーの公式アカウント解除"
unverify: "公式アカウントを解除する"
unverified: "公式アカウントを解除しました"
desktop/views/pages/admin/admin.announcements.vue:
admin/views/emoji.vue:
add-emoji:
title: "絵文字の登録"
name: "絵文字名"
name-desc: "a~z 0~9 _ の文字が使えます。"
aliases: "エイリアス"
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
admin/views/announcements.vue:
announcements: "お知らせ"
desktop/views/pages/admin/admin.hashtags.vue:
save: "保存"
remove: "削除"
add: "追加"
title: "タイトル"
text: "内容"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"
desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
@@ -1323,6 +1370,7 @@ mobile/views/pages/settings.vue:
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
password: "パスワード"
mobile/views/pages/user.vue:
follows-you: "フォローされています"
following: "フォロー"

128
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "10.33.0",
"version": "10.37.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -563,9 +563,9 @@
"integrity": "sha512-OftRLCgAzJP7vmKn9by/GVjnf4hloz/pXNOwPo0vKGAfXI7GqWXJi9N2kRar4cP5s1dGwuwcagWqO6iHBTq1Mg=="
},
"@types/node": {
"version": "10.12.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
"integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ=="
"version": "10.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.2.tgz",
"integrity": "sha512-53ElVDSnZeFUUFIYzI8WLQ25IhWzb6vbddNp8UHlXQyU0ET2RhV5zg0NfubzU7iNMh5bBXb0htCzfvrSVNgzaQ=="
},
"@types/orchestrator": {
"version": "0.3.2",
@@ -626,9 +626,9 @@
"integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y="
},
"@types/request": {
"version": "2.47.1",
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.1.tgz",
"integrity": "sha512-TV3XLvDjQbIeVxJ1Z3oCTDk/KuYwwcNKVwz2YaT0F5u86Prgc4syDAp6P96rkTQQ4bIdh+VswQIC9zS6NjY7/g==",
"version": "2.48.0",
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.0.tgz",
"integrity": "sha512-KnfoOtqXKllSqfXSEvGTd8KDkNlpHs+PWr6I6XiEIWk/jckH3pNmWDXNFZyPkB9wApb8vzDq2wMByM/0GFSmXg==",
"requires": {
"@types/caseless": "*",
"@types/form-data": "*",
@@ -691,9 +691,12 @@
"integrity": "sha512-XWwqRvaSsf4yq/4SYL5/7n5i2RWqf+jtIRlasj65cuZZDZ01wtkDfAIxrEpYcLvzT1HMqBmsnMEcZjK+OMeojQ=="
},
"@types/speakeasy": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@types/speakeasy/-/speakeasy-2.0.2.tgz",
"integrity": "sha512-h8KW3wSd3/l4oKRGYPxExCaos5VmjcnwDG3RK25tfcoWQR9iLmM9UbwvF1Pd+UT5aY1Z3LdQGt4xU0u9Zk/C2Q=="
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/speakeasy/-/speakeasy-2.0.3.tgz",
"integrity": "sha512-lDc49Aec4WnQPRhW3n90ct14CH0Zyrj48RGMK1SSQP6BOf8HamWg+PG9uj1DVnaa6t+lhQU1j1lhGA7d9baxWw==",
"requires": {
"@types/node": "*"
}
},
"@types/superagent": {
"version": "3.8.4",
@@ -733,9 +736,9 @@
"integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0="
},
"@types/tough-cookie": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz",
"integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ=="
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.4.tgz",
"integrity": "sha512-Set5ZdrAaKI/qHdFlVMgm/GsAv/wkXhSTuZFkJ+JI7HK+wIkIlOaUXSXieIvJ0+OvGIqtREFoE+NHJtEq0gtEw=="
},
"@types/uglify-js": {
"version": "3.0.4",
@@ -1259,9 +1262,9 @@
}
},
"apexcharts": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-2.1.6.tgz",
"integrity": "sha512-kIb4Q07bWwTGuTWhyzhDAOz6nrltDgyP8VUUwqetxr0o11mNH6PA6YVnR/e9nyd9HU6q3bFZN8eVuSatnqdxAQ==",
"version": "2.1.9",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-2.1.9.tgz",
"integrity": "sha512-Qs/jLUa03wqPR53yMk8QAwq+qrX/Odc3IIXH2WVVjdWyFXS1lYzGSDbVcVDnOKkxoLdAlzPI3icb2bMjskwfXQ==",
"requires": {
"babel-polyfill": "^6.26.0",
"core-js": "^2.5.7",
@@ -2247,9 +2250,9 @@
}
},
"cafy": {
"version": "11.3.0",
"resolved": "https://registry.npmjs.org/cafy/-/cafy-11.3.0.tgz",
"integrity": "sha512-7kqqF4I6seSNSAWihRfnM78wP/OwaZMrCNIUzu0+TC1pDGfF2uoVfMsAJ1oV1jZsZ2L2qlUSvo9zhSEIouS/xQ=="
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/cafy/-/cafy-12.0.0.tgz",
"integrity": "sha512-HGsunRfyqFyG1/oh+Szw8GtVpj4pwehyqmp8sTO1QwDF3htjDP+vVBWzg7iOU2Y3Cm+h+UiEpf6DJ0p57RNmAg=="
},
"caller-path": {
"version": "0.1.0",
@@ -3094,15 +3097,15 @@
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
},
"css-loader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.0.tgz",
"integrity": "sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz",
"integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==",
"requires": {
"babel-code-frame": "^6.26.0",
"css-selector-tokenizer": "^0.7.0",
"icss-utils": "^2.1.0",
"loader-utils": "^1.0.2",
"lodash.camelcase": "^4.3.0",
"lodash": "^4.17.11",
"postcss": "^6.0.23",
"postcss-modules-extract-imports": "^1.2.0",
"postcss-modules-local-by-default": "^1.2.0",
@@ -3134,9 +3137,9 @@
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
"css-selector-tokenizer": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
"integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
"integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
"requires": {
"cssesc": "^0.1.0",
"fastparse": "^1.1.1",
@@ -3332,12 +3335,12 @@
}
},
"data-urls": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz",
"integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
"integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
"requires": {
"abab": "^2.0.0",
"whatwg-mimetype": "^2.1.0",
"whatwg-mimetype": "^2.2.0",
"whatwg-url": "^7.0.0"
}
},
@@ -4501,9 +4504,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"elasticsearch": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-15.1.1.tgz",
"integrity": "sha512-Yr9xy10rUMjDty7qCys7X9AIW5+PX4Gtv2NksZqXIc+AZiWna/y2QwZdiSLtb5LTOKDp7PbegfuokhIjMHUpKw==",
"version": "15.2.0",
"resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-15.2.0.tgz",
"integrity": "sha512-jOFcBoEh3Sn3gjUTozInODZTLriJtfppAUC7jnQCUE+OUj8o7GoAyC+L4h/L3ZxmXNFbQCunqVR+nmSofHdo9A==",
"requires": {
"agentkeepalive": "^3.4.1",
"chalk": "^1.0.0",
@@ -5272,9 +5275,9 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fastparse": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
"integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg="
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
},
"fd-slicer": {
"version": "1.1.0",
@@ -5311,9 +5314,9 @@
}
},
"file-type": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-10.1.0.tgz",
"integrity": "sha512-fkjfXnqBRrdUFTS6opakWyMXb+uzDv8zOCqjSOWPbzMLnYnmnUEv/RNY9igkk4nc8TVL44Xd1OCC2fJXH3eb7Q=="
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-10.3.0.tgz",
"integrity": "sha512-wk3yZ4wav7qrpJJuDfW3zSYCoxA/ZWZ8YtvrFYcbAE8jSXGFEej7jWVqFKWeeNqFIlG3B3o+fzoSKC6HJvdWUg=="
},
"filename-regex": {
"version": "2.0.1",
@@ -8351,9 +8354,9 @@
"integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ=="
},
"jsdom": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-12.2.0.tgz",
"integrity": "sha512-QPOggIJ8fquWPLaYYMoh+zqUmdphDtu1ju0QGTitZT1Yd8I5qenPpXM1etzUegu3MjVp8XPzgZxdn8Yj7e40ig==",
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-13.0.0.tgz",
"integrity": "sha512-Kmq4ASMNkgpY+YufE322EnIKoiz0UWY2DRkKlU7d5YrIW4xiVRhWFrZV1fr6w/ZNxQ50wGAH5gGRzydgnmkkvw==",
"requires": {
"abab": "^2.0.0",
"acorn": "^6.0.2",
@@ -8374,6 +8377,7 @@
"symbol-tree": "^3.2.2",
"tough-cookie": "^2.4.3",
"w3c-hr-time": "^1.0.1",
"w3c-xmlserializer": "^1.0.0",
"webidl-conversions": "^4.0.2",
"whatwg-encoding": "^1.0.5",
"whatwg-mimetype": "^2.2.0",
@@ -9036,11 +9040,6 @@
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
"integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
},
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
"lodash.clone": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz",
@@ -11985,9 +11984,9 @@
}
},
"postcss-modules-extract-imports": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz",
"integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz",
"integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==",
"requires": {
"postcss": "^6.0.1"
}
@@ -15569,9 +15568,9 @@
}
},
"ts-loader": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.2.2.tgz",
"integrity": "sha512-vM/TrEKXBqRYq5yLatsXyKFnYSpv53klmGtrILGlNqcMsxPVi8+e4yr1Agbu9oMZepx/4szDVn5QpFo83IQdQg==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.0.tgz",
"integrity": "sha512-lGSNs7szRFj/rK9T1EQuayE3QNLg6izDUxt5jpmq0RG1rU2bapAt7E7uLckLCUPeO1jwxCiet2oRaWovc53UAg==",
"requires": {
"chalk": "^2.3.0",
"enhanced-resolve": "^4.0.0",
@@ -15683,16 +15682,17 @@
}
},
"typescript": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz",
"integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA=="
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.5.tgz",
"integrity": "sha512-muYNWV9j5+3mXoKD6oPONKuGUmYiFX14gfo9lWm9ZXRHOqVDQiB4q1CzFPbF4QLV2E9TZXH6oK55oQ94rn3PpA=="
},
"typescript-eslint-parser": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-20.0.0.tgz",
"integrity": "sha512-HZEoGA+LnS3etUlVAPX6I8sZ7872Yb0vPvQv6QDCIE44KD3bFmvPEQ4LbiD+qGkcxh6segjVK0v3rxpb2R6oSA==",
"version": "20.1.1",
"resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-20.1.1.tgz",
"integrity": "sha512-IJhpqHK60Pz2J5pe8rJUQ10DcMcGwhQnvRFcPV79coEV3bpNfSiHkgpS+sf6zx2ANDWgBhmtZbK9ICOy+v3FKA==",
"requires": {
"eslint": "4.19.1",
"eslint-visitor-keys": "^1.0.0",
"typescript-estree": "2.1.0"
},
"dependencies": {
@@ -16775,6 +16775,16 @@
"browser-process-hrtime": "^0.1.2"
}
},
"w3c-xmlserializer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.0.0.tgz",
"integrity": "sha512-0et1+9uXYiIRAecx1D5Z1nk60+vimniGdIKl4XjeqkWi6acoHNlXMv1VR5jV+jF4ooeO08oWbYxeAJOcon1oMA==",
"requires": {
"domexception": "^1.0.1",
"webidl-conversions": "^4.0.2",
"xml-name-validator": "^3.0.0"
}
},
"ware": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz",

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.35.0",
"clientVersion": "1.0.11255",
"version": "10.38.0",
"clientVersion": "1.0.11454",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@@ -61,20 +61,20 @@
"@types/mocha": "5.2.5",
"@types/mongodb": "3.1.12",
"@types/ms": "0.7.30",
"@types/node": "10.12.0",
"@types/node": "10.12.2",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.3.0",
"@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.7",
"@types/request": "2.47.1",
"@types/request": "2.48.0",
"@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.27",
"@types/sharp": "0.21.0",
"@types/showdown": "1.7.5",
"@types/single-line-log": "1.1.0",
"@types/speakeasy": "2.0.2",
"@types/speakeasy": "2.0.3",
"@types/systeminformation": "3.23.0",
"@types/tinycolor2": "1.4.1",
"@types/tmp": "0.0.33",
@@ -84,35 +84,35 @@
"@types/websocket": "0.0.40",
"@types/ws": "6.0.1",
"animejs": "2.2.0",
"apexcharts": "2.1.6",
"apexcharts": "2.1.9",
"autobind-decorator": "2.1.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
"bcryptjs": "2.4.3",
"bee-queue": "1.2.2",
"bootstrap-vue": "2.0.0-rc.11",
"cafy": "11.3.0",
"cafy": "12.0.0",
"chai": "4.2.0",
"chai-http": "4.2.0",
"chalk": "2.4.1",
"chart.js": "2.7.3",
"commander": "2.19.0",
"crc-32": "1.2.0",
"css-loader": "1.0.0",
"css-loader": "1.0.1",
"dateformat": "3.0.3",
"debug": "4.1.0",
"deep-equal": "1.0.1",
"deepcopy": "0.6.3",
"diskusage": "0.2.5",
"double-ended-queue": "2.1.0-0",
"elasticsearch": "15.1.1",
"elasticsearch": "15.2.0",
"emojilib": "2.3.0",
"escape-regexp": "0.0.1",
"eslint": "5.8.0",
"eslint-plugin-vue": "4.7.1",
"eventemitter3": "3.1.0",
"file-loader": "2.0.0",
"file-type": "10.1.0",
"file-type": "10.3.0",
"fuckadblock": "3.2.1",
"gulp": "3.9.1",
"gulp-cssnano": "2.1.3",
@@ -135,7 +135,7 @@
"is-root": "2.0.0",
"is-url": "1.2.4",
"js-yaml": "3.12.0",
"jsdom": "12.2.0",
"jsdom": "13.0.0",
"json5": "2.1.0",
"json5-loader": "1.0.1",
"koa": "2.6.1",
@@ -201,11 +201,11 @@
"textarea-caret": "3.1.0",
"tinycolor2": "1.4.1",
"tmp": "0.0.33",
"ts-loader": "5.2.2",
"ts-loader": "5.3.0",
"ts-node": "7.0.1",
"tslint": "5.10.0",
"typescript": "3.1.3",
"typescript-eslint-parser": "20.0.0",
"typescript": "3.1.5",
"typescript-eslint-parser": "20.1.1",
"uglify-es": "3.3.9",
"url-loader": "1.1.2",
"uuid": "3.3.2",

View File

@@ -230,7 +230,7 @@ export default abstract class Chart<T> {
null;
// ログ取得
const logs = await this.collection.find({
let logs = await this.collection.find({
group: group,
span: span,
date: {
@@ -245,6 +245,27 @@ export default abstract class Chart<T> {
}
});
// 要求された範囲にログがひとつもなかったら
if (logs.length == 0) {
// もっとも新しいログを持ってくる
// (すくなくともひとつログが無いと隙間埋めできないため)
const recentLog = await this.collection.findOne({
group: group,
span: span
}, {
sort: {
date: -1
},
fields: {
_id: 0
}
});
if (recentLog) {
logs = [recentLog];
}
}
// 整形
for (let i = (range - 1); i >= 0; i--) {
const current =
@@ -269,14 +290,11 @@ export default abstract class Chart<T> {
/**
* [{
* xxxxx: 1,
* yyyyy: 5
* xxxxx: 1, yyyyy: 5
* }, {
* xxxxx: 2,
* yyyyy: 6
* xxxxx: 2, yyyyy: 6
* }, {
* xxxxx: 3,
* yyyyy: 7
* xxxxx: 3, yyyyy: 7
* }]
*
* を

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
viewBox="0 0 135.46667 135.46667"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r15371"
sodipodi:docname="header-icon.dark.svg"
inkscape:export-filename="C:\Users\syuilo\projects\misskey\assets\favicon\32.png"
inkscape:export-xdpi="6"
inkscape:export-ydpi="6">
<defs
id="defs2">
<inkscape:path-effect
effect="simplify"
id="path-effect5115"
is_visible="true"
steps="1"
threshold="0.000408163"
smooth_angles="360"
helper_size="0"
simplify_individual_paths="false"
simplify_just_coalesce="false"
simplifyindividualpaths="false"
simplifyJustCoalesce="false" />
<inkscape:path-effect
effect="simplify"
id="path-effect5111"
is_visible="true"
steps="1"
threshold="0.000408163"
smooth_angles="360"
helper_size="0"
simplify_individual_paths="false"
simplify_just_coalesce="false"
simplifyindividualpaths="false"
simplifyJustCoalesce="false" />
<inkscape:path-effect
effect="simplify"
id="path-effect5104"
is_visible="true"
steps="1"
threshold="0.000408163"
smooth_angles="360"
helper_size="0"
simplify_individual_paths="false"
simplify_just_coalesce="false"
simplifyindividualpaths="false"
simplifyJustCoalesce="false" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="114.309"
inkscape:cy="251.50613"
inkscape:document-units="px"
inkscape:current-layer="g4502"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:snap-smooth-nodes="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:window-width="1920"
inkscape:window-height="1027"
inkscape:window-x="-8"
inkscape:window-y="1072"
inkscape:window-maximized="1"
inkscape:snap-object-midpoints="true"
inkscape:snap-midpoints="true"
inkscape:object-paths="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
objecttolerance="1"
guidetolerance="1"
inkscape:snap-nodes="false"
inkscape:snap-others="false">
<inkscape:grid
type="xygrid"
id="grid4504"
spacingx="4.2333334"
spacingy="4.2333334"
empcolor="#ff3fff"
empopacity="0.25098039"
empspacing="4" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="レイヤー 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-30.809093,-111.78601)">
<g
id="g4502"
transform="matrix(1.096096,0,0,1.096096,-2.960633,-44.023579)">
<g
style="fill-opacity:1"
transform="translate(-1.3333333e-6,-1.3439941e-6)"
id="g5125">
<g
transform="matrix(0.91391326,0,0,0.91391326,7.9719907,17.595761)"
id="text4489"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.03404236px;line-height:476.69509888px;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';letter-spacing:0px;word-spacing:0px;fill-opacity:1;stroke:none;stroke-width:0.28950602px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
aria-label="Mi">
<path
sodipodi:nodetypes="zccssscssccscczzzccsccsscscsccz"
inkscape:connector-curvature="0"
id="path5210"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill-opacity:1;stroke-width:0.28950602px"
d="m 75.196381,231.17126 c -5.855419,0.0202 -10.885068,-3.50766 -13.2572,-7.61584 -1.266603,-1.79454 -3.772419,-2.43291 -3.807919,0 v 11.2332 c 0,4.51309 -1.645397,8.41504 -4.936191,11.70583 -3.196772,3.19677 -7.098714,4.79516 -11.705826,4.79516 -4.513089,0 -8.415031,-1.59839 -11.705825,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -61.7729 c 0,-3.47884 0.987238,-6.6286 2.961715,-9.44928 2.068499,-2.91471 4.701135,-4.9362 7.897906,-6.06447 1.786431,-0.65816 3.666885,-0.98724 5.641362,-0.98724 5.077225,0 9.308247,1.97448 12.693064,5.92343 1.786431,1.97448 2.820681,3.00873 3.102749,3.10275 0,0 13.408119,16.21319 13.78421,16.49526 0.376091,0.28206 1.480789,2.43848 4.127113,2.43848 2.646324,0 3.89218,-2.15642 4.26827,-2.43848 0.376091,-0.28207 13.784088,-16.49526 13.784088,-16.49526 0.09402,0.094 1.081261,-0.94022 2.961715,-3.10275 3.478837,-3.94895 7.756866,-5.92343 12.834096,-5.92343 1.88045,0 3.76091,0.32908 5.64136,0.98724 3.19677,1.12827 5.7824,3.14976 7.75688,6.06447 2.06849,2.82068 3.10274,5.97044 3.10274,9.44928 v 61.7729 c 0,4.51309 -1.6454,8.41504 -4.93619,11.70583 -3.19677,3.19677 -7.09871,4.79516 -11.70582,4.79516 -4.51309,0 -8.41504,-1.59839 -11.705828,-4.79516 -3.196772,-3.29079 -4.795158,-7.19274 -4.795158,-11.70583 v -11.2332 c -0.277898,-3.06563 -2.987588,-1.13379 -3.948953,0 -2.538613,4.70114 -7.401781,7.59567 -13.2572,7.61584 z" />
<path
inkscape:connector-curvature="0"
id="path5212"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'OTADESIGN Rounded';-inkscape-font-specification:'OTADESIGN Rounded';fill-opacity:1;stroke-width:0.28950602px"
d="m 145.83461,185.00361 q -5.92343,0 -10.15445,-4.08999 -4.08999,-4.23102 -4.08999,-10.15445 0,-5.92343 4.08999,-10.01342 4.23102,-4.23102 10.15445,-4.23102 5.92343,0 10.15445,4.23102 4.23102,4.08999 4.23102,10.01342 0,5.92343 -4.23102,10.15445 -4.23102,4.08999 -10.15445,4.08999 z m 0.14103,2.82068 q 5.92343,0 10.01342,4.23102 4.23102,4.23102 4.23102,10.15445 v 34.83541 q 0,5.92343 -4.23102,10.15445 -4.08999,4.08999 -10.01342,4.08999 -5.92343,0 -10.15445,-4.08999 -4.23102,-4.23102 -4.23102,-10.15445 v -34.83541 q 0,-5.92343 4.23102,-10.15445 4.23102,-4.23102 10.15445,-4.23102 z" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -0,0 +1,27 @@
/**
* Admin
*/
import VueRouter from 'vue-router';
// Style
import './style.styl';
import init from '../init';
import Index from './views/index.vue';
init(launch => {
document.title = 'Admin';
// Init router
const router = new VueRouter({
mode: 'history',
base: '/admin/',
routes: [
{ path: '/', component: Index },
]
});
// Launch the app
launch(router);
});

View File

@@ -0,0 +1,6 @@
@import "../app"
@import "../reset"
html
height 100%
background var(--bg)

View File

@@ -0,0 +1,64 @@
<template>
<div>
<ui-card>
<div slot="title">%fa:broadcast-tower% %i18n:@announcements%</div>
<section v-for="(announcement, i) in announcements" class="fit-top">
<ui-input v-model="announcement.title" @change="save">
<span>%i18n:@title%</span>
</ui-input>
<ui-textarea v-model="announcement.text">
<span>%i18n:@text%</span>
</ui-textarea>
<ui-button-group>
<ui-button inline @click="save">%fa:save R% %i18n:@save%</ui-button>
<ui-button inline @click="remove(i)">%fa:trash-alt R% %i18n:@remove%</ui-button>
</ui-button-group>
</section>
<section>
<ui-button @click="add">%fa:plus% %i18n:@add%</ui-button>
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
announcements: [],
};
},
created() {
(this as any).os.getMeta().then(meta => {
this.announcements = meta.broadcasts;
});
},
methods: {
add() {
this.announcements.push({
title: '',
text: ''
});
},
remove(i) {
this.announcements = this.announcements.filter((_, j) => j !== i);
this.save();
},
save() {
(this as any).api('admin/update-meta', {
broadcasts: this.announcements
}).then(() => {
(this as any).os.apis.dialog({ text: `Saved` });
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
}
}
});
</script>

View File

@@ -0,0 +1,104 @@
<template>
<div class="hyhctythnmwihguaaapnbrbszsjqxpio">
<table>
<thead>
<tr>
<th>%fa:exchange-alt% In/Out</th>
<th>%fa:server% Host</th>
<th>%fa:bolt% Activity</th>
<th>%fa:user% Actor</th>
</tr>
</thead>
<tbody>
<tr v-for="log in logs" :key="log.id">
<td :class="log.direction">{{ log.direction == 'in' ? '<' : '>' }} {{ log.direction }}</td>
<td>{{ log.host }}</td>
<td>{{ log.activity }}</td>
<td>@{{ log.actor }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
data() {
return {
logs: [],
connection: null
};
},
mounted() {
this.connection = (this as any).os.stream.useSharedConnection('apLog');
this.connection.on('stats', this.onLog);
this.connection.on('statsLog', this.onLogs);
this.connection.send('requestLog', {
id: Math.random().toString().substr(2, 8),
length: 50
});
},
beforeDestroy() {
this.connection.dispose();
},
methods: {
onLog(log) {
log.id = Math.random();
this.logs.unshift(log);
if (this.logs.length > 50) this.logs.pop();
},
onLogs(logs) {
logs.reverse().forEach(log => this.onLog(log));
}
}
});
</script>
<style lang="stylus" scoped>
.hyhctythnmwihguaaapnbrbszsjqxpio
display block
padding 16px
height 250px
overflow auto
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
> table
width 100%
max-width 100%
overflow auto
border-spacing 0
border-collapse collapse
color #555
thead
border-bottom solid 2px #eee
tr
th
font-weight normal
text-align left
tbody
tr
&:nth-child(odd)
background #fbfbfb
th, td
padding 8px 16px
min-width 128px
td.in
color #d26755
td.out
color #55bb83
</style>

View File

@@ -0,0 +1,441 @@
<template>
<div class="qvgidhudpqhjttdhxubzuyrhyzgslujw">
<header>
<b>%fa:chart-bar R% %i18n:@title%:</b>
<select v-model="src">
<optgroup label="%i18n:@federation%">
<option value="federation-instances">%i18n:@charts.federation-instances%</option>
<option value="federation-instances-total">%i18n:@charts.federation-instances-total%</option>
</optgroup>
<optgroup label="%i18n:@users%">
<option value="users">%i18n:@charts.users%</option>
<option value="users-total">%i18n:@charts.users-total%</option>
</optgroup>
<optgroup label="%i18n:@notes%">
<option value="notes">%i18n:@charts.notes%</option>
<option value="local-notes">%i18n:@charts.local-notes%</option>
<option value="remote-notes">%i18n:@charts.remote-notes%</option>
<option value="notes-total">%i18n:@charts.notes-total%</option>
</optgroup>
<optgroup label="%i18n:@drive%">
<option value="drive-files">%i18n:@charts.drive-files%</option>
<option value="drive-files-total">%i18n:@charts.drive-files-total%</option>
<option value="drive">%i18n:@charts.drive%</option>
<option value="drive-total">%i18n:@charts.drive-total%</option>
</optgroup>
<optgroup label="%i18n:@network%">
<option value="network-requests">%i18n:@charts.network-requests%</option>
<option value="network-time">%i18n:@charts.network-time%</option>
<option value="network-usage">%i18n:@charts.network-usage%</option>
</optgroup>
</select>
<div>
<span @click="span = 'day'" :class="{ active: span == 'day' }">%i18n:@per-day%</span> | <span @click="span = 'hour'" :class="{ active: span == 'hour' }">%i18n:@per-hour%</span>
</div>
</header>
<div ref="chart"></div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as ApexCharts from 'apexcharts';
const limit = 90;
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
const negate = arr => arr.map(x => -x);
export default Vue.extend({
data() {
return {
chart: null,
src: 'notes',
span: 'hour',
chartInstance: null
};
},
computed: {
data(): any {
if (this.chart == null) return null;
switch (this.src) {
case 'federation-instances': return this.federationInstancesChart(false);
case 'federation-instances-total': return this.federationInstancesChart(true);
case 'users': return this.usersChart(false);
case 'users-total': return this.usersChart(true);
case 'notes': return this.notesChart('combined');
case 'local-notes': return this.notesChart('local');
case 'remote-notes': return this.notesChart('remote');
case 'notes-total': return this.notesTotalChart();
case 'drive': return this.driveChart();
case 'drive-total': return this.driveTotalChart();
case 'drive-files': return this.driveFilesChart();
case 'drive-files-total': return this.driveFilesTotalChart();
case 'network-requests': return this.networkRequestsChart();
case 'network-time': return this.networkTimeChart();
case 'network-usage': return this.networkUsageChart();
}
},
stats(): any[] {
const stats =
this.span == 'day' ? this.chart.perDay :
this.span == 'hour' ? this.chart.perHour :
null;
return stats;
}
},
watch: {
src() {
this.render();
},
span() {
this.render();
}
},
async mounted() {
this.now = new Date();
const [perHour, perDay] = await Promise.all([Promise.all([
(this as any).api('charts/federation', { limit: limit, span: 'hour' }),
(this as any).api('charts/users', { limit: limit, span: 'hour' }),
(this as any).api('charts/notes', { limit: limit, span: 'hour' }),
(this as any).api('charts/drive', { limit: limit, span: 'hour' }),
(this as any).api('charts/network', { limit: limit, span: 'hour' })
]), Promise.all([
(this as any).api('charts/federation', { limit: limit, span: 'day' }),
(this as any).api('charts/users', { limit: limit, span: 'day' }),
(this as any).api('charts/notes', { limit: limit, span: 'day' }),
(this as any).api('charts/drive', { limit: limit, span: 'day' }),
(this as any).api('charts/network', { limit: limit, span: 'day' })
])]);
const chart = {
perHour: {
federation: perHour[0],
users: perHour[1],
notes: perHour[2],
drive: perHour[3],
network: perHour[4]
},
perDay: {
federation: perDay[0],
users: perDay[1],
notes: perDay[2],
drive: perDay[3],
network: perDay[4]
}
};
this.chart = chart;
this.render();
},
methods: {
setSrc(src) {
this.src = src;
},
render() {
if (this.chartInstance) {
this.chartInstance.destroy();
}
this.chartInstance = new ApexCharts(this.$refs.chart, Object.assign({
chart: {
type: 'area',
height: 300,
animations: {
dynamicAnimation: {
enabled: false
}
},
toolbar: {
show: false
},
zoom: {
enabled: false
}
},
dataLabels: {
enabled: false
},
grid: {
clipMarkers: false,
},
stroke: {
curve: 'straight',
width: 2
},
xaxis: {
type: 'datetime'
},
yaxis: {
}
}, this.data));
this.chartInstance.render();
},
getDate(i: number) {
const y = this.now.getFullYear();
const m = this.now.getMonth();
const d = this.now.getDate();
const h = this.now.getHours();
return (
this.span == 'day' ? new Date(y, m, d - i) :
this.span == 'hour' ? new Date(y, m, d, h - i) :
null
);
},
format(arr) {
return arr.map((v, i) => ({ x: this.getDate(i).getTime(), y: v }));
},
federationInstancesChart(total: boolean): any {
return {
series: [{
data: this.format(total
? this.stats.federation.instance.total
: sum(this.stats.federation.instance.inc, negate(this.stats.federation.instance.dec))
)
}]
};
},
notesChart(type: string): any {
return {
series: [{
name: 'All',
type: 'line',
data: this.format(type == 'combined'
? sum(this.stats.notes.local.inc, negate(this.stats.notes.local.dec), this.stats.notes.remote.inc, negate(this.stats.notes.remote.dec))
: sum(this.stats.notes[type].inc, negate(this.stats.notes[type].dec))
)
}, {
name: 'Renotes',
type: 'area',
data: this.format(type == 'combined'
? sum(this.stats.notes.local.diffs.renote, this.stats.notes.remote.diffs.renote)
: this.stats.notes[type].diffs.renote
)
}, {
name: 'Replies',
type: 'area',
data: this.format(type == 'combined'
? sum(this.stats.notes.local.diffs.reply, this.stats.notes.remote.diffs.reply)
: this.stats.notes[type].diffs.reply
)
}, {
name: 'Normal',
type: 'area',
data: this.format(type == 'combined'
? sum(this.stats.notes.local.diffs.normal, this.stats.notes.remote.diffs.normal)
: this.stats.notes[type].diffs.normal
)
}]
};
},
notesTotalChart(): any {
return {
series: [{
name: 'Combined',
data: this.format(sum(this.stats.notes.local.total, this.stats.notes.remote.total))
}, {
name: 'Local',
data: this.format(this.stats.notes.local.total)
}, {
name: 'Remote',
data: this.format(this.stats.notes.remote.total)
}]
};
},
usersChart(total: boolean): any {
return {
series: [{
name: 'Combined',
data: this.format(total
? sum(this.stats.users.local.total, this.stats.users.remote.total)
: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec), this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
)
}, {
name: 'Local',
data: this.format(total
? this.stats.users.local.total
: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec))
)
}, {
name: 'Remote',
data: this.format(total
? this.stats.users.remote.total
: sum(this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
)
}]
};
},
driveChart(): any {
return {
series: [{
name: 'All',
data: this.format(
sum(
this.stats.drive.local.incSize,
negate(this.stats.drive.local.decSize),
this.stats.drive.remote.incSize,
negate(this.stats.drive.remote.decSize)
)
)
}, {
name: 'Local +',
data: this.format(this.stats.drive.local.incSize)
}, {
name: 'Local -',
data: this.format(negate(this.stats.drive.local.decSize))
}, {
name: 'Remote +',
data: this.format(this.stats.drive.remote.incSize)
}, {
name: 'Remote -',
data: this.format(negate(this.stats.drive.remote.decSize))
}]
};
},
driveTotalChart(): any {
return {
series: [{
name: 'Combined',
data: this.format(sum(this.stats.drive.local.totalSize, this.stats.drive.remote.totalSize))
}, {
name: 'Local',
data: this.format(this.stats.drive.local.totalSize)
}, {
name: 'Remote',
data: this.format(this.stats.drive.remote.totalSize)
}]
};
},
driveFilesChart(): any {
return {
series: [{
name: 'All',
data: this.format(
sum(
this.stats.drive.local.incCount,
negate(this.stats.drive.local.decCount),
this.stats.drive.remote.incCount,
negate(this.stats.drive.remote.decCount)
)
)
}, {
name: 'Local +',
data: this.format(this.stats.drive.local.incCount)
}, {
name: 'Local -',
data: this.format(negate(this.stats.drive.local.decCount))
}, {
name: 'Remote +',
data: this.format(this.stats.drive.remote.incCount)
}, {
name: 'Remote -',
data: this.format(negate(this.stats.drive.remote.decCount))
}]
};
},
driveFilesTotalChart(): any {
return {
series: [{
name: 'Combined',
data: this.format(sum(this.stats.drive.local.totalCount, this.stats.drive.remote.totalCount))
}, {
name: 'Local',
data: this.format(this.stats.drive.local.totalCount)
}, {
name: 'Remote',
data: this.format(this.stats.drive.remote.totalCount)
}]
};
},
networkRequestsChart(): any {
return {
series: [{
name: 'Incoming',
data: this.format(this.stats.network.incomingRequests)
}]
};
},
networkTimeChart(): any {
const data = [];
for (let i = 0; i < limit; i++) {
data.push(this.stats.network.incomingRequests[i] != 0 ? (this.stats.network.totalTime[i] / this.stats.network.incomingRequests[i]) : 0);
}
return {
series: [{
name: 'Avg time',
data: this.format(data)
}]
};
},
networkUsageChart(): any {
return {
series: [{
name: 'Incoming',
data: this.format(this.stats.network.incomingBytes)
}, {
name: 'Outgoing',
data: this.format(this.stats.network.outgoingBytes)
}]
};
},
}
});
</script>
<style lang="stylus" scoped>
.qvgidhudpqhjttdhxubzuyrhyzgslujw
display block
flex 1
padding 32px 24px
padding-bottom 0
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
> header
display flex
margin 0 8px
padding 0 0 8px 0
font-size 1em
color #555
border-bottom solid 1px #eee
> b
margin-right 8px
> *:last-child
margin-left auto
*
&:not(.active)
color var(--primary)
cursor pointer
</style>

View File

@@ -0,0 +1,170 @@
<template>
<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
<div>
<header>
<span>%fa:microchip% CPU <span>{{ cpuP }}%</span></span>
<span v-if="meta">{{ meta.cpu.model }}</span>
</header>
<div ref="cpu"></div>
</div>
<div>
<header>
<span>%fa:memory% MEM <span>{{ memP }}%</span></span>
<span v-if="meta"></span>
</header>
<div ref="mem"></div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as ApexCharts from 'apexcharts';
export default Vue.extend({
props: ['connection'],
data() {
return {
stats: [],
cpuChart: null,
memChart: null,
cpuP: '',
memP: '',
meta: null
};
},
watch: {
stats(stats) {
this.cpuChart.updateSeries([{
data: stats.map((x, i) => ({ x: i, y: x.cpu_usage }))
}]);
this.memChart.updateSeries([{
data: stats.map((x, i) => ({ x: i, y: (x.mem.used / x.mem.total) }))
}]);
}
},
mounted() {
(this as any).os.getMeta().then(meta => {
this.meta = meta;
});
this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog);
this.connection.send('requestLog', {
id: Math.random().toString().substr(2, 8),
length: 200
});
const chartOpts = {
chart: {
type: 'area',
height: 200,
animations: {
dynamicAnimation: {
enabled: false
}
},
toolbar: {
show: false
},
zoom: {
enabled: false
}
},
dataLabels: {
enabled: false
},
grid: {
clipMarkers: false,
},
stroke: {
curve: 'straight',
width: 2
},
tooltip: {
enabled: false
},
series: [{
data: []
}],
xaxis: {
type: 'numeric',
labels: {
show: false
},
tooltip: {
enabled: false
}
},
yaxis: {
show: false,
min: 0,
max: 1
}
};
this.cpuChart = new ApexCharts(this.$refs.cpu, chartOpts);
this.memChart = new ApexCharts(this.$refs.mem, chartOpts);
this.cpuChart.render();
this.memChart.render();
},
beforeDestroy() {
this.connection.off('stats', this.onStats);
this.connection.off('statsLog', this.onStatsLog);
},
methods: {
onStats(stats) {
this.stats.push(stats);
if (this.stats.length > 200) this.stats.shift();
this.cpuP = (stats.cpu_usage * 100).toFixed(0);
this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
},
onStatsLog(statsLog) {
statsLog.reverse().forEach(stats => this.onStats(stats));
}
}
});
</script>
<style lang="stylus" scoped>
.zyknedwtlthezamcjlolyusmipqmjgxz
display flex
> div
display block
flex 1
padding 20px 12px 0 12px
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
&:first-child
margin-right 16px
> header
display flex
padding 0 8px
margin-bottom -16px
color #555
font-size 14px
> span
&:last-child
margin-left auto
opacity 0.7
> span
opacity 0.7
> div
margin-bottom -10px
</style>

View File

@@ -0,0 +1,211 @@
<template>
<div class="obdskegsannmntldydackcpzezagxqfy">
<header v-if="meta">
<p><b>Misskey</b><span>{{ meta.version }}</span></p>
<p><b>Machine</b><span>{{ meta.machine }}</span></p>
<p><b>OS</b><span>{{ meta.os }}</span></p>
<p><b>Node</b><span>{{ meta.node }}</span></p>
<p>%i18n:common.ai-chan-kawaii%</p>
</header>
<div v-if="stats" class="stats">
<div>
<div>
<div>%fa:user%</div>
<div>
<span>%i18n:@accounts%</span>
<b class="primary">{{ stats.originalUsersCount | number }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('users')">%fa:chart-bar R%</span>
</div>
</div>
<div>
<div>
<div>%fa:pencil-alt%</div>
<div>
<span>%i18n:@notes%</span>
<b class="primary">{{ stats.originalNotesCount | number }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('notes')">%fa:chart-bar R%</span>
</div>
</div>
<div>
<div>
<div>%fa:database%</div>
<div>
<span>%i18n:@drive%</span>
<b>{{ stats.driveUsageLocal | bytes }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('drive')">%fa:chart-bar R%</span>
</div>
</div>
<div>
<div>
<div>%fa:hdd R%</div>
<div>
<span>%i18n:@instances%</span>
<b>{{ stats.instances | number }}</b>
</div>
</div>
<div>
<span>%fa:globe% %i18n:@federated%</span>
<span @click="setChartSrc('federation-instances-total')">%fa:chart-bar R%</span>
</div>
</div>
</div>
<div class="charts">
<x-charts ref="charts"/>
</div>
<div class="cpu-memory">
<x-cpu-memory :connection="connection"/>
</div>
<div class="ap">
<x-ap-log/>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XCpuMemory from "./cpu-memory.vue";
import XCharts from "./charts.vue";
import XApLog from "./ap-log.vue";
export default Vue.extend({
components: {
XCpuMemory,
XCharts,
XApLog
},
data() {
return {
stats: null,
connection: null,
meta: null
};
},
created() {
this.connection = (this as any).os.stream.useSharedConnection('serverStats');
(this as any).os.getMeta().then(meta => {
this.meta = meta;
});
(this as any).api('stats').then(stats => {
this.stats = stats;
});
},
beforeDestroy() {
this.connection.dispose();
},
methods: {
setChartSrc(src) {
this.$refs.charts.setSrc(src);
}
}
});
</script>
<style lang="stylus" scoped>
.obdskegsannmntldydackcpzezagxqfy
> header
display flex
margin-bottom 16px
padding-bottom 16px
border-bottom solid 1px #ccc
color #777
font-size 14px
> p
display inline
margin 0 32px 0 0
> b
&:after
content ':'
margin-right 8px
&:last-child
margin-left auto
margin-right 0
> .stats
display flex
justify-content space-between
margin-bottom 16px
> div
flex 1
max-width 300px
margin-right 16px
color var(--text)
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
background var(--face)
border-radius 8px
&:last-child
margin-right 0
> div:first-child
display flex
align-items center
text-align center
&:last-child
margin-right 0
> div:first-child
padding 16px 24px
font-size 28px
> div:last-child
flex 1
padding 16px 32px 16px 0
text-align right
> span
font-size 70%
opacity 0.7
> b
display block
&.primary
color var(--primary)
> div:last-child
display flex
padding 6px 16px
border-top solid 1px #eee
> span
font-size 70%
opacity 0.7
&:last-child
margin-left auto
cursor pointer
> .charts
margin-bottom 16px
> .cpu-memory
margin-bottom 16px
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div>
<ui-card>
<div slot="title">%fa:plus% %i18n:@add-emoji.title%</div>
<section class="fit-top">
<ui-input v-model="name">
<span>%i18n:@add-emoji.name%</span>
<span slot="text">%i18n:@add-emoji.name-desc%</span>
</ui-input>
<ui-input v-model="aliases">
<span>%i18n:@add-emoji.aliases%</span>
<span slot="text">%i18n:@add-emoji.aliases-desc%</span>
</ui-input>
<ui-input v-model="url">
<span>%i18n:@add-emoji.url%</span>
</ui-input>
<ui-button @click="add">%i18n:@add-emoji.add%</ui-button>
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
name: '',
url: '',
aliases: '',
};
},
methods: {
add() {
(this as any).api('admin/add-emoji', {
name: this.name,
url: this.url,
aliases: this.aliases.split(' ')
}).then(() => {
(this as any).os.apis.dialog({ text: `Added` });
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
}
}
});
</script>

View File

@@ -1,8 +1,12 @@
<template>
<div class="jdnqwkzlnxcfftthoybjxrebyolvoucw mk-admin-card">
<header>%i18n:@hided-tags%</header>
<textarea v-model="hidedTags"></textarea>
<button class="ui" @click="save">%i18n:@save%</button>
<div>
<ui-card>
<div slot="title">%i18n:@hided-tags%</div>
<section>
<textarea class="jdnqwkzlnxcfftthoybjxrebyolvoucw" v-model="hidedTags"></textarea>
<ui-button @click="save">%i18n:@save%</ui-button>
</section>
</ui-card>
</div>
</template>
@@ -35,11 +39,8 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
.jdnqwkzlnxcfftthoybjxrebyolvoucw
textarea
width 100%
min-height 300px
width 100%
min-height 300px
</style>

View File

@@ -0,0 +1,195 @@
<template>
<div class="mk-admin">
<nav>
<div class="mi">
<img svg-inline src="../assets/header-icon.svg"/>
</div>
<div class="me">
<img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/>
<p class="name">{{ $store.state.i | userName }}</p>
</div>
<ul>
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:home .fw%%i18n:@dashboard%</li>
<li @click="nav('instance')" :class="{ active: page == 'instance' }">%fa:cog .fw%%i18n:@instance%</li>
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
<li @click="nav('emoji')" :class="{ active: page == 'emoji' }">%fa:grin R .fw%%i18n:@emoji%</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
</ul>
<div class="back-to-misskey">
<a href="/">%fa:arrow-left% %i18n:@back-to-misskey%</a>
</div>
<div class="version">
<small>Misskey {{ version }}</small>
</div>
</nav>
<main>
<div v-show="page == 'dashboard'"><x-dashboard/></div>
<div v-show="page == 'instance'"><x-instance/></div>
<div v-if="page == 'users'"><x-users/></div>
<div v-show="page == 'emoji'"><x-emoji/></div>
<div v-show="page == 'announcements'"><x-announcements/></div>
<div v-show="page == 'hashtags'"><x-hashtags/></div>
<div v-if="page == 'drive'"></div>
<div v-if="page == 'update'"></div>
</main>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { version } from '../../config';
import XDashboard from "./dashboard.vue";
import XInstance from "./instance.vue";
import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue";
import XHashtags from "./hashtags.vue";
import XUsers from "./users.vue";
export default Vue.extend({
components: {
XDashboard,
XInstance,
XEmoji,
XAnnouncements,
XHashtags,
XUsers
},
data() {
return {
page: 'dashboard',
version
};
},
methods: {
nav(page: string) {
this.page = page;
}
}
});
</script>
<style lang="stylus">
.mk-admin
display flex
height 100%
> nav
position fixed
z-index 10000
top 0
left 0
width 250px
height 100vh
overflow auto
background #333
color #fff
> .mi
text-align center
> svg
width 24px
height 82px
vertical-align top
fill #fff
opacity 0.7
> .me
display flex
margin 0 16px 16px 16px
padding 16px 0
align-items center
border-top solid 1px #555
border-bottom solid 1px #555
> .avatar
height 48px
border-radius 100%
vertical-align middle
> .name
margin 0 16px
padding 0
color #fff
overflow hidden
text-overflow ellipsis
white-space nowrap
font-size 15px
> .back-to-misskey
margin 16px 16px 0 16px
padding 0
border-top solid 1px #555
> a
display block
padding 16px 4px
color inherit
text-decoration none
color #eee
font-size 15px
&:hover
color #fff
> [data-fa]
margin-right 6px
> .version
margin 0 16px 16px 16px
padding-top 16px
border-top solid 1px #555
text-align center
> small
opacity 0.7
> ul
margin 0
padding 0
list-style none
font-size 15px
> li
display block
padding 10px 16px
margin 0
cursor pointer
user-select none
color #eee
transition margin-left 0.2s ease
&:hover
color #fff
> [data-fa]
margin-right 6px
&.active
margin-left 8px
color var(--primary) !important
&:after
content ""
display block
position absolute
top 0
right 0
bottom 0
margin auto 0
height 0
border-top solid 16px transparent
border-right solid 16px var(--bg)
border-bottom solid 16px transparent
border-left solid 16px transparent
> main
width 100%
padding 32px 32px 32px calc(32px + 250px)
max-width 1300px
</style>

View File

@@ -0,0 +1,62 @@
<template>
<div>
<ui-card>
<div slot="title">%i18n:@banner-url%</div>
<section class="fit-top">
<ui-input v-model="bannerUrl"/>
<ui-button @click="updateMeta">%i18n:@save%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@disable-registration%</div>
<section>
<input type="checkbox" v-model="disableRegistration" @change="updateMeta">
<button class="ui" @click="invite">%i18n:@invite%</button>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@disable-local-timeline%</div>
<section>
<input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
disableRegistration: false,
disableLocalTimeline: false,
bannerUrl: null,
inviteCode: null,
};
},
methods: {
invite() {
(this as any).api('admin/invite').then(x => {
this.inviteCode = x.code;
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
},
updateMeta() {
(this as any).api('admin/update-meta', {
disableRegistration: this.disableRegistration,
disableLocalTimeline: this.disableLocalTimeline,
bannerUrl: this.bannerUrl
}).then(() => {
(this as any).os.apis.dialog({ text: `Saved` });
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
}
}
});
</script>

View File

@@ -0,0 +1,129 @@
<template>
<div>
<ui-card>
<div slot="title">%i18n:@verify-user%</div>
<section class="fit-top">
<ui-input v-model="verifyUsername" type="text">
<span slot="prefix">@</span>
</ui-input>
<ui-button @click="verifyUser" :disabled="verifying">%i18n:@verify%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@unverify-user%</div>
<section class="fit-top">
<ui-input v-model="unverifyUsername" type="text">
<span slot="prefix">@</span>
</ui-input>
<ui-button @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@suspend-user%</div>
<section class="fit-top">
<ui-input v-model="suspendUsername" type="text">
<span slot="prefix">@</span>
</ui-input>
<ui-button @click="suspendUser" :disabled="suspending">%i18n:@suspend%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@unsuspend-user%</div>
<section class="fit-top">
<ui-input v-model="unsuspendUsername" type="text">
<span slot="prefix">@</span>
</ui-input>
<ui-button @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</ui-button>
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import parseAcct from "../../../../misc/acct/parse";
export default Vue.extend({
data() {
return {
verifyUsername: null,
verifying: false,
unverifyUsername: null,
unverifying: false,
suspendUsername: null,
suspending: false,
unsuspendUsername: null,
unsuspending: false
};
},
methods: {
async verifyUser() {
this.verifying = true;
const process = async () => {
const user = await (this as any).os.api('users/show', parseAcct(this.verifyUsername));
await (this as any).os.api('admin/verify-user', { userId: user.id });
(this as any).os.apis.dialog({ text: '%i18n:@verified%' });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.verifying = false;
},
async unverifyUser() {
this.unverifying = true;
const process = async () => {
const user = await (this as any).os.api('users/show', parseAcct(this.unverifyUsername));
await (this as any).os.api('admin/unverify-user', { userId: user.id });
(this as any).os.apis.dialog({ text: '%i18n:@unverified%' });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.unverifying = false;
},
async suspendUser() {
this.suspending = true;
const process = async () => {
const user = await (this as any).os.api('users/show', parseAcct(this.suspendUsername));
await (this as any).os.api('admin/suspend-user', { userId: user.id });
(this as any).os.apis.dialog({ text: '%i18n:@suspended%' });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.suspending = false;
},
async unsuspendUser() {
this.unsuspending = true;
const process = async () => {
const user = await (this as any).os.api('users/show', parseAcct(this.unsuspendUsername));
await (this as any).os.api('admin/unsuspend-user', { userId: user.id });
(this as any).os.apis.dialog({ text: '%i18n:@unsuspended%' });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.unsuspending = false;
}
}
});
</script>

View File

@@ -46,6 +46,7 @@
if (`${url.pathname}/`.startsWith('/docs/')) app = 'docs';
if (`${url.pathname}/`.startsWith('/dev/')) app = 'dev';
if (`${url.pathname}/`.startsWith('/auth/')) app = 'auth';
if (`${url.pathname}/`.startsWith('/admin/')) app = 'admin';
//#endregion
//#region Detect the user language

View File

@@ -1,5 +1,5 @@
import MiOS from '../../mios';
import { version as current } from '../../config';
import { clientVersion as current } from '../../config';
export default async function(mios: MiOS, force = false, silent = false) {
const meta = await mios.getMeta(force);

View File

@@ -14,9 +14,10 @@
</ol>
<ol class="emojis" ref="suggests" v-if="emojis.length > 0">
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
<span class="emoji">{{ emoji.emoji }}</span>
<span class="emoji" v-if="emoji.url"><img :src="emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else>{{ emoji.emoji }}</span>
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
<span class="alias" v-if="emoji.alias">({{ emoji.alias }})</span>
<span class="alias" v-if="emoji.aliasOf">({{ emoji.aliasOf }})</span>
</li>
</ol>
</div>
@@ -27,14 +28,21 @@ import Vue from 'vue';
import * as emojilib from 'emojilib';
import contains from '../../../common/scripts/contains';
type EmojiDef = {
emoji: string;
name: string;
aliasOf?: string;
url?: string;
};
const lib = Object.entries(emojilib.lib).filter((x: any) => {
return x[1].category != 'flags';
});
const emjdb = lib.map((x: any) => ({
const emjdb: EmojiDef[] = lib.map((x: any) => ({
emoji: x[1].char,
name: x[0],
alias: null
aliasOf: null
}));
lib.forEach((x: any) => {
@@ -43,7 +51,7 @@ lib.forEach((x: any) => {
emjdb.push({
emoji: x[1].char,
name: k,
alias: x[0]
aliasOf: x[0]
});
});
}
@@ -61,7 +69,8 @@ export default Vue.extend({
hashtags: [],
emojis: [],
select: -1,
emojilib
emojilib,
emojiDb: [] as EmojiDef[]
}
},
@@ -90,6 +99,34 @@ export default Vue.extend({
},
mounted() {
//#region Construct Emoji DB
const customEmojis = (this.os.getMetaSync() || { emojis: [] }).emojis || [];
const emojiDefinitions: EmojiDef[] = [];
customEmojis.forEach(x => {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url
});
if (x.aliases) {
x.aliases.forEach(alias => {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url
});
});
}
});
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
this.emojiDb = emojiDefinitions.concat(emjdb);
//#endregion
this.textarea.addEventListener('keydown', this.onKeydown);
Array.from(document.querySelectorAll('body *')).forEach(el => {
@@ -169,22 +206,25 @@ export default Vue.extend({
}
} else if (this.type == 'emoji') {
const matched = [];
emjdb.some(x => {
if (x.name.indexOf(this.q) == 0 && !x.alias && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30;
const max = 30;
this.emojiDb.some(x => {
if (x.name.startsWith(this.q) && !x.aliasOf && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
if (matched.length < 30) {
emjdb.some(x => {
if (x.name.indexOf(this.q) == 0 && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30;
if (matched.length < max) {
this.emojiDb.some(x => {
if (x.name.startsWith(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
}
if (matched.length < 30) {
emjdb.some(x => {
if (x.name.indexOf(this.q) > -1 && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30;
if (matched.length < max) {
this.emojiDb.some(x => {
if (x.name.includes(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
}
this.emojis = matched;
}
},
@@ -340,6 +380,10 @@ export default Vue.extend({
margin 0 4px 0 0
width 24px
> img
width 24px
vertical-align bottom
.name
color var(--autocompleteItemText)

View File

@@ -1,5 +1,5 @@
<template>
<a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="View source on Github">
<a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="View source on GitHub">
<svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path>

View File

@@ -3,6 +3,7 @@ import Vue from 'vue';
import muteAndBlock from './mute-and-block.vue';
import error from './error.vue';
import apiSettings from './api-settings.vue';
import passwordSettings from './password-settings.vue';
import driveSettings from './drive-settings.vue';
import profileEditor from './profile-editor.vue';
import noteSkeleton from './note-skeleton.vue';
@@ -41,6 +42,7 @@ import Reversi from './games/reversi/reversi.vue';
import welcomeTimeline from './welcome-timeline.vue';
import uiInput from './ui/input.vue';
import uiButton from './ui/button.vue';
import uiButtonGroup from './ui/button-group.vue';
import uiCard from './ui/card.vue';
import uiForm from './ui/form.vue';
import uiTextarea from './ui/textarea.vue';
@@ -54,6 +56,7 @@ import formRadio from './ui/form/radio.vue';
Vue.component('mk-mute-and-block', muteAndBlock);
Vue.component('mk-error', error);
Vue.component('mk-api-settings', apiSettings);
Vue.component('mk-password-settings', passwordSettings);
Vue.component('mk-drive-settings', driveSettings);
Vue.component('mk-profile-editor', profileEditor);
Vue.component('mk-note-skeleton', noteSkeleton);
@@ -92,6 +95,7 @@ Vue.component('mk-reversi', Reversi);
Vue.component('mk-welcome-timeline', welcomeTimeline);
Vue.component('ui-input', uiInput);
Vue.component('ui-button', uiButton);
Vue.component('ui-button-group', uiButtonGroup);
Vue.component('ui-card', uiCard);
Vue.component('ui-form', uiForm);
Vue.component('ui-textarea', uiTextarea);

View File

@@ -3,7 +3,6 @@ import * as emojilib from 'emojilib';
import { length } from 'stringz';
import parse from '../../../../../mfm/parse';
import getAcct from '../../../../../misc/acct/render';
import { url } from '../../../config';
import MkUrl from './url.vue';
import MkGoogle from './google.vue';
import { concat } from '../../../../../prelude/array';
@@ -25,6 +24,9 @@ export default Vue.component('misskey-flavored-markdown', {
i: {
type: Object,
default: null
},
customEmojis: {
required: false,
}
},
@@ -186,6 +188,22 @@ export default Vue.component('misskey-flavored-markdown', {
}
case 'emoji': {
//#region カスタム絵文字
if (this.customEmojis != null) {
const customEmoji = this.customEmojis.find(e => e.name == token.emoji || (e.aliases || []).includes(token.emoji));
if (customEmoji) {
return [createElement('img', {
attrs: {
src: customEmoji.url,
alt: token.emoji,
title: token.emoji,
style: 'height: 2.5em; vertical-align: middle;'
}
})];
}
}
//#endregion
const emoji = emojilib.lib[token.emoji];
return [createElement('span', emoji ? emoji.char : token.content)];
}

View File

@@ -4,9 +4,7 @@
<section>
<header>%i18n:@mute%</header>
<ui-info v-if="!muteFetching && mute.length == 0">
<p>%i18n:@no-muted-users%</p>
</ui-info>
<ui-info v-if="!muteFetching && mute.length == 0">%i18n:@no-muted-users%</ui-info>
<div class="users" v-if="mute.length != 0">
<div v-for="user in mute" :key="user.id">
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>
@@ -16,9 +14,7 @@
<section>
<header>%i18n:@block%</header>
<ui-info v-if="!blockFetching && block.length == 0">
<p>%i18n:@no-blocked-users%</p>
</ui-info>
<ui-info v-if="!blockFetching && block.length == 0">%i18n:@no-blocked-users%</ui-info>
<div class="users" v-if="block.length != 0">
<div v-for="user in block" :key="user.id">
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>

View File

@@ -0,0 +1,21 @@
<template>
<div class="pfzekjfwkwvadvlujpdnnxfggqgqjoze">
<slot></slot>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({});
</script>
<style lang="stylus" scoped>
.pfzekjfwkwvadvlujpdnnxfggqgqjoze
display flex
> *
flex 1
&:not(:last-child)
margin-right 16px
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div class="ymxyweixqwsxauxldgpvecjepnwxbylu" :class="{ warn }">
<i v-if="warn">%fa:exclamation-triangle%</i>
<i v-else>%fa:info-circle%</i>
<slot></slot>
</div>
</template>
@@ -23,11 +24,20 @@ export default Vue.extend({
margin 16px 0
padding 16px
font-size 90%
> i
margin-right 4px
background var(--infoBg)
color var(--infoFg)
&.warn
background var(--infoWarnBg)
color var(--infoWarnFg)
&:first-child
margin-top 0
&:last-child
margin-bottom 0
> i
margin-right 4px
</style>

View File

@@ -14,7 +14,7 @@
</div>
</header>
<div class="text">
<misskey-flavored-markdown v-if="note.text" :text="note.text"/>
<misskey-flavored-markdown v-if="note.text" :text="note.text" :customEmojis="p.emojis"/>
</div>
</div>
</div>

View File

@@ -222,13 +222,15 @@ class Autocomplete {
const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
const after = source.substr(caret);
if (value.startsWith(':')) value = value + ' ';
// 挿入
this.text = trimmedBefore + value + after;
// キャレットを戻す
this.vm.$nextTick(() => {
this.textarea.focus();
const pos = trimmedBefore.length + 1;
const pos = trimmedBefore.length + (value.startsWith(':') ? value.length : 1);
this.textarea.setSelectionRange(pos, pos);
});
}

View File

@@ -1,6 +1,7 @@
import Vue from 'vue';
Vue.filter('bytes', (v, digits = 0) => {
if (v == null) return '?';
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (v == 0) return '0';
const isMinus = v < 0;

View File

@@ -1,5 +1,6 @@
import Vue from 'vue';
Vue.filter('number', (n) => {
if (n == null) return 'N/A';
return n.toLocaleString();
});

View File

@@ -3,7 +3,7 @@
</template>
<script lang="ts">
import { version, codename } from '../../../config';
import { clientVersion as version, codename } from '../../../config';
import define from '../../../common/define-widget';
export default define({
name: 'version'

View File

@@ -3,6 +3,7 @@ declare const _LANGS_: string;
declare const _THEME_COLOR_: string;
declare const _COPYRIGHT_: string;
declare const _VERSION_: string;
declare const _CLIENT_VERSION_: string;
declare const _CODENAME_: string;
declare const _ENV_: string;
@@ -18,5 +19,6 @@ export const langs = _LANGS_;
export const themeColor = _THEME_COLOR_;
export const copyright = _COPYRIGHT_;
export const version = _VERSION_;
export const clientVersion = _CLIENT_VERSION_;
export const codename = _CODENAME_;
export const env = _ENV_;

View File

@@ -23,7 +23,6 @@ import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue';
import MkHome from './views/pages/home.vue';
import MkDeck from './views/pages/deck/deck.vue';
import MkAdmin from './views/pages/admin/admin.vue';
import MkStats from './views/pages/stats/stats.vue';
import MkUser from './views/pages/user/user.vue';
import MkFavorites from './views/pages/favorites.vue';
@@ -57,7 +56,6 @@ init(async (launch) => {
{ path: '/', name: 'index', component: MkIndex },
{ path: '/home', name: 'home', component: MkHome },
{ path: '/deck', name: 'deck', component: MkDeck },
{ path: '/admin', name: 'admin', component: MkAdmin },
{ path: '/stats', name: 'stats', component: MkStats },
{ path: '/i/customize-home', component: MkHomeCustomize },
{ path: '/i/favorites', component: MkFavorites },

View File

@@ -32,9 +32,21 @@ export default Vue.extend({
this.data.forEach(d => d.total = d.notes + d.replies + d.renotes);
const peak = Math.max.apply(null, this.data.map(d => d.total));
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const day = now.getDate();
let x = 0;
this.data.slice().reverse().forEach(d => {
this.data.slice().reverse().forEach((d, i) => {
d.x = x;
const date = new Date(year, month, day - i);
d.date = {
year: date.getFullYear(),
month: date.getMonth(),
day: date.getDate()
};
d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
d.v = peak == 0 ? 0 : d.total / (peak / 2);

View File

@@ -43,11 +43,17 @@ export default Vue.extend({
};
},
mounted() {
(this as any).api('aggregation/users/activity', {
(this as any).api('charts/user/notes', {
userId: this.user.id,
limit: 20 * 7
span: 'day',
limit: 7 * 20
}).then(activity => {
this.activity = activity;
this.activity = activity.diffs.normal.map((_, i) => ({
total: activity.diffs.normal[i] + activity.diffs.reply[i] + activity.diffs.renote[i],
notes: activity.diffs.normal[i],
replies: activity.diffs.reply[i],
renotes: activity.diffs.renote[i]
}));
this.fetching = false;
});
},

View File

@@ -45,7 +45,7 @@
<div class="text">
<span v-if="p.isHidden" style="opacity: 0.5">%i18n:@private%</span>
<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :customEmojis="p.emojis" />
</div>
<div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.files" :raw="true"/>

View File

@@ -34,7 +34,7 @@
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">%i18n:@private%</span>
<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text"/>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote">RN:</a>
</div>
<div class="files" v-if="appearNote.files.length > 0">

View File

@@ -1,8 +1,6 @@
<template>
<div class="root">
<div class="none ui info" v-if="!fetching && apps.length == 0">
<p>%fa:info-circle%%i18n:@no-apps%</p>
</div>
<ui-info v-if="!fetching && apps.length == 0">%i18n:@no-apps%</ui-info>
<div class="apps" v-if="apps.length != 0">
<div v-for="app in apps">
<p><b>{{ app.name }}</b></p>

View File

@@ -214,7 +214,7 @@
<ui-card class="password" v-show="page == 'security'">
<div slot="title">%fa:unlock-alt% %i18n:@password%</div>
<section>
<x-password/>
<mk-password-settings/>
</section>
</ui-card>
@@ -286,17 +286,15 @@
<script lang="ts">
import Vue from 'vue';
import XPassword from './settings.password.vue';
import X2fa from './settings.2fa.vue';
import XApps from './settings.apps.vue';
import XSignins from './settings.signins.vue';
import XTags from './settings.tags.vue';
import { url, langs, version } from '../../../config';
import { url, langs, clientVersion as version } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update';
export default Vue.extend({
components: {
XPassword,
X2fa,
XApps,
XSignins,

View File

@@ -4,7 +4,7 @@
<span v-if="note.isHidden" style="opacity: 0.5">%i18n:@private%</span>
<span v-if="note.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
<a class="reply" v-if="note.replyId">%fa:reply%</a>
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i" :customEmojis="note.emojis"/>
<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RN: ...</a>
</div>
<details v-if="note.files.length > 0">

View File

@@ -1,52 +0,0 @@
<template>
<div class="qldxjjsrseehkusjuoooapmsprvfrxyl mk-admin-card">
<header>%i18n:@announcements%</header>
<textarea v-model="broadcasts" placeholder='[ { "title": "Title1", "text": "Text1" }, { "title": "Title2", "text": "Text2" } ]'></textarea>
<button class="ui" @click="save">%i18n:@save%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data() {
return {
broadcasts: '',
};
},
created() {
(this as any).os.getMeta().then(meta => {
this.broadcasts = JSON.stringify(meta.broadcasts, null, ' ');
});
},
methods: {
save() {
let json;
try {
json = JSON.parse(this.broadcasts);
} catch (e) {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
return;
}
(this as any).api('admin/update-meta', {
broadcasts: json
}).then(() => {
(this as any).os.apis.dialog({ text: `Saved` });
}.catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
}
}
});
</script>
<style lang="stylus" scoped>
.qldxjjsrseehkusjuoooapmsprvfrxyl
textarea
width 100%
min-height 300px
</style>

View File

@@ -1,137 +0,0 @@
<template>
<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<defs>
<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask :id="cpuMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
<polygon
:points="cpuPolygonPoints"
fill="#fff"
fill-opacity="0.5"/>
<polyline
:points="cpuPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"/>
</mask>
</defs>
<rect
x="0" y="0"
:width="viewBoxX" :height="viewBoxY"
:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"/>
<text x="1" y="12">CPU <tspan>{{ cpuP }}%</tspan></text>
</svg>
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
<defs>
<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask :id="memMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
<polygon
:points="memPolygonPoints"
fill="#fff"
fill-opacity="0.5"/>
<polyline
:points="memPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"/>
</mask>
</defs>
<rect
x="0" y="0"
:width="viewBoxX" :height="viewBoxY"
:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"/>
<text x="1" y="12">MEM <tspan>{{ memP }}%</tspan></text>
</svg>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as uuid from 'uuid';
export default Vue.extend({
props: ['connection'],
data() {
return {
viewBoxX: 200,
viewBoxY: 70,
stats: [],
cpuGradientId: uuid(),
cpuMaskId: uuid(),
memGradientId: uuid(),
memMaskId: uuid(),
cpuPolylinePoints: '',
memPolylinePoints: '',
cpuPolygonPoints: '',
memPolygonPoints: '',
cpuP: '',
memP: ''
};
},
mounted() {
this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog);
this.connection.send('requestLog', {
id: Math.random().toString().substr(2, 8),
length: 200
});
},
beforeDestroy() {
this.connection.off('stats', this.onStats);
this.connection.off('statsLog', this.onStatsLog);
},
methods: {
onStats(stats) {
this.stats.push(stats);
if (this.stats.length > 200) this.stats.shift();
const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu_usage) * this.viewBoxY]);
const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.used / s.mem.total)) * this.viewBoxY]);
this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.cpuPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.memPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
this.cpuP = (stats.cpu_usage * 100).toFixed(0);
this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
},
onStatsLog(statsLog) {
statsLog.reverse().forEach(stats => this.onStats(stats));
}
}
});
</script>
<style lang="stylus" scoped>
.zyknedwtlthezamcjlolyusmipqmjgxz
> svg
display block
width 50%
float left
&:first-child
padding-right 5px
&:last-child
padding-left 5px
> text
font-size 10px
fill var(--chartCaption)
> tspan
opacity 0.5
&:after
content ""
display block
clear both
</style>

View File

@@ -1,135 +0,0 @@
<template>
<div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card">
<header>%i18n:@dashboard%</header>
<div v-if="stats" class="stats">
<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>
<div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div>
<div><b>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div>
<div><span>%fa:pencil-alt% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div>
</div>
<div class="cpu-memory">
<x-cpu-memory :connection="connection"/>
</div>
<div v-if="this.$store.state.i && this.$store.state.i.isAdmin" class="form">
<div>
<label>
<p>%i18n:@banner-url%</p>
<input v-model="bannerUrl">
</label>
<button class="ui" @click="updateMeta">%i18n:@save%</button>
</div>
<div>
<label>
<input type="checkbox" v-model="disableRegistration" @change="updateMeta">
<span>%i18n:@disableRegistration%</span>
</label>
<button class="ui" @click="invite">%i18n:@invite%</button>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
</div>
<div>
<label>
<input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
<span>%i18n:@disableLocalTimeline%</span>
</label>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import XCpuMemory from "./admin.cpu-memory.vue";
export default Vue.extend({
components: {
XCpuMemory
},
data() {
return {
stats: null,
disableRegistration: false,
disableLocalTimeline: false,
bannerUrl: null,
inviteCode: null,
connection: null
};
},
created() {
this.connection = (this as any).os.stream.useSharedConnection('serverStats');
(this as any).os.getMeta().then(meta => {
this.disableRegistration = meta.disableRegistration;
this.disableLocalTimeline = meta.disableLocalTimeline;
this.bannerUrl = meta.bannerUrl;
});
(this as any).api('stats').then(stats => {
this.stats = stats;
});
},
beforeDestroy() {
this.connection.dispose();
},
methods: {
invite() {
(this as any).api('admin/invite').then(x => {
this.inviteCode = x.code;
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
},
updateMeta() {
(this as any).api('admin/update-meta', {
disableRegistration: this.disableRegistration,
disableLocalTimeline: this.disableLocalTimeline,
bannerUrl: this.bannerUrl
}).then(() => {
(this as any).os.apis.dialog({ text: `Saved` });
}).catch(e => {
(this as any).os.apis.dialog({ text: `Failed ${e}` });
});
}
}
});
</script>
<style lang="stylus" scoped>
.obdskegsannmntldydackcpzezagxqfy
> .stats
display flex
justify-content center
margin-bottom 16px
padding 16px
border solid 1px #eee
border-radius 8px
> div
flex 1
text-align center
> *:first-child
display block
color var(--primary)
> *:last-child
font-size 70%
> .cpu-memory
margin-bottom 16px
padding 16px
border solid 1px #eee
border-radius: 8px
> .form
> div
padding 16px
border-bottom solid 1px #eee
</style>

View File

@@ -1,57 +0,0 @@
<template>
<div class="mk-admin-card">
<header>%i18n:@suspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="suspendUser" :disabled="suspending">%i18n:@suspend%</button>
</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 process = async () => {
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 as any).os.apis.dialog({ text: "%i18n:@suspended%" });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.suspending = false;
}
}
});
</script>
<style lang="stylus" scoped>
header
margin 10px 0
button
margin 16px 0
</style>

View File

@@ -1,58 +0,0 @@
<template>
<div class="mk-admin-card">
<header>%i18n:@unsuspend-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</button>
</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 process = async () => {
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 as any).os.apis.dialog({ text: "%i18n:@unsuspended%" });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.unsuspending = false;
}
}
});
</script>
<style lang="stylus" scoped>
header
margin 10px 0
button
margin 16px 0
</style>

View File

@@ -1,57 +0,0 @@
<template>
<div class="mk-admin-card">
<header>%i18n:@unverify-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import parseAcct from "../../../../../../misc/acct/parse";
export default Vue.extend({
data() {
return {
username: null,
unverifying: false
};
},
methods: {
async unverifyUser() {
this.unverifying = true;
const process = async () => {
const user = await (this as any).os.api(
"users/show",
parseAcct(this.username)
);
await (this as any).os.api("admin/unverify-user", {
userId: user.id
});
(this as any).os.apis.dialog({ text: "%i18n:@unverified%" });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.unverifying = false;
}
}
});
</script>
<style lang="stylus" scoped>
header
margin 10px 0
button
margin 16px 0
</style>

View File

@@ -1,57 +0,0 @@
<template>
<div class="mk-admin-card">
<header>%i18n:@verify-user%</header>
<input v-model="username" type="text" class="ui"/>
<button class="ui" @click="verifyUser" :disabled="verifying">%i18n:@verify%</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import parseAcct from "../../../../../../misc/acct/parse";
export default Vue.extend({
data() {
return {
username: null,
verifying: false
};
},
methods: {
async verifyUser() {
this.verifying = true;
const process = async () => {
const user = await (this as any).os.api(
"users/show",
parseAcct(this.username)
);
await (this as any).os.api("admin/verify-user", {
userId: user.id
});
(this as any).os.apis.dialog({ text: "%i18n:@verified%" });
};
await process().catch(e => {
(this as any).os.apis.dialog({ text: `Failed: ${e}` });
});
this.verifying = false;
}
}
});
</script>
<style lang="stylus" scoped>
header
margin 10px 0
button
margin 16px 0
</style>

View File

@@ -1,140 +0,0 @@
<template>
<div class="mk-admin">
<nav>
<ul>
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
@click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
@click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
@click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
</ul>
</nav>
<main>
<div v-show="page == 'dashboard'">
<x-dashboard/>
<x-charts/>
</div>
<div v-show="page == 'announcements'">
<x-announcements/>
</div>
<div v-show="page == 'hashtags'">
<x-hashtags/>
</div>
<div v-if="page == 'users'">
<x-suspend-user/>
<x-unsuspend-user/>
<x-verify-user/>
<x-unverify-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 XAnnouncements from "./admin.announcements.vue";
import XHashtags from "./admin.hashtags.vue";
import XSuspendUser from "./admin.suspend-user.vue";
import XUnsuspendUser from "./admin.unsuspend-user.vue";
import XVerifyUser from "./admin.verify-user.vue";
import XUnverifyUser from "./admin.unverify-user.vue";
import XCharts from "../../components/charts.vue";
export default Vue.extend({
components: {
XDashboard,
XAnnouncements,
XHashtags,
XSuspendUser,
XUnsuspendUser,
XVerifyUser,
XUnverifyUser,
XCharts
},
data() {
return {
page: 'dashboard'
};
},
methods: {
nav(page: string) {
this.page = page;
}
}
});
</script>
<style lang="stylus">
.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 var(--primary) !important
> main
width 100%
padding 16px 32px
> div
> div
max-width 800px
.mk-admin-card
padding 32px
background #fff
box-shadow 0 2px 8px rgba(#000, 0.1)
&:not(:last-child)
margin-bottom 16px
> header
margin 0 0 1em 0
padding 0 0 8px 0
font-size 1em
color #555
border-bottom solid 1px #eee
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow, active, isStacked, draghover, dragging, dropready }"
@dragenter.prevent.stop="onDragenter"
@dragover.prevent.stop="onDragover"
@dragleave="onDragleave"
@drop.prevent.stop="onDrop"
v-hotkey="keymap">
@@ -269,7 +269,7 @@ export default Vue.extend({
this.dragging = false;
},
onDragenter(e) {
onDragover(e) {
// テンポラリカラムにはドロップさせない
if (this.isTemporaryColumn) {
e.dataTransfer.dropEffect = 'none';

View File

@@ -14,7 +14,7 @@ import VueHotkey from './common/hotkey';
import App from './app.vue';
import checkForUpdate from './common/scripts/check-for-update';
import MiOS, { API } from './mios';
import { version, codename, lang } from './config';
import { clientVersion as version, codename, lang } from './config';
import { builtinThemes, lightTheme, applyTheme } from './theme';
if (localStorage.getItem('theme') == null) {

View File

@@ -4,7 +4,7 @@ import { EventEmitter } from 'eventemitter3';
import * as uuid from 'uuid';
import initStore from './store';
import { apiUrl, version, lang } from './config';
import { apiUrl, clientVersion as version, lang } from './config';
import Progress from './common/scripts/loading';
import Err from './common/views/components/connect-failed.vue';
@@ -510,6 +510,14 @@ export default class MiOS extends EventEmitter {
return promise;
}
/**
* Misskeyのメタ情報を取得します
*/
@autobind
public getMetaSync() {
return this.meta ? this.meta.data : null;
}
/**
* Misskeyのメタ情報を取得します
* @param force キャッシュを無視するか否か
@@ -529,7 +537,9 @@ export default class MiOS extends EventEmitter {
// forceが有効, meta情報を保持していない or 期限切れ
if (force || this.meta == null || Date.now() - this.meta.chachedAt.getTime() > expire) {
this.isMetaFetching = true;
const meta = await this.api('meta');
const meta = await this.api('meta', {
detail: false
});
this.meta = {
data: meta,
chachedAt: new Date()

View File

@@ -1,23 +1,13 @@
<template>
<div class="mk-activity">
<svg v-if="data" ref="canvas" viewBox="0 0 30 1" preserveAspectRatio="none">
<g v-for="(d, i) in data">
<rect width="0.8" :height="d.notesH"
:x="i + 0.1" :y="1 - d.notesH - d.repliesH - d.renotesH"
fill="#41ddde"/>
<rect width="0.8" :height="d.repliesH"
:x="i + 0.1" :y="1 - d.repliesH - d.renotesH"
fill="#f7796c"/>
<rect width="0.8" :height="d.renotesH"
:x="i + 0.1" :y="1 - d.renotesH"
fill="#a1de41"/>
</g>
</svg>
<div ref="chart"></div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as ApexCharts from 'apexcharts';
export default Vue.extend({
props: ['user'],
data() {
@@ -28,19 +18,84 @@ export default Vue.extend({
};
},
mounted() {
(this as any).api('aggregation/users/activity', {
(this as any).api('charts/user/notes', {
userId: this.user.id,
limit: 30
}).then(data => {
data.forEach(d => d.total = d.notes + d.replies + d.renotes);
this.peak = Math.max.apply(null, data.map(d => d.total));
data.forEach(d => {
d.notesH = d.notes / this.peak;
d.repliesH = d.replies / this.peak;
d.renotesH = d.renotes / this.peak;
span: 'day',
limit: 21
}).then(stats => {
const normal = [];
const reply = [];
const renote = [];
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
for (let i = 0; i < 21; i++) {
const x = new Date(y, m, d - i);
normal.push([
x,
stats.diffs.normal[i]
]);
reply.push([
x,
stats.diffs.reply[i]
]);
renote.push([
x,
stats.diffs.renote[i]
]);
}
const chart = new ApexCharts(this.$refs.chart, {
chart: {
type: 'bar',
stacked: true,
height: 100,
sparkline: {
enabled: true
},
},
plotOptions: {
bar: {
columnWidth: '90%',
endingShape: 'rounded'
}
},
grid: {
clipMarkers: false,
padding: {
top: 0,
right: 8,
bottom: 0,
left: 8
}
},
tooltip: {
shared: true,
intersect: false
},
series: [{
name: 'Normal',
data: normal
}, {
name: 'Reply',
data: reply
}, {
name: 'Renote',
data: renote
}],
xaxis: {
type: 'datetime',
crosshairs: {
width: 1,
opacity: 1
}
}
});
data.reverse();
this.data = data;
chart.render();
});
}
});
@@ -51,12 +106,4 @@ export default Vue.extend({
max-width 600px
margin 0 auto
> svg
display block
width 100%
height 80px
> rect
transform-origin center
</style>

View File

@@ -43,7 +43,7 @@
<div class="text">
<span v-if="p.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :customEmojis="p.emojis"/>
</div>
<div class="files" v-if="p.files.length > 0">
<mk-media-list :media-list="p.files" :raw="true"/>

View File

@@ -30,7 +30,7 @@
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text"/>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
</div>
<div class="files" v-if="appearNote.files.length > 0">

View File

@@ -4,7 +4,7 @@
<span v-if="note.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
<span v-if="note.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
<a class="reply" v-if="note.replyId">%fa:reply%</a>
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i" :customEmojis="note.emojis"/>
<a class="rp" v-if="note.renoteId">RN: ...</a>
</div>
<details v-if="note.files.length > 0">

View File

@@ -127,6 +127,13 @@
<mk-api-settings />
<ui-card>
<div slot="title">%fa:unlock-alt% %i18n:@password%</div>
<section>
<mk-password-settings/>
</section>
</ui-card>
<ui-card>
<div slot="title">%fa:sync-alt% %i18n:@update%</div>
@@ -154,7 +161,7 @@
<script lang="ts">
import Vue from 'vue';
import { apiUrl, version, codename, langs } from '../../../config';
import { apiUrl, clientVersion as version, codename, langs } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update';
export default Vue.extend({

View File

@@ -131,6 +131,8 @@
remoteInfoBg: '#42321c',
remoteInfoFg: '#ffbd3e',
infoBg: '#253142',
infoFg: '#fff',
infoWarnBg: '#42321c',
infoWarnFg: '#ffbd3e',

View File

@@ -131,6 +131,8 @@
remoteInfoBg: '#fff0db',
remoteInfoFg: '#573c08',
infoBg: '#e5f5ff',
infoFg: '#72818a',
infoWarnBg: '#fff0db',
infoWarnFg: '#573c08',

View File

@@ -3,9 +3,9 @@
*/
export type TextElementBig = {
type: 'big'
content: string
big: string
type: 'big';
content: string;
big: string;
};
export default function(text: string) {

View File

@@ -3,9 +3,9 @@
*/
export type TextElementBold = {
type: 'bold'
content: string
bold: string
type: 'bold';
content: string;
bold: string;
};
export default function(text: string) {

View File

@@ -5,10 +5,10 @@
import genHtml from '../core/syntax-highlighter';
export type TextElementCode = {
type: 'code'
content: string
code: string
html: string
type: 'code';
content: string;
code: string;
html: string;
};
export default function(text: string) {

View File

@@ -3,13 +3,13 @@
*/
export type TextElementEmoji = {
type: 'emoji'
content: string
emoji: string
type: 'emoji';
content: string;
emoji: 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;
const emoji = match[0];
return {

View File

@@ -3,15 +3,15 @@
*/
export type TextElementHashtag = {
type: 'hashtag'
content: string
hashtag: string
type: 'hashtag';
content: string;
hashtag: string;
};
export default function(text: string, i: number) {
if (!(/^\s#[^\s\.,!\?]+/.test(text) || (i == 0 && /^#[^\s\.,!\?]+/.test(text)))) return null;
export default function(text: string, isBegin: boolean) {
if (!(/^\s#[^\s\.,!\?#]+/.test(text) || (isBegin && /^#[^\s\.,!\?#]+/.test(text)))) return null;
const isHead = text.startsWith('#');
const hashtag = text.match(/^\s?#[^\s\.,!\?]+/)[0];
const hashtag = text.match(/^\s?#[^\s\.,!\?#]+/)[0];
const res: any[] = !isHead ? [{
type: 'text',
content: text[0]

View File

@@ -5,10 +5,10 @@
import genHtml from '../core/syntax-highlighter';
export type TextElementInlineCode = {
type: 'inline-code'
content: string
code: string
html: string
type: 'inline-code';
content: string;
code: string;
html: string;
};
export default function(text: string) {

View File

@@ -3,11 +3,11 @@
*/
export type TextElementLink = {
type: 'link'
content: string
title: string
url: string
silent: boolean
type: 'link';
content: string;
title: string;
url: string;
silent: boolean;
};
export default function(text: string) {

View File

@@ -5,11 +5,11 @@ import parseAcct from '../../../misc/acct/parse';
import { toUnicode } from 'punycode';
export type TextElementMention = {
type: 'mention'
content: string
canonical: string
username: string
host: string
type: 'mention';
content: string;
canonical: string;
username: string;
host: string;
};
export default function(text: string) {

View File

@@ -3,9 +3,9 @@
*/
export type TextElementMotion = {
type: 'motion'
content: string
motion: string
type: 'motion';
content: string;
motion: string;
};
export default function(text: string) {

View File

@@ -3,14 +3,14 @@
*/
export type TextElementQuote = {
type: 'quote'
content: string
quote: string
type: 'quote';
content: string;
quote: string;
};
export default function(text: string, index: number) {
export default function(text: string, isBegin: boolean) {
const match = text.match(/^"([\s\S]+?)\n"/) || text.match(/^\n>([\s\S]+?)(\n\n|$)/) ||
(index == 0 ? text.match(/^>([\s\S]+?)(\n\n|$)/) : null);
(isBegin ? text.match(/^>([\s\S]+?)(\n\n|$)/) : null);
if (!match) return null;

View File

@@ -3,9 +3,9 @@
*/
export type TextElementSearch = {
type: 'search'
content: string
query: string
type: 'search';
content: string;
query: string;
};
export default function(text: string) {

View File

@@ -3,13 +3,13 @@
*/
export type TextElementTitle = {
type: 'title'
content: string
title: string
type: 'title';
content: string;
title: string;
};
export default function(text: string) {
const match = text.match(/^(【|\[)(.+?)(】|])\n/);
export default function(text: string, isBegin: boolean) {
const match = isBegin ? text.match(/^(【|\[)(.+?)(】|])\n/) : text.match(/^\n(【|\[)(.+?)(】|])\n/);
if (!match) return null;
const title = match[0];
return {

View File

@@ -3,9 +3,9 @@
*/
export type TextElementUrl = {
type: 'url'
content: string
url: string
type: 'url';
content: string;
url: string;
};
export default function(text: string) {

View File

@@ -46,7 +46,7 @@ export type TextElement = { type: 'text', content: string }
| TextElementTitle
| TextElementUrl
| TextElementMotion;
export type TextElementProcessor = (text: string, i: number) => TextElement | TextElement[];
export type TextElementProcessor = (text: string, isBegin: boolean) => TextElement | TextElement[];
export default (source: string): TextElement[] => {
if (source == null || source == '') {
@@ -67,7 +67,7 @@ export default (source: string): TextElement[] => {
// パース
while (source != '') {
const parsed = elements.some(el => {
let _tokens = el(source, i);
let _tokens = el(source, i == 0);
if (_tokens) {
if (!Array.isArray(_tokens)) {
_tokens = [_tokens];

View File

@@ -4,23 +4,31 @@ import isObjectId from './is-objectid';
export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
export const isNotAnId = (x: any) => !isAnId(x);
export const transform = (x: string | mongo.ObjectID): mongo.ObjectID => {
if (x == null) return null;
if (isAnId(x) && !isObjectId(x)) {
return new mongo.ObjectID(x);
} else {
return x as mongo.ObjectID;
}
};
export const transformMany = (xs: (string | mongo.ObjectID)[]): mongo.ObjectID[] => {
if (xs == null) return null;
return xs.map(x => transform(x));
};
export type ObjectId = mongo.ObjectID;
/**
* ID
*/
export default class ID extends Context<mongo.ObjectID> {
export default class ID extends Context<string> {
constructor() {
super();
this.transform = v => {
if (isAnId(v) && !isObjectId(v)) {
return new mongo.ObjectID(v);
} else {
return v;
}
};
this.push(v => {
this.push((v: any) => {
if (!isObjectId(v) && isNotAnId(v)) {
return new Error('must-be-an-id');
}

View File

@@ -0,0 +1,20 @@
import { IDriveFile } from '../models/drive-file';
import config from '../config';
export default function(file: IDriveFile, thumbnail = false): string {
if (file == null) return null;
if (file.metadata.withoutChunks) {
if (thumbnail) {
return file.metadata.thumbnailUrl || file.metadata.url;
} else {
return file.metadata.url;
}
} else {
if (thumbnail) {
return `${config.drive_url}/${file._id}?thumbnail`;
} else {
return `${config.drive_url}/${file._id}`;
}
}
}

View File

@@ -22,27 +22,28 @@ export type IApp = {
/**
* Pack an app for API response
*
* @param {any} app
* @param {any} me?
* @param {any} options?
* @return {Promise<any>}
*/
export const pack = (
app: any,
me?: any,
options?: {
detail?: boolean,
includeSecret?: boolean,
includeProfileImageIds?: boolean
}
) => new Promise<any>(async (resolve, reject) => {
const opts = options || {
const opts = Object.assign({
detail: false,
includeSecret: false,
includeProfileImageIds: false
};
}, options);
let _app: any;
const fields = opts.detail ? {} : {
name: true
};
// Populate the app if 'app' is ID
if (isObjectId(app)) {
_app = await App.findOne({
@@ -51,7 +52,7 @@ export const pack = (
} else if (typeof app === 'string') {
_app = await App.findOne({
_id: new mongo.ObjectID(app)
});
}, { fields });
} else {
_app = deepcopy(app);
}

View File

@@ -48,7 +48,9 @@ export const pack = (
delete _blocking._id;
// Populate blockee
_blocking.blockee = await packUser(_blocking.blockeeId, me);
_blocking.blockee = await packUser(_blocking.blockeeId, me, {
detail: true
});
resolve(_blocking);
});

View File

@@ -1,9 +1,9 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import { pack as packFolder } from './drive-folder';
import config from '../config';
import monkDb, { nativeDbConn } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import getDriveFileUrl from '../misc/get-drive-file-url';
const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
DriveFile.createIndex('md5');
@@ -33,7 +33,14 @@ export type IMetadata = {
thumbnailUrl?: string;
src?: string;
deletedAt?: Date;
/**
* このファイルの中身データがMongoDB内に保存されているのか否か
* オブジェクトストレージを利用している or リモートサーバーへの直リンクである
* な場合は false になります
*/
withoutChunks?: boolean;
storage?: string;
storageProps?: any;
isSensitive?: boolean;
@@ -128,8 +135,8 @@ export const pack = (
_target = Object.assign(_target, _file.metadata);
_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.url = getDriveFileUrl(_file);
_target.thumbnailUrl = getDriveFileUrl(_file, true);
_target.isRemote = _file.metadata.isRemote;
if (_target.properties == null) _target.properties = {};
@@ -156,6 +163,7 @@ export const pack = (
delete _target.storage;
delete _target.storageProps;
delete _target.isRemote;
delete _target._user;
resolve(_target);
});

27
src/models/emoji.ts Normal file
View File

@@ -0,0 +1,27 @@
import db from '../db/mongodb';
const Emoji = db.get<IEmoji>('emoji');
Emoji.createIndex('name');
Emoji.createIndex('host');
Emoji.createIndex(['name', 'host'], { unique: true });
export default Emoji;
export type IEmoji = {
name: string;
host: string;
url: string;
aliases?: string[];
updatedAt?: Date;
};
export const packEmojis = async (
host: string,
// MeiTODO: filter
) => {
return await Emoji.find({ host }, {
fields: {
_id: false
}
});
};

View File

@@ -48,7 +48,9 @@ export const pack = (
delete _mute._id;
// Populate mutee
_mute.mutee = await packUser(_mute.muteeId, me);
_mute.mutee = await packUser(_mute.muteeId, me, {
detail: true
});
resolve(_mute);
});

View File

@@ -12,6 +12,7 @@ import { packMany as packFileMany, IDriveFile } from './drive-file';
import Favorite from './favorite';
import Following from './following';
import config from '../config';
import { packEmojis } from './emoji';
const Note = db.get<INote>('notes');
Note.createIndex('uri', { sparse: true, unique: true });
@@ -228,6 +229,11 @@ export const pack = async (
const id = _note._id;
// _note._userを消す前か、_note.userを解決した後でないとホストがわからない
if (_note._user) {
_note.emojis = packEmojis(_note._user.host);
}
// Rename _id to id
_note.id = _note._id;
delete _note._id;
@@ -259,11 +265,6 @@ export const pack = async (
// When requested a detailed note data
if (opts.detail) {
//#region 重いので廃止
_note.prev = null;
_note.next = null;
//#endregion
if (_note.replyId) {
// Populate reply to note
_note.reply = pack(_note.replyId, meId, {

View File

@@ -2,6 +2,8 @@ import * as mongo from 'mongodb';
import db from '../db/mongodb';
const PollVote = db.get<IPollVote>('pollVotes');
PollVote.createIndex('userId');
PollVote.createIndex('noteId');
export default PollVote;
export interface IPollVote {

View File

@@ -155,6 +155,50 @@ export function isValidBirthday(birthday: string): boolean {
}
//#endregion
export async function getRelation(me: mongo.ObjectId, target: mongo.ObjectId) {
const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([
Following.findOne({
followerId: me,
followeeId: target
}),
Following.findOne({
followerId: target,
followeeId: me
}),
FollowRequest.findOne({
followerId: me,
followeeId: target
}),
FollowRequest.findOne({
followerId: target,
followeeId: me
}),
Blocking.findOne({
blockerId: me,
blockeeId: target
}),
Blocking.findOne({
blockerId: target,
blockeeId: me
}),
Mute.findOne({
muterId: me,
muteeId: target
})
]);
return {
isFollowing: following1 !== null,
isStalking: following1 ? following1.stalk : false,
hasPendingFollowRequestFromYou: followReq1 !== null,
hasPendingFollowRequestToYou: followReq2 !== null,
isFollowed: following2 !== null,
isBlocking: toBlocking !== null,
isBlocked: fromBlocked !== null,
isMuted: mute !== null
};
}
/**
* Pack a user for API response
*
@@ -179,13 +223,16 @@ export const pack = (
let _user: any;
const fields = opts.detail ? {
} : {
settings: false,
clientSettings: false,
profile: false,
keywords: false,
domains: false
const fields = opts.detail ? {} : {
name: true,
username: true,
host: true,
avatarColor: true,
avatarUrl: true,
isCat: true,
isBot: true,
isAdmin: true,
isVerified: true
};
// Populate the user if 'user' is ID
@@ -220,6 +267,8 @@ export const pack = (
_user.id = _user._id;
delete _user._id;
delete _user.usernameLower;
if (_user.host == null) {
// Remove private properties
delete _user.keypair;
@@ -227,7 +276,6 @@ export const pack = (
delete _user.token;
delete _user.twoFactorTempSecret;
delete _user.twoFactorSecret;
delete _user.usernameLower;
if (_user.twitter) {
delete _user.twitter.accessToken;
delete _user.twitter.accessTokenSecret;
@@ -250,16 +298,6 @@ export const pack = (
if (_user.avatarUrl == null) {
_user.avatarUrl = `${config.drive_url}/default-avatar.jpg`;
// 互換性のため
if (_user.avatarId) {
_user.avatarUrl = `${config.drive_url}/${_user.avatarId}`;
}
}
// 互換性のため
if (_user.bannerId && _user.bannerUrl == null) {
_user.bannerUrl = `${config.drive_url}/${_user.bannerId}`;
}
if (!meId || !meId.equals(_user.id) || !opts.detail) {
@@ -270,55 +308,16 @@ export const pack = (
}
if (meId && !meId.equals(_user.id) && opts.detail) {
const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([
Following.findOne({
followerId: meId,
followeeId: _user.id
}),
Following.findOne({
followerId: _user.id,
followeeId: meId
}),
FollowRequest.findOne({
followerId: meId,
followeeId: _user.id
}),
FollowRequest.findOne({
followerId: _user.id,
followeeId: meId
}),
Blocking.findOne({
blockerId: meId,
blockeeId: _user.id
}),
Blocking.findOne({
blockerId: _user.id,
blockeeId: meId
}),
Mute.findOne({
muterId: meId,
muteeId: _user.id
})
]);
const relation = await getRelation(meId, _user.id);
// Whether the user is following
_user.isFollowing = following1 !== null;
_user.isStalking = following1 && following1.stalk;
_user.hasPendingFollowRequestFromYou = followReq1 !== null;
_user.hasPendingFollowRequestToYou = followReq2 !== null;
// Whether the user is followed
_user.isFollowed = following2 !== null;
// Whether the user is blocking
_user.isBlocking = toBlocking !== null;
// Whether the user is blocked
_user.isBlocked = fromBlocked !== null;
// Whether the user is muted
_user.isMuted = mute !== null;
_user.isFollowing = relation.isFollowing;
_user.isFollowed = relation.isFollowed;
_user.isStalking = relation.isStalking;
_user.hasPendingFollowRequestFromYou = relation.hasPendingFollowRequestFromYou;
_user.hasPendingFollowRequestToYou = relation.hasPendingFollowRequestToYou;
_user.isBlocking = relation.isBlocking;
_user.isBlocked = relation.isBlocked;
_user.isMuted = relation.isMuted;
}
if (opts.detail) {

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