Compare commits

...

131 Commits

Author SHA1 Message Date
14b16b4733 10.77.0 2019-01-16 14:58:05 +09:00
256c216dfb インスタンス情報ページに各種タイムラインの有効/無効を表示 2019-01-16 14:57:01 +09:00
13cee2b4f5 Resolve #3896 2019-01-16 14:54:14 +09:00
eb45eeb1ae [Client] Resolve #3895 2019-01-16 14:46:54 +09:00
3154350b64 10.76.0 2019-01-16 11:41:40 +09:00
519c9c4499 インスタンス情報ページにユーザー数と投稿数を追加 2019-01-16 03:36:25 +09:00
c2f6b09969 disableLocalTimeline機能を強化
* ストリームだけではなくAPIも無効に
* モデレーターは無効の場合でも見れるように
* グローバルタイムラインも無効に(連合数が少ないインスタンスではグローバルタイムラインは実質的にローカルタイムラインと同一なので)
2019-01-16 02:30:55 +09:00
c8e2b22942 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-01-15 18:28:31 +09:00
f433182c4c Revert "Resolve #3813 (#3814)"
This reverts commit 96515c4544.
2019-01-15 18:28:11 +09:00
957392aaae Update minio requirement from 7.0.2 to 7.0.3 (#3888)
Updates the requirements on [minio](https://github.com/minio/minio-js) to permit the latest version.
- [Release notes](https://github.com/minio/minio-js/releases)
- [Commits](https://github.com/minio/minio-js/commits/7.0.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-15 10:41:16 +09:00
bd8d06e133 Update vue-i18n requirement from 8.6.0 to 8.7.0 (#3889)
Updates the requirements on [vue-i18n](https://github.com/kazupon/vue-i18n) to permit the latest version.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/commits/v8.7.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-15 10:40:04 +09:00
c617b60f70 Correct some weird french translations in the docs. (#3884)
* Correct some weird french translations

* Update docker.fr.md

* Update setup.fr.md

* Update setup.fr.md

* Update docker.fr.md

* Update setup.fr.md
2019-01-14 06:08:33 +09:00
018837db0b Support SVG (#3883)
* Update add-file.ts

* Update package.json

* Revert "Update add-file.ts"

This reverts commit ba0fe83b54a44493447208dfb3cc304a60df6fdd.

* Update add-file.ts

* Update package.json

* Update add-file.ts

* Update add-file.ts

* Create image.svg

* Update api.ts
2019-01-13 18:21:10 +09:00
00d5fdfc13 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-01-12 19:31:03 +09:00
2debb0c2ca Provide instance description in info page 2019-01-12 19:30:56 +09:00
148d6737cc Grammatical Fixes (#3844)
Updated the README to read more naturally for English speakers.
2019-01-12 14:34:00 +09:00
c15cb8d28c Update chalk requirement from 2.4.1 to 2.4.2 (#3855)
Updates the requirements on [chalk](https://github.com/chalk/chalk) to permit the latest version.
- [Release notes](https://github.com/chalk/chalk/releases)
- [Commits](https://github.com/chalk/chalk/commits/v2.4.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-12 14:33:23 +09:00
1d5471db70 Update webpack-cli requirement from 3.1.2 to 3.2.1 (#3850)
Updates the requirements on [webpack-cli](https://github.com/webpack/webpack-cli) to permit the latest version.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-12 14:32:42 +09:00
086b83c1fe Merge pull request #3851 from syuilo/dependabot/npm_and_yarn/eslint-5.12.0
Update eslint requirement from 5.11.1 to 5.12.0
2019-01-12 14:32:29 +09:00
c509e0b86c Update ts-loader requirement from 5.3.1 to 5.3.3 (#3854)
Updates the requirements on [ts-loader](https://github.com/TypeStrong/ts-loader) to permit the latest version.
- [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/commits/v5.3.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-12 14:32:20 +09:00
e8a1ad9823 Update chai-http requirement from 4.2.0 to 4.2.1 (#3856)
Updates the requirements on [chai-http](https://github.com/chaijs/chai-http) to permit the latest version.
- [Release notes](https://github.com/chaijs/chai-http/releases)
- [Changelog](https://github.com/chaijs/chai-http/blob/master/History.md)
- [Commits](https://github.com/chaijs/chai-http/commits/4.2.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-12 14:32:11 +09:00
6446b1cfb1 Update cssnano requirement from 4.1.7 to 4.1.8 (#3880)
Updates the requirements on [cssnano](https://github.com/cssnano/cssnano) to permit the latest version.
- [Release notes](https://github.com/cssnano/cssnano/releases)
- [Commits](https://github.com/cssnano/cssnano/commits/v4.1.8)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-12 14:32:03 +09:00
2b9216c441 Merge pull request #3866 from syuilo/dependabot/npm_and_yarn/@types/mongodb-3.1.18
Update @types/mongodb requirement from 3.1.14 to 3.1.18
2019-01-12 14:31:52 +09:00
28656a701f Merge pull request #3857 from syuilo/dependabot/npm_and_yarn/@types/showdown-1.9.1
Update @types/showdown requirement from 1.9.0 to 1.9.1
2019-01-12 14:31:43 +09:00
cd628eaf54 [MFM] Better hashtag parsing: Ignore trailing colon 2019-01-12 14:10:16 +09:00
3d62bd8007 10.75.0 2019-01-12 13:27:14 +09:00
7ad9560f53 Implement instance info page 2019-01-12 11:27:23 +09:00
c135d02895 Update CHANGELOG.md 2019-01-12 09:42:49 +09:00
0757f67bde [Client] specifiedのアイコンを戻した 2019-01-12 09:40:53 +09:00
c5dc25cb9e Revert "[Client] Renote数の表示を廃止"
This reverts commit d7af18efbd.
2019-01-12 09:38:44 +09:00
0fcf422dec [Client] Improve UI 2019-01-12 09:34:02 +09:00
21e801a325 🎨 2019-01-12 09:17:23 +09:00
183faf3b2a [Client] Resolve #3881 2019-01-12 09:13:35 +09:00
9fc66a2d1e Update terser-webpack-plugin requirement from 1.1.0 to 1.2.1 (#3867)
Updates the requirements on [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) to permit the latest version.
- [Release notes](https://github.com/webpack-contrib/terser-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/terser-webpack-plugin/commits/v1.2.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-11 19:58:16 +09:00
12cf598e6b Fix bug (for return) (#3878) 2019-01-11 17:53:53 +09:00
dd6cd6332c Update CHANGELOG.md 2019-01-11 16:00:09 +09:00
20ee2118ee モデレーターを凍結できないようにする (#3877) 2019-01-11 08:12:10 +09:00
1546160f6a モデレーター登録を解除できるように (#3876) 2019-01-11 08:11:24 +09:00
dd77a6194e Hide NSFW in Photos (#3875) 2019-01-11 08:10:39 +09:00
203fba0216 管理画面でユーザーを状態でフィルタできるように (#3873) 2019-01-11 08:09:44 +09:00
826a2466b7 管理者がサインイン履歴を参照できるツール (#3870)
* 管理者がサインイン履歴を参照できるツール

* remove debug code
2019-01-11 08:07:09 +09:00
273bc6507a ダイレクトを非公開のように使えるようにする (#3869) 2019-01-11 08:06:05 +09:00
2b13969b26 Supports toggle password in SMTP settings (#3868) 2019-01-11 08:05:36 +09:00
2f10ff1a2e Fix style 2019-01-10 19:23:22 +09:00
1f52aea193 Update CHANGELOG.md 2019-01-10 17:53:56 +09:00
0a0e76679e Add manage and docker docs in french and correct mistake in english (#3863) 2019-01-10 10:24:04 +09:00
845f3436cc Change SMTP password field to have password type (#3861) 2019-01-10 10:23:13 +09:00
f6a8c8cf76 Toggle show/hide password (#3865)
* Toggle show/hide password

* hoverでアンダーラインが中途半端に出てダサいので出さないように

* Update signin.vue
2019-01-10 10:22:45 +09:00
53298933e4 Update @types/mongodb requirement from 3.1.14 to 3.1.18
Updates the requirements on [@types/mongodb](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-09 20:16:29 +00:00
af61a7a17f 10.74.0 2019-01-09 15:32:36 +09:00
667ad8fe96 Update CHANGELOG.md 2019-01-09 15:19:00 +09:00
e1cc2394fa Use cached and asynchronous DNS resolver for AP delivery (#3859) 2019-01-09 15:17:54 +09:00
e7cfae3ccb Update @types/showdown requirement from 1.9.0 to 1.9.1
Updates the requirements on [@types/showdown](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-08 20:29:07 +00:00
ebb03113ab Update ts-loader requirement from 5.3.1 to 5.3.3
Updates the requirements on [ts-loader](https://github.com/TypeStrong/ts-loader) to permit the latest version.
- [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/commits/v5.3.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-08 20:19:39 +00:00
04e1e48f17 Hide invisible notes from timeline (#3852) 2019-01-08 21:02:00 +09:00
b3a0fe823e Update eslint requirement from 5.11.1 to 5.12.0
Updates the requirements on [eslint](https://github.com/eslint/eslint) to permit the latest version.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v5.12.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-08 10:15:52 +00:00
c417e2f4a1 🎨 2019-01-08 18:00:05 +09:00
02a27a8b12 ドライブの管理画面でファイルのオリジナルURLを表示するように 2019-01-08 17:45:16 +09:00
d775e19059 Update CHANGELOG.md 2019-01-08 13:33:50 +09:00
35e7dca2bb Resolve #3847 (#3849)
* Update notifications.ts

* Update notifications.ts

* Update notifications.ts

* Update notifications.ts

* Add missing semicolon

* Improve readability

* Fix typo
2019-01-08 13:32:28 +09:00
6c4ea5e087 Merge pull request #3842 from syuilo/l10n_develop
New Crowdin translations
2019-01-07 18:23:24 +09:00
54a1e500e2 New translations ja-JP.yml (French) 2019-01-07 14:12:02 +09:00
450ed2c471 New translations ja-JP.yml (English) 2019-01-07 07:02:09 +09:00
bf97fcb2fd Update README.md [AUTOGEN] (#3845) 2019-01-07 06:53:25 +09:00
4edeae07a0 Update README.md [AUTOGEN] (#3843) 2019-01-07 06:52:56 +09:00
8e19e4d33b New translations ja-JP.yml (Korean) 2019-01-06 22:22:34 +09:00
2a774c9414 Update update_readme_patreon.sh
Patreon API updates
2019-01-06 18:20:47 +09:00
6f50ed327d New translations ja-JP.yml (Norwegian) 2019-01-06 17:52:52 +09:00
a51d384f19 New translations ja-JP.yml (Dutch) 2019-01-06 17:52:48 +09:00
e2b2e4633a New translations ja-JP.yml (Japanese, Kansai) 2019-01-06 17:52:43 +09:00
46ec773128 New translations ja-JP.yml (Spanish) 2019-01-06 17:52:37 +09:00
1827a65874 New translations ja-JP.yml (Russian) 2019-01-06 17:52:32 +09:00
1b4dd64cbe New translations ja-JP.yml (Portuguese) 2019-01-06 17:52:28 +09:00
95b7d84025 New translations ja-JP.yml (Polish) 2019-01-06 17:52:22 +09:00
137b081b8a New translations ja-JP.yml (Korean) 2019-01-06 17:52:18 +09:00
76af9bbda7 New translations ja-JP.yml (Italian) 2019-01-06 17:52:14 +09:00
17ab07ae9c New translations ja-JP.yml (German) 2019-01-06 17:52:09 +09:00
4c4d06e49b New translations ja-JP.yml (French) 2019-01-06 17:52:05 +09:00
5d9ef68f14 New translations ja-JP.yml (English) 2019-01-06 17:51:59 +09:00
4689cf5591 New translations ja-JP.yml (Chinese Simplified) 2019-01-06 17:51:54 +09:00
58e7edf08a New translations ja-JP.yml (Catalan) 2019-01-06 17:51:50 +09:00
9c6c281ac3 Update CHANGELOG.md 2019-01-06 17:47:05 +09:00
2326d6208b Merge pull request #3811 from syuilo/l10n_develop
New Crowdin translations
2019-01-06 17:46:09 +09:00
cd4be4116b Fix sharedInbox recovery code (#3840) 2019-01-06 17:45:53 +09:00
6697ca243c Update README.md [AUTOGEN] (#3841) 2019-01-06 17:45:34 +09:00
15ce89a88d Resolve #3078 (#3838) 2019-01-06 17:45:14 +09:00
4b13278a41 Update README.md [AUTOGEN] (#3834) 2019-01-06 17:44:36 +09:00
e01167fcab Merge pull request #3816 from syuilo/dependabot/npm_and_yarn/nodemailer-5.0.0
Update nodemailer requirement from 4.7.0 to 5.0.0
2019-01-06 13:29:05 +09:00
719ff26e79 Merge pull request #3830 from syuilo/dependabot/npm_and_yarn/moment-2.23.0
Update moment requirement from 2.22.2 to 2.23.0
2019-01-06 13:28:57 +09:00
2657328ac1 Merge pull request #3831 from syuilo/dependabot/npm_and_yarn/vue-marquee-text-component-1.1.1
Update vue-marquee-text-component requirement from 1.1.0 to 1.1.1
2019-01-06 13:28:49 +09:00
4b7cef239e Merge pull request #3817 from syuilo/dependabot/npm_and_yarn/@fortawesome/fontawesome-svg-core-1.2.12
Update @fortawesome/fontawesome-svg-core requirement from 1.2.8 to 1.2.12
2019-01-06 13:28:39 +09:00
49d9e51f72 Merge branch 'develop' into dependabot/npm_and_yarn/@fortawesome/fontawesome-svg-core-1.2.12 2019-01-06 13:28:33 +09:00
40a5f79d76 Merge pull request #3819 from syuilo/dependabot/npm_and_yarn/@fortawesome/free-brands-svg-icons-5.6.3
Update @fortawesome/free-brands-svg-icons requirement from 5.6.0 to 5.6.3
2019-01-06 13:27:56 +09:00
9cfd0b7351 Merge pull request #3818 from syuilo/dependabot/npm_and_yarn/@types/elasticsearch-5.0.30
Update @types/elasticsearch requirement from 5.0.29 to 5.0.30
2019-01-06 13:27:44 +09:00
2223ecf890 Merge pull request #3832 from syuilo/dependabot/npm_and_yarn/@types/koa-2.0.48
Update @types/koa requirement from 2.0.47 to 2.0.48
2019-01-06 13:27:36 +09:00
06bad9c501 Merge pull request #3833 from syuilo/dependabot/npm_and_yarn/@types/redis-2.8.10
Update @types/redis requirement from 2.8.8 to 2.8.10
2019-01-06 13:27:25 +09:00
a479e65f3e Compact URL preview (#3835)
* Compact url-preview

* fix header

* increase limit

* better limit

* Revert "better limit"

This reverts commit ef396f773394068b0b7e37fccff31c70661b3978.

ハードリミットかけるならサーバー上でかけたほうが良さそう

* Revert "increase limit"

This reverts commit 72c10a456ba37151a4d88d11544b0ff9daabd284.
2019-01-06 12:56:13 +09:00
a2e99e46b9 New translations ja-JP.yml (Polish) 2019-01-06 08:22:03 +09:00
07a27cfb9a New translations ja-JP.yml (Polish) 2019-01-06 08:11:40 +09:00
77f3a0d3a9 New translations ja-JP.yml (Polish) 2019-01-06 08:01:48 +09:00
f9065943c5 Fix #3827 (#3837) 2019-01-06 04:00:30 +09:00
d0aff4409d Locked mark (#3836) 2019-01-05 19:59:10 +09:00
84ea1fbd4d Fix typo: not -> note
1344ffa67d (commitcomment-31817792)
2019-01-05 10:29:46 +09:00
d1d92be09a New translations ja-JP.yml (English) 2019-01-05 02:11:58 +09:00
52b23af97e Update @types/redis requirement from 2.8.8 to 2.8.10
Updates the requirements on [@types/redis](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 20:22:40 +00:00
b76cd18dea Update @types/koa requirement from 2.0.47 to 2.0.48
Updates the requirements on [@types/koa](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 20:20:43 +00:00
cd3b30bf5c Update vue-marquee-text-component requirement from 1.1.0 to 1.1.1
Updates the requirements on [vue-marquee-text-component](https://github.com/EvodiaAut/vue-marquee-text-component) to permit the latest version.
- [Release notes](https://github.com/EvodiaAut/vue-marquee-text-component/releases)
- [Commits](https://github.com/EvodiaAut/vue-marquee-text-component/commits/v1.1.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 20:18:49 +00:00
b87ebc6f9d Update moment requirement from 2.22.2 to 2.23.0
Updates the requirements on [moment](https://github.com/moment/moment) to permit the latest version.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/commits/2.23.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 20:17:22 +00:00
4d7d119524 Update CHANGELOG.md 2019-01-04 04:54:28 +09:00
b4b6e9548d Rename 2019-01-04 03:52:50 +09:00
ebf9cd18c8 Make instance logo customisable (#3829) 2019-01-04 03:02:40 +09:00
b1ccbb2deb New translations ja-JP.yml (English) 2019-01-04 00:43:55 +09:00
562cd6ad0b Improve readability 2019-01-03 12:34:08 +09:00
a832672b59 Update file-type requirement from 10.6.0 to 10.7.0 (#3815)
Updates the requirements on [file-type](https://github.com/sindresorhus/file-type) to permit the latest version.
- [Release notes](https://github.com/sindresorhus/file-type/releases)
- [Commits](https://github.com/sindresorhus/file-type/commits/v10.7.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 11:47:32 +09:00
309058f209 Update webpack requirement from 4.26.1 to 4.28.3 (#3822)
Updates the requirements on [webpack](https://github.com/webpack/webpack) to permit the latest version.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/commits/v4.28.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 08:39:17 +09:00
2a344dfbd8 adds ko-KR な to にゃ (#3820)
* adds ko-KR な to にゃ
- this only take considers pre-composed "Hangul Syllables",
not composable area "Hangul Jamo" which are not used commonly
- 56 is '냐' - '나'

* replace magic number as suggested
2019-01-03 08:38:26 +09:00
866d4cd59a Update vue-i18n requirement from 8.3.2 to 8.6.0 (#3821)
Updates the requirements on [vue-i18n](https://github.com/kazupon/vue-i18n) to permit the latest version.
- [Release notes](https://github.com/kazupon/vue-i18n/releases)
- [Changelog](https://github.com/kazupon/vue-i18n/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/kazupon/vue-i18n/commits/v8.6.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 08:37:44 +09:00
165350cca6 Update apexcharts requirement from 2.4.2 to 2.5.1 (#3826)
Updates the requirements on [apexcharts](https://github.com/apexcharts/apexcharts.js) to permit the latest version.
- [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/commits/v2.5.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-01-03 08:36:00 +09:00
8c21b8a9a6 Update CHANGELOG.md 2019-01-02 18:10:23 +09:00
41e3a9a004 Tune AP URL negotiating with Accept (#3824) 2019-01-02 18:07:32 +09:00
4dc6ec5387 New translations ja-JP.yml (French) 2019-01-02 14:41:41 +09:00
96515c4544 Resolve #3813 (#3814) 2019-01-02 03:35:42 +09:00
b3637b5e8a New translations ja-JP.yml (Korean) 2019-01-02 00:22:17 +09:00
43bcdf397e Update @fortawesome/free-brands-svg-icons requirement
Updates the requirements on [@fortawesome/free-brands-svg-icons](https://github.com/FortAwesome/Font-Awesome) to permit the latest version.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/commits/5.6.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-31 20:27:42 +00:00
22c5db7121 Update @types/elasticsearch requirement from 5.0.29 to 5.0.30
Updates the requirements on [@types/elasticsearch](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-31 20:25:44 +00:00
1c6a8f8691 Update @fortawesome/fontawesome-svg-core requirement
Updates the requirements on [@fortawesome/fontawesome-svg-core](https://github.com/FortAwesome/Font-Awesome) to permit the latest version.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-31 20:21:31 +00:00
31b5175bb0 Update nodemailer requirement from 4.7.0 to 5.0.0
Updates the requirements on [nodemailer](https://github.com/nodemailer/nodemailer) to permit the latest version.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/commits/v5.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-31 20:17:17 +00:00
9add59aca9 2019 🎉 2019-01-01 00:11:07 +09:00
16c65173c1 New translations ja-JP.yml (French) 2018-12-31 06:12:15 +09:00
4f6ae4633f New translations ja-JP.yml (French) 2018-12-31 06:01:44 +09:00
8aa1577713 New translations ja-JP.yml (French) 2018-12-31 05:52:42 +09:00
95 changed files with 1272 additions and 296 deletions

View File

@ -35,7 +35,7 @@ while :
cat patreon.cache | \ cat patreon.cache | \
awk -F'\t' '{print $2,$1}' | \ awk -F'\t' '{print $2,$1}' | \
sed -e 's/ /\\" alt=\\"/' | \ sed -e 's/ /\\" alt=\\"/' | \
xargs -I% echo '<td><img src="%"></td>' >> patreon.md.cache && \ xargs -I% echo '<td><img src="%" width="100"></td>' >> patreon.md.cache && \
echo '</tr><tr>' >> patreon.md.cache && \ echo '</tr><tr>' >> patreon.md.cache && \
cat patreon.cache | \ cat patreon.cache | \
awk -F'\t' '{print $3,$1}' | \ awk -F'\t' '{print $3,$1}' | \

View File

@ -1,6 +1,44 @@
ChangeLog ChangeLog
========= =========
10.77.0
----------
* ローカルタイムライン無効オプションをグローバルタイムライン無効オプションと分離
* モデレータはLTL無効時でもUIからLTLを消さない
* インスタンス情報ページに各種タイムラインの有効/無効を表示
10.76.0
----------
* disableLocalTimeline機能を強化
* インスタンス情報ページの強化
* ハッシュタグ判定の強化
* SVGサムネイルを表示するように
* CWの引き継ぎ機能を無効化
10.75.0
----------
* ダイレクトを非公開のように使えるように
* モデレーターを凍結できないように
* モデレーター登録を解除できるように
* NSFWなメディアをユーザーページなどで表示しないように
* 管理画面でユーザーを状態でフィルタできるように
* 管理者がサインイン履歴を参照できるツール
* Renote数を再度表示するように
* インスタンス情報ページの追加
* テーマの調整
* UIの改善
10.74.0
----------
* Pleromaとのフェデレーションを修正
* インスタンスのキャラクター画像を設定できるように
* Catモードの朝鮮語対応
* CWが付いた投稿に返信する際、そのCWを引き継ぐように
* 投稿のソースをクリップボードにコピーできるように
* i/notifications API で取得する通知の種別を配列で指定できるように
* パフォーマンスの改善
* バグ修正
10.73.0 10.73.0
------- -------
* テーマの強化 * テーマの強化

View File

@ -7,7 +7,7 @@
[![Dependencies](https://img.shields.io/david/syuilo/misskey.svg?style=for-the-badge)](https://david-dm.org/syuilo/misskey) [![Dependencies](https://img.shields.io/david/syuilo/misskey.svg?style=for-the-badge)](https://david-dm.org/syuilo/misskey)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge)](http://makeapullrequest.com) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge)](http://makeapullrequest.com)
**Sophisticated microblogging platform, evolving forever.** **A forever evolving, sophisticated microblogging platform.**
<p align="justify"> <p align="justify">
<a href="https://misskey.xyz">Misskey</a> is a decentralized microblogging platform born on Earth. <a href="https://misskey.xyz">Misskey</a> is a decentralized microblogging platform born on Earth.
@ -27,7 +27,7 @@ Why don't you take a short break from the hustle and bustle of the city, and div
<h3 align="left">Posting</h3> <h3 align="left">Posting</h3>
<p align="justify"> <p align="justify">
Just post your idea, hot topics and anything you want to share. You may decorate your words, attach your favorite pictures or movies, and create a poll - those are all supported in Misskey! Post your ideas, discussion topics, fun moments, or anything else you want to share! Misskey supports text, emoji, pictures, videos, and polls!
</p> </p>
--- ---
@ -36,7 +36,7 @@ Just post your idea, hot topics and anything you want to share. You may decorate
<h3 align="right">Reactions</h3> <h3 align="right">Reactions</h3>
<p align="justify"> <p align="justify">
The simplest way to tell your emotions to the posts. You can choose the best reaction from various reactions. Reactions on Misskey has much more expressive than other social media which only allows pushing “likes”. Reactions are the simplest way to respond to others' posts. Simply pick a reaction emote from the list! Reactions on Misskey are much more expressive than other social media services which only allow “liking”.
</p> </p>
--- ---
@ -45,7 +45,7 @@ The simplest way to tell your emotions to the posts. You can choose the best rea
<h3 align="left">Interface</h3> <h3 align="left">Interface</h3>
<p align="justify"> <p align="justify">
Highly customizable UI for your taste. We understand no UI fits for everyone. Make your graceful home by editing, adjusting layouts of timeline, and placing widgets. Customize the UI to your own tastes! No UI will work for everyone, so Misskey is completely customizable. Make Misskey *yours* by editing the style, adjusting timeline layouts, and placing widgets.
</p> </p>
--- ---
@ -54,35 +54,33 @@ Highly customizable UI for your taste. We understand no UI fits for everyone. Ma
<h3 align="right">Misskey Drive</h3> <h3 align="right">Misskey Drive</h3>
<p align="justify"> <p align="justify">
Organized uploaded files. Wanna post a picture you have already uploaded? Wish to create a folder for your files? Misskey Drive is the best solution for you. Organize and store your files! Want to post a picture you have already uploaded? Wish you could organize your files into folders? Misskey Drive is a solution!
</p> </p>
--- ---
and more! Now it's time to experience the world with your own eyes at [misskey.xyz](https://misskey.xyz) or [other instances](https://joinmisskey.github.io/). ...and more! Experience Misskey with your own eyes at [misskey.xyz](https://misskey.xyz) or join one of the [other instances](https://joinmisskey.github.io/) that are available.
:package: Create your own instance :package: Create Your Own Instance
---------------------------------------------------------------- ----------------------------------------------------------------
Please see [Setup and installation guide](./docs/setup.en.md). Please see the [Setup and Installation Guide](./docs/setup.en.md).
:wrench: Contribution :wrench: Contribution
---------------------------------------------------------------- ----------------------------------------------------------------
Please see [Contribution guide](./CONTRIBUTING.md). Please see the [Contribution Guide](./CONTRIBUTING.md).
:heart: Backers & Sponsors :heart: Backers & Sponsors
---------------------------------------------------------------- ----------------------------------------------------------------
<!-- PATREON_START --> <!-- PATREON_START -->
<table><tr> <table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/1?token-time=2145916800&token-hash=Zeh1u6l_Vmgoy8A1eT1Sltea-_SZSq8t8uOWDRZRh94%3D" alt="weep"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/1?token-time=2145916800&token-hash=WeuDzzz24cRXJogyIkU-mxARqkdyms-rcZKbO-GpGjw%3D" alt="weep" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13376668/71f3cf87ec6c4393a44b1b9df5ee3d12/1?token-time=2145916800&token-hash=7pSmWqgMfMSJHVIEcNsuuQoKeU3TRluew5p0EGTzWA4%3D" alt="Arctic"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=prtYqPOiSHBulhM7NU0VzMaWx39-9ntdq25b6kafDNA%3D" alt="negao" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D" alt="negao"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/2?token-time=2145916800&token-hash=djaJ9cwy9uwTiF9UFtxYQdS8Nw7BhyfaREzZUbErN-0%3D" alt="Melilot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/2?token-time=2145916800&token-hash=mgPdX9TqZxEg4TTPuc477dxhIgYk9246qafjWZEqZ7g%3D" alt="Melilot"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=LtV2lRi3L2jOWMLwccr9qWYfPrFlzIo2jYZHKzHEb6k%3D" alt="Xeltica" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=ybYtxfpte1b-rGg6Zecpys2ZdZDtwR_UNJHQjt-3eoU%3D" alt="Xeltica"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=Ch3iF81ZGP0LMo894Y9ajpLisgtE91SnxtZE7fxsgrM%3D" alt="べすれい" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=1FlxS9MEgmNGH_RHUVHbO5hIXB5I1z0lvA33CTvYvjA%3D" alt="gutfuckllc" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td>
</tr><tr> </tr><tr>
<td><a href="https://www.patreon.com/weepjp">weep</a></td> <td><a href="https://www.patreon.com/weepjp">weep</a></td>
<td><a href="https://www.patreon.com/user?u=13376668">Arctic</a></td>
<td><a href="https://www.patreon.com/negao">negao</a></td> <td><a href="https://www.patreon.com/negao">negao</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td> <td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
<td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td> <td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td>
@ -90,13 +88,13 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td> <td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
</tr></table> </tr></table>
<table><tr> <table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1?token-time=2145916800&token-hash=I8lJVM8LeW6TSo5W6uIIRZ42cw83zp1wK_FsbzY0mcQ%3D" alt="mydarkstar"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1?token-time=2145916800&token-hash=0xgcpqvFDqRcV_YIEhcPNVH7gs9sLg_BBnTJXCkN4ao%3D" alt="mydarkstar" width="100"></td>
<td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td> <td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
<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/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=2PsbFNw0tnubZzgSXD01R6hIgncfiElG7H7HX2Y3dyo%3D" alt="nemu" width="100"></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/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3?token-time=2145916800&token-hash=9JtETp0X8gI280Ne1E8bxn6j4Lw5o2k4mJkICx97V_k%3D" alt="YUKIMOCHI" width="100"></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/eyJ3IjoyMDB9/patreon-media/p/user/8241184/39e18850e87a449e9c9a71acb3310ebd/2?token-time=2145916800&token-hash=zrInDotuEIFslKphuSiCqr3M-r-rveTXjVKWr-VK6M0%3D" alt="Acid Chicken" width="100"></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/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=5T8XcaAf9Zyzfg3QubR06s_kJZkArVEM2dwObrBVAU4%3D" alt="Hiratake" width="100"></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> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/10789744/97175095d8f04c0f86225ff47cb98d40/1?token-time=2145916800&token-hash=ubVARikVOg3v7NW6LDhtG-ClE1LTU3I2TJ3js2-5xDs%3D" alt="Naoki Hirayama" width="100"></td>
</tr><tr> </tr><tr>
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td> <td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td> <td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
@ -107,10 +105,10 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td> <td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td>
</tr></table> </tr></table>
<table><tr> <table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D" alt="dansup"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=Ksk_2l3gjPDbnzMUOCSW1E-hdPJsNs2tSR4_RAakRK8%3D" alt="dansup" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=tB1e_r8RlZ5sFL0KV_e8dugapxatNBRK1Z3h67TO1g8%3D" alt="Gargron"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=CXe9AqlZy9AsYfiWd3OBYVOzvODoN47Litz0Tu4BFpU%3D" alt="Gargron" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1?token-time=2145916800&token-hash=VZUtwrjQa8Jml4twCjHYQQZ64wHEY4oIlGl7Kc-VYUQ%3D" alt="Nokotaro Takeda"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1?token-time=2145916800&token-hash=xhR1n6NAAyEb-IUXLD6_dshkFa3mefU5ZZuk1L8qKTs%3D" alt="Nokotaro Takeda" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D" alt="Takashi Shibuya"></td> <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=uR-48MQ0A4j0irQSrCAQZJ-sJUSs_Fkihlg3-l59b7c%3D" alt="Takashi Shibuya" width="100"></td>
</tr><tr> </tr><tr>
<td><a href="https://www.patreon.com/dansup">dansup</a></td> <td><a href="https://www.patreon.com/dansup">dansup</a></td>
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td> <td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
@ -118,14 +116,14 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td> <td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table> </tr></table>
**Last updated:** Tue, 25 Dec 2018 04:58:06 UTC **Last updated:** Sun, 06 Jan 2019 21:53:06 UTC
<!-- PATREON_END --> <!-- PATREON_END -->
:four_leaf_clover: Copyright :four_leaf_clover: Copyright
---------------------------------------------------------------- ----------------------------------------------------------------
> Copyright (c) 2014-2018 syuilo > Copyright (c) 2014-2019 syuilo
Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE). Misskey is open-source software licensed under the [GNU AGPLv3](LICENSE).
[![][agpl-3.0-badge]][AGPL-3.0] [![][agpl-3.0-badge]][AGPL-3.0]

View File

@ -17,7 +17,7 @@ This guide describes how to install and setup Misskey with Docker.
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. 1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`. 2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`.
2. Edit `default.yml` and `mongo_initdb.js`. 3. Edit `default.yml` and `mongo_initdb.js`.
*3.* Configure Docker *3.* Configure Docker
---------------------------------------------------------------- ----------------------------------------------------------------

67
docs/docker.fr.md Normal file
View File

@ -0,0 +1,67 @@
Guide Docker
================================================================
Ce guide explique comment installer et configurer Misskey avec Docker.
[Version japonaise également disponible - Japanese version also available - 日本語版もあります](./docker.ja.md)
[Version anglaise également disponible - English version also available - 英語版もあります](./docker.en.md)
----------------------------------------------------------------
*1.* Télécharger Misskey
----------------------------------------------------------------
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone le dépôt de Misskey sur la branche master.
2. `cd misskey` Naviguez dans le dossier du dépôt.
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest).
*2.* Configuration de Misskey
----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le `default.yml`.
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copie le fichier `.config/mongo_initdb_example.js` et le renomme en `mongo_initdb.js`.
3. Editez `default.yml` et `mongo_initdb.js`.
*3.* Configurer Docker
----------------------------------------------------------------
Editez `docker-compose.yml`.
*4.* Contruire Misskey
----------------------------------------------------------------
Contruire l'image Docker avec:
`docker-compose build`
*5.* C'est tout !
----------------------------------------------------------------
Parfait, Vous avez un environnement prêt pour démarrer Misskey.
### Lancer normalement
Utilisez la commande `docker-compose up -d`. GLHF!
### How to update your Misskey server to the latest version
1. `git fetch`
2. `git stash`
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
4. `git stash pop`
5. `docker-compose build`
6. Consultez le [ChangeLog](../CHANGELOG.md) pour avoir les éventuelles informations de migration
7. `docker-compose stop && docker-compose up -d`
### Comment exécuter des [commandes](manage.fr.md)
`docker-compose run --rm web node cli/mark-admin @example`
### Configuration d'ElasticSearch (pour la fonction de recherche)
*1.* Préparation de l'environnement
----------------------------------------------------------------
1. `mkdir elasticsearch && chown 1000:1000 elasticsearch` Permet de créer le dossier d'accueil de la base ElasticSearch aves les bons droits
2. `sysctl -w vm.max_map_count=262144` Augmente la valeur max du paramètre map_count du système (valeur minimum pour pouvoir lancer ES)
*2.* Après lancement du docker-compose, initialisation de la base ElasticSearch
----------------------------------------------------------------
1. `docker-compose -it web /bin/sh` Connexion dans le conteneur web
2. `apk add curl` Ajout du paquet curl
3. `curl -X PUT "es:9200/misskey" -H 'Content-Type: application/json' -d'{ "settings" : { "index" : { } }}'` Création de la base ES
4. `exit`
----------------------------------------------------------------
Si vous avez des questions ou des problèmes, n'hésitez pas à nous contacter !

18
docs/manage.fr.md Normal file
View File

@ -0,0 +1,18 @@
# Guide d'administration
## Vérifier le status de la file d'attente des taches
coming soon
## Marquer un utilisateur en tant que 'admin'
``` shell
node cli/mark-admin (ID utilisateur ou nom d'utilisateur)
```
Exemple :
``` shell
# Par id
node cli/mark-admin 57d01a501fdf2d07be417afe
# Par nom d'utilisateur
node cli/suspend @syuilo
```

View File

@ -10,8 +10,8 @@ Ce guide décrit les étapes à suivre afin d'installer et de configurer une ins
*1.* Création de l'utilisateur Misskey *1.* Création de l'utilisateur Misskey
---------------------------------------------------------------- ----------------------------------------------------------------
Lancer misskey en tant qu'utilisateur est une mauvaise idée, nous avons besoin de créer un utilisateur dédié. Executer misskey en tant que super-utilisateur étant une mauvaise idée, nous allons créer un utilisateur dédié.
Sur Debian, à titre d'exemple : Sous Debian, par exemple :
``` ```
adduser --disabled-password --disabled-login misskey adduser --disabled-password --disabled-login misskey
@ -32,10 +32,10 @@ Installez les paquets suivants :
*3.* Paramètrage de MongoDB *3.* Paramètrage de MongoDB
---------------------------------------------------------------- ----------------------------------------------------------------
En mode root : En root :
1. `mongo` Accédez au shell de mango 1. `mongo` Ouvrez le shell mongo
2. `use misskey` Utilisez la base de données misskey 2. `use misskey` Utilisez la base de données misskey
3. `db.users.save( {dummy:"dummy"} )` Write dummy data to initialize the db. 3. `db.users.save( {dummy:"dummy"} )` Écrivez une donnée factice pour initialiser la base de données.
4. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` Créez l'utilisateur misskey. 4. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` Créez l'utilisateur misskey.
5. `exit` Vous avez terminé ! 5. `exit` Vous avez terminé !
@ -44,12 +44,12 @@ En mode root :
1. `su - misskey` Basculez vers l'utilisateur misskey. 1. `su - misskey` Basculez vers l'utilisateur misskey.
2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey. 2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey.
3. `cd misskey` Accédez au dossier misskey. 3. `cd misskey` Accédez au dossier misskey.
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Télécharge la [version la plus récente](https://github.com/syuilo/misskey/releases/latest) 4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
5. `npm install` Installez les dépendances de misskey. 5. `npm install` Installez les dépendances de misskey.
*5.* Création du fichier de configuration *5.* Création du fichier de configuration
---------------------------------------------------------------- ----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le `default.yml`. 1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
2. Editez le fichier `default.yml` 2. Editez le fichier `default.yml`
*6.* Construction de Misskey *6.* Construction de Misskey
@ -59,7 +59,7 @@ Construisez Misskey comme ceci :
`npm run build` `npm run build`
Si vous êtes sous Debian, vous serez amené à installer les paquets `build-essential`, `python`. Si vous êtes sous Debian, vous serez amené à installer les paquets `build-essential` et `python`.
Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp: Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp:
@ -77,7 +77,7 @@ Lancez tout simplement `npm start`. Bonne chance et amusez-vous bien !
### Démarrage avec systemd ### Démarrage avec systemd
1. Créez une service systemd sur : `/etc/systemd/system/misskey.service` 1. Créez un service systemd sur : `/etc/systemd/system/misskey.service`
2. Editez-le puis copiez et coller ceci dans le fichier : 2. Editez-le puis copiez et coller ceci dans le fichier :
``` ```

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "Animationen der Benutzeroberfläche reduzieren" reduce-motion: "Animationen der Benutzeroberfläche reduzieren"
this-setting-is-this-device-only: "Nur auf diesem Gerät" this-setting-is-this-device-only: "Nur auf diesem Gerät"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "Dies ist eine Entwicklungsversion. Nicht in einer Produktionsumgebung verwenden." do-not-use-in-production: "Dies ist eine Entwicklungsversion. Nicht in einer Produktionsumgebung verwenden."
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "Diese Notiz favorisieren" favorite: "Diese Notiz favorisieren"
unfavorite: "Aus Favoriten entfernen" unfavorite: "Aus Favoriten entfernen"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Nacht Modus" dark-mode: "Nacht Modus"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "Abgerundete Ecken" rounded-corners: "Abgerundete Ecken"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "Kreisförmige Icons" circle-icons: "Kreisförmige Icons"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -120,11 +120,15 @@ common:
reduce-motion: "Reduce motion in UI" reduce-motion: "Reduce motion in UI"
this-setting-is-this-device-only: "Only for this device" this-setting-is-this-device-only: "Only for this device"
use-os-default-emojis: "Use the OS default Emojis" use-os-default-emojis: "Use the OS default Emojis"
line-width: "Line thickness"
line-width-thin: "Thin"
line-width-normal: "Regular"
line-width-thick: "Thick"
do-not-use-in-production: "This is a development build. Do not use in production." do-not-use-in-production: "This is a development build. Do not use in production."
user-suspended: "This user has been suspended." user-suspended: "This user has been suspended."
is-remote-user: "This user information is copied." is-remote-user: "This user's information is mirrored."
is-remote-post: "This post information is a copy." is-remote-post: "These post contents are mirrored."
view-on-remote: "View it on remote" view-on-remote: "For completion, view it remotely."
renoted-by: "Renoted by {user}" renoted-by: "Renoted by {user}"
error: error:
title: "Something happened :(" title: "Something happened :("
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "Mention" mention: "Mention"
detail: "Details" detail: "Details"
copy-content: "Copy the contents"
copy-link: "Copy link" copy-link: "Copy link"
favorite: "Favorite this note" favorite: "Favorite this note"
unfavorite: "Unfavorite" unfavorite: "Unfavorite"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Dark Mode" dark-mode: "Dark Mode"
use-shadow: "Use shadows in the UI" use-shadow: "Use shadows in the UI"
rounded-corners: "Round corners of UI" rounded-corners: "Round corners of UI"
line-width: "Line thickness"
line-width-thin: "Thin"
line-width-normal: "Regular"
line-width-thick: "Thick"
circle-icons: "Use circle icons" circle-icons: "Use circle icons"
contrasted-acct: "Add contrast to username" contrasted-acct: "Add contrast to username"
post-form-on-timeline: "Display post form at the top of the timeline" post-form-on-timeline: "Display post form at the top of the timeline"
@ -992,6 +993,7 @@ admin/views/instance.vue:
instance-name: "Instance name" instance-name: "Instance name"
instance-description: "Instance description" instance-description: "Instance description"
host: "Host" host: "Host"
logo-url: "Logo image URL"
banner-url: "Banner image URL" banner-url: "Banner image URL"
error-image-url: "Error image URL" error-image-url: "Error image URL"
languages: "Language of this instance" languages: "Language of this instance"
@ -1065,7 +1067,7 @@ admin/views/charts.vue:
federation: "Federation" federation: "Federation"
notes: "Posts" notes: "Posts"
users: "Users" users: "Users"
drive: "Drive" drive: "Media storage"
network: "Network" network: "Network"
charts: charts:
federation-instances: "The number of instances: increase/decrease" federation-instances: "The number of instances: increase/decrease"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "Esto está en desarrollo, no usarlo para producción." do-not-use-in-production: "Esto está en desarrollo, no usarlo para producción."
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "Detalles" detail: "Detalles"
copy-content: "内容をコピー"
copy-link: "Copiar enlace" copy-link: "Copiar enlace"
favorite: "Me gusta esta nota" favorite: "Me gusta esta nota"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Modo Nocturno" dark-mode: "Modo Nocturno"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "Usar iconos circulares" circle-icons: "Usar iconos circulares"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo"

View File

@ -109,10 +109,10 @@ common:
my-token-regenerated: "Votre jeton vient dêtre généré, vous allez maintenant être déconnecté." my-token-regenerated: "Votre jeton vient dêtre généré, vous allez maintenant être déconnecté."
i-like-sushi: "Je préfère les sushis plutôt que le pudding" i-like-sushi: "Je préfère les sushis plutôt que le pudding"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi" show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
use-avatar-reversi-stones: "リバーシの石にアバターを使う" use-avatar-reversi-stones: "Utiliser lavatar comme pion dans Reversi"
verified-user: "Compte vérifié" verified-user: "Compte vérifié"
disable-animated-mfm: "Désactiver les textes animés dans les publications" disable-animated-mfm: "Désactiver les textes animés dans les publications"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" suggest-recent-hashtags: "Suggérer les hashtags récemment utilisés dans le champs de saisie"
always-show-nsfw: "Toujours afficher les contenus sensibles" always-show-nsfw: "Toujours afficher les contenus sensibles"
always-mark-nsfw: "Toujours marquer les notes ayant des attachements comme sensibles" always-mark-nsfw: "Toujours marquer les notes ayant des attachements comme sensibles"
show-full-acct: "Afficher ladresse complète de lutilisateur" show-full-acct: "Afficher ladresse complète de lutilisateur"
@ -120,8 +120,12 @@ common:
reduce-motion: "Réduire les animations dans linterface utilisateur" reduce-motion: "Réduire les animations dans linterface utilisateur"
this-setting-is-this-device-only: "Uniquement sur cet appareil" this-setting-is-this-device-only: "Uniquement sur cet appareil"
use-os-default-emojis: "Utiliser les émojis standards du système" use-os-default-emojis: "Utiliser les émojis standards du système"
line-width: "Epaisseur du trait"
line-width-thin: "Fine"
line-width-normal: "Normale"
line-width-thick: "Épaisse"
do-not-use-in-production: "Il sagit dune version de développement. Ne pas utiliser dans un environnement de production." do-not-use-in-production: "Il sagit dune version de développement. Ne pas utiliser dans un environnement de production."
user-suspended: "このユーザーは凍結されています。" user-suspended: "Cet·te utilisateur·trice a été suspendu·e"
is-remote-user: "Ces informations appartiennent à un utilisateur distant." is-remote-user: "Ces informations appartiennent à un utilisateur distant."
is-remote-post: "Ceci est une publication distante." is-remote-post: "Ceci est une publication distante."
view-on-remote: " Consulter le profil complet" view-on-remote: " Consulter le profil complet"
@ -260,7 +264,7 @@ common/views/components/media-banner.vue:
sensitive: "Contenu sensible" sensitive: "Contenu sensible"
click-to-show: "Cliquer pour afficher" click-to-show: "Cliquer pour afficher"
common/views/components/theme.vue: common/views/components/theme.vue:
theme: "テーマ" theme: "Thème"
light-theme: "Thème en mode jour" light-theme: "Thème en mode jour"
dark-theme: "Thème en mode nuit" dark-theme: "Thème en mode nuit"
light-themes: "Thème clair" light-themes: "Thème clair"
@ -277,7 +281,7 @@ common/views/components/theme.vue:
base-theme: "Thème de base" base-theme: "Thème de base"
base-theme-light: "Clair" base-theme-light: "Clair"
base-theme-dark: "Sombre" base-theme-dark: "Sombre"
find-more-theme: "その他のテーマを入手" find-more-theme: "Obtenir dautres thèmes"
theme-name: "Nom du Thème" theme-name: "Nom du Thème"
preview-created-theme: "Prévisualisation" preview-created-theme: "Prévisualisation"
invalid-theme: "Thème nest pas valide." invalid-theme: "Thème nest pas valide."
@ -301,7 +305,7 @@ common/views/components/cw-button.vue:
show: "Voir plus" show: "Voir plus"
chars: "{count} caractères" chars: "{count} caractères"
files: "{count} fichiers" files: "{count} fichiers"
poll: "アンケート" poll: "Sondage"
common/views/components/messaging.vue: common/views/components/messaging.vue:
search-user: "Trouver un utilisateur" search-user: "Trouver un utilisateur"
you: "Vous" you: "Vous"
@ -331,8 +335,9 @@ common/views/components/nav.vue:
develop: "Développeurs" develop: "Développeurs"
feedback: "Suggestions" feedback: "Suggestions"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "Mention"
detail: "Détails" detail: "Détails"
copy-content: "Copier le contenu"
copy-link: "Copier le lien" copy-link: "Copier le lien"
favorite: "Mettre cette note en favoris" favorite: "Mettre cette note en favoris"
unfavorite: "Retirer des favoris" unfavorite: "Retirer des favoris"
@ -408,10 +413,10 @@ common/views/components/stream-indicator.vue:
reconnecting: "Reconnexion en cours" reconnecting: "Reconnexion en cours"
connected: "Connecté" connected: "Connecté"
common/views/components/notification-settings.vue: common/views/components/notification-settings.vue:
title: "通知" title: "Notifications"
mark-as-read-all-notifications: "すべての通知を既読にする" mark-as-read-all-notifications: "Marquer toutes les notifications comme lues"
mark-as-read-all-unread-notes: "すべての投稿を既読にする" mark-as-read-all-unread-notes: "Marquer toutes les notes comme lues"
mark-as-read-all-talk-messages: "すべてのトークを既読にする" mark-as-read-all-talk-messages: "Marquer toutes les conversations comme lues"
auto-watch: "投稿の自動ウォッチ" auto-watch: "投稿の自動ウォッチ"
auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。" auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。"
common/views/components/integration-settings.vue: common/views/components/integration-settings.vue:
@ -438,7 +443,7 @@ common/views/components/uploader.vue:
common/views/components/visibility-chooser.vue: common/views/components/visibility-chooser.vue:
public: "Public" public: "Public"
home: "Accueil" home: "Accueil"
home-desc: "Publier sur le fil d'Accueil uniquement" home-desc: "Publier sur le fil dAccueil uniquement"
followers: "Abonnés" followers: "Abonnés"
followers-desc: "Publier à vos abonnés uniquement" followers-desc: "Publier à vos abonnés uniquement"
specified: "Direct" specified: "Direct"
@ -476,7 +481,7 @@ common/views/components/profile-editor.vue:
privacy: "Vie privée" privacy: "Vie privée"
save: "Mettre à jour le profil" save: "Mettre à jour le profil"
saved: "Profil mis à jour avec succès" saved: "Profil mis à jour avec succès"
uploading: "En cours d'envoi…" uploading: "En cours denvoi …"
upload-failed: "Échec de l'envoi" upload-failed: "Échec de l'envoi"
email: "Paramètres de messagerie" email: "Paramètres de messagerie"
email-address: "Adresse de courrier électronique" email-address: "Adresse de courrier électronique"
@ -542,7 +547,7 @@ common/views/widgets/tips.vue:
tips-line24: "Misskey est fonctionnel depuis 2014" tips-line24: "Misskey est fonctionnel depuis 2014"
tips-line25: "Vous pouvez recevoir les notifications de Misskey dans un navigateur web compatible" tips-line25: "Vous pouvez recevoir les notifications de Misskey dans un navigateur web compatible"
common/views/pages/not-found.vue: common/views/pages/not-found.vue:
page-not-found: "ページが見つかりませんでした" page-not-found: "La page demandée est introuvable !"
common/views/pages/follow.vue: common/views/pages/follow.vue:
signed-in-as: "Connecté en tant que {}" signed-in-as: "Connecté en tant que {}"
following: "Suit" following: "Suit"
@ -678,12 +683,12 @@ desktop/views/components/note-detail.vue:
location: "Géolocalisation" location: "Géolocalisation"
renote: "Republier" renote: "Republier"
add-reaction: "Ajouter votre reaction" add-reaction: "Ajouter votre reaction"
undo-reaction: "リアクション解除" undo-reaction: "Inverser la réaction"
desktop/views/components/note.vue: desktop/views/components/note.vue:
reply: "Répondre" reply: "Répondre"
renote: "Partager" renote: "Partager"
add-reaction: "Ajouter votre réaction" add-reaction: "Ajouter votre réaction"
undo-reaction: "リアクション解除" undo-reaction: "Inverser la réaction"
detail: "Détails" detail: "Détails"
private: "Cette publication est privée" private: "Cette publication est privée"
deleted: "Cette publication a été supprimée" deleted: "Cette publication a été supprimée"
@ -733,7 +738,7 @@ desktop/views/components/renote-form.vue:
quote: "Citer..." quote: "Citer..."
cancel: "Annuler" cancel: "Annuler"
renote: "Republier" renote: "Republier"
renote-home: "Renote (Home)" renote-home: "Renote (accueil)"
reposting: "Republication en cours…" reposting: "Republication en cours…"
success: "Republié !" success: "Republié !"
failure: "La renote a échoué" failure: "La renote a échoué"
@ -771,8 +776,8 @@ desktop/views/components/settings.vue:
advanced: "Paramètres avancés" advanced: "Paramètres avancés"
api-via-stream: "Requête API via le flux" api-via-stream: "Requête API via le flux"
api-via-stream-desc: "Lorsque ce paramètre est activé, une demande d'API est effectuée via une connexion WebSocket (pour une meilleure performance). Lorsqu'il est désactivé, l'API de récupération native est utilisée. Ce paramètre n'est valide que sur cet appareil." api-via-stream-desc: "Lorsque ce paramètre est activé, une demande d'API est effectuée via une connexion WebSocket (pour une meilleure performance). Lorsqu'il est désactivé, l'API de récupération native est utilisée. Ce paramètre n'est valide que sur cet appareil."
deck-nav: "デッキ内ナビゲーション" deck-nav: "Deck sans tansitions"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。" deck-nav-desc: "Vous obtenez une colonne temporaire sans transitions dans la page pendant la navigation, lors de lutilisation du Deck."
deck-default: "Utiliser le Deck comme IU par défaut" deck-default: "Utiliser le Deck comme IU par défaut"
display: "Affichage et design" display: "Affichage et design"
customize: "Personnaliser l'Accueil" customize: "Personnaliser l'Accueil"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Mode nuit" dark-mode: "Mode nuit"
use-shadow: "Utiliser les ombres dans l'interface utilisateur" use-shadow: "Utiliser les ombres dans l'interface utilisateur"
rounded-corners: "Coins arrondis" rounded-corners: "Coins arrondis"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
contrasted-acct: "Nom dutilisateur contrasté" contrasted-acct: "Nom dutilisateur contrasté"
post-form-on-timeline: "Afficher le formulaire en haut du fil" post-form-on-timeline: "Afficher le formulaire en haut du fil"
@ -855,7 +856,7 @@ desktop/views/components/settings.2fa.vue:
enter-password: "Entrez un mot de passe" enter-password: "Entrez un mot de passe"
authenticator: "Vous devez au préalable installer Google Authenticator sur votre appareil:" authenticator: "Vous devez au préalable installer Google Authenticator sur votre appareil:"
howtoinstall: "Comment installer" howtoinstall: "Comment installer"
token: "トークン" token: "Jeton"
scan: "Ensuite, scannez le code QR affiché sur votre écran :" scan: "Ensuite, scannez le code QR affiché sur votre écran :"
done: "Veuillez entrer le token qui s'affiche sur votre appareil :" done: "Veuillez entrer le token qui s'affiche sur votre appareil :"
submit: "Envoyer" submit: "Envoyer"
@ -1057,7 +1058,7 @@ admin/views/instance.vue:
serviceworker-info: "Devrait être activé pour les notifications push." serviceworker-info: "Devrait être activé pour les notifications push."
vapid-publickey: "Clé Publique VAPID" vapid-publickey: "Clé Publique VAPID"
vapid-privatekey: "Clé privée VAPID" vapid-privatekey: "Clé privée VAPID"
vapid-info: "ServiceWorkerを有効にする場合、VAPIDキーペアを生成する必要があります。シェルで次のようにします:" vapid-info: "Vous devez activer ServiceWorker pour pouvoir générer les clés VAPID. Vous devez lancer ceci en mode root :"
admin/views/charts.vue: admin/views/charts.vue:
title: "Graphe" title: "Graphe"
per-day: "par jour" per-day: "par jour"
@ -1073,7 +1074,7 @@ admin/views/charts.vue:
notes: "Nombre de publications : augmentation/diminution (combinés)" notes: "Nombre de publications : augmentation/diminution (combinés)"
local-notes: "Nombre des publications : augmentation/diminution (Local)" local-notes: "Nombre des publications : augmentation/diminution (Local)"
remote-notes: "Nombre de publications : augmentation/diminution (distants)" remote-notes: "Nombre de publications : augmentation/diminution (distants)"
notes-total: "Total des publications" notes-total: "Total des notes"
users: "Nombre dutilisateurs : augmentation/diminution" users: "Nombre dutilisateurs : augmentation/diminution"
users-total: "Nombre total des utilisateurs" users-total: "Nombre total des utilisateurs"
drive: "Capacité utilisée comme stockage : augmentation/diminution" drive: "Capacité utilisée comme stockage : augmentation/diminution"
@ -1173,7 +1174,7 @@ desktop/views/pages/welcome.vue:
signup: "S'enregistrer" signup: "S'enregistrer"
signin-button: "Se connecter" signin-button: "Se connecter"
signup-button: "S'inscrire" signup-button: "S'inscrire"
timeline: "Fil d'actualité" timeline: "Fil dactualité"
announcements: "Notices" announcements: "Notices"
photos: "Images récentes" photos: "Images récentes"
powered-by-misskey: "Propulsé par <b>Misskey</b>." powered-by-misskey: "Propulsé par <b>Misskey</b>."
@ -1230,7 +1231,7 @@ desktop/views/pages/user/user.header.vue:
posts: "Notes" posts: "Notes"
following: "Suit" following: "Suit"
followers: "Abonnés" followers: "Abonnés"
mention: "メンション" mention: "Mentions"
is-bot: "Ce compte est un Bot" is-bot: "Ce compte est un Bot"
years-old: "{age} ans" years-old: "{age} ans"
year: "/" year: "/"
@ -1354,7 +1355,7 @@ mobile/views/components/ui.header.vue:
welcome-back: "Content de vous revoir ! " welcome-back: "Content de vous revoir ! "
adjective: "M." adjective: "M."
mobile/views/components/ui.nav.vue: mobile/views/components/ui.nav.vue:
timeline: "Fil d'actualité" timeline: "Fil dactualité"
notifications: "Notifications" notifications: "Notifications"
follow-requests: "Demandes dabonnement" follow-requests: "Demandes dabonnement"
search: "Rechercher" search: "Rechercher"
@ -1368,7 +1369,7 @@ mobile/views/components/ui.nav.vue:
about: "À propos de Misskey" about: "À propos de Misskey"
mobile/views/components/user-timeline.vue: mobile/views/components/user-timeline.vue:
no-notes: "Il semble que cet utilisateur na rien publié pour le moment." no-notes: "Il semble que cet utilisateur na rien publié pour le moment."
no-notes-with-media: "Aucune notes avec des médias" no-notes-with-media: "Aucune note comprenant des médias"
mobile/views/components/users-list.vue: mobile/views/components/users-list.vue:
all: "Tout" all: "Tout"
known: "Vous connaissez" known: "Vous connaissez"
@ -1428,11 +1429,11 @@ mobile/views/pages/settings.vue:
i-am-under-limited-internet: "J'ai un accès Internet limité" i-am-under-limited-internet: "J'ai un accès Internet limité"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
contrasted-acct: "Nom dutilisateur contrasté" contrasted-acct: "Nom dutilisateur contrasté"
timeline: "Fil d'actualité" timeline: "Fil dactualité"
show-reply-target: "Afficher les réponses" show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes partages" show-my-renotes: "Afficher mes partages"
show-renoted-my-notes: "Afficher mes publications partagées" show-renoted-my-notes: "Afficher mes notes partagées"
show-local-renotes: "Afficher les publications partagées localement" show-local-renotes: "Afficher les notes partagées localement"
post-style: "Style de la publication" post-style: "Style de la publication"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Intelligent" post-style-smart: "Intelligent"
@ -1469,7 +1470,7 @@ mobile/views/pages/user.vue:
followers: "Abonnés" followers: "Abonnés"
notes: "Notes" notes: "Notes"
overview: "Aperçu" overview: "Aperçu"
timeline: "Fil d'actualité" timeline: "Fil dactualité"
media: "Média" media: "Média"
mute: "Mettre en sourdine" mute: "Mettre en sourdine"
unmute: "Enlever la sourdine" unmute: "Enlever la sourdine"
@ -1524,7 +1525,7 @@ deck/deck.user-column.vue:
posts: "Notes" posts: "Notes"
following: "Suit" following: "Suit"
followers: "Abonnés" followers: "Abonnés"
mention: "メンション" mention: "Mentions"
images: "Images" images: "Images"
activity: "Activité" activity: "Activité"
timeline: "Fil dactualité" timeline: "Fil dactualité"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -132,6 +132,8 @@ common:
line-width-thin: "細い" line-width-thin: "細い"
line-width-normal: "普通" line-width-normal: "普通"
line-width-thick: "太い" line-width-thick: "太い"
hide-password: "パスワードを隠す"
show-password: "パスワードを表示する"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
@ -367,6 +369,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -1160,6 +1163,7 @@ admin/views/instance.vue:
max-note-text-length: "投稿の最大文字数" max-note-text-length: "投稿の最大文字数"
disable-registration: "ユーザー登録の受付を停止する" disable-registration: "ユーザー登録の受付を停止する"
disable-local-timeline: "ローカルタイムラインを無効にする" disable-local-timeline: "ローカルタイムラインを無効にする"
disable-global-timeline: "グローバルタイムラインを無効にする"
invite: "招待" invite: "招待"
save: "保存" save: "保存"
saved: "保存しました" saved: "保存しました"
@ -1252,6 +1256,14 @@ admin/views/users.vue:
createdAtDesc: "登録日時が新しい順" createdAtDesc: "登録日時が新しい順"
updatedAtAsc: "更新日時が古い順" updatedAtAsc: "更新日時が古い順"
updatedAtDesc: "更新日時が新しい順" updatedAtDesc: "更新日時が新しい順"
state:
title: "状態"
all: "すべて"
admin: "管理者"
moderator: "モデレーター"
adminOrModerator: "管理者+モデレーター"
verified: "公式アカウント"
suspended: "凍結済み"
origin: origin:
title: "オリジン" title: "オリジン"
combined: "ローカル+リモート" combined: "ローカル+リモート"
@ -1265,6 +1277,8 @@ admin/views/moderators.vue:
title: "モデレーターの登録" title: "モデレーターの登録"
add: "登録" add: "登録"
added: "モデレーターを登録しました" added: "モデレーターを登録しました"
remove: "解除"
removed: "モデレーター登録を解除しました"
admin/views/emoji.vue: admin/views/emoji.vue:
add-emoji: add-emoji:

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UI、動き過ぎや、静かにしてや" reduce-motion: "UI、動き過ぎや、静かにしてや"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OSにもとから入っとる絵文字使う" use-os-default-emojis: "OSにもとから入っとる絵文字使う"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "開発ビルドや。本番環境で使わんといて!知らんで!" do-not-use-in-production: "開発ビルドや。本番環境で使わんといて!知らんで!"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "もっと" detail: "もっと"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入りやめる" unfavorite: "お気に入りやめる"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "夜にすんで" dark-mode: "夜にすんで"
use-shadow: "UIに影付けたる" use-shadow: "UIに影付けたる"
rounded-corners: "みんなまぁるくUI変更" rounded-corners: "みんなまぁるくUI変更"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "アイコンもタコ焼きも丸いやんな?" circle-icons: "アイコンもタコ焼きも丸いやんな?"
contrasted-acct: "ユーザー名ようわからんし見やすしといて" contrasted-acct: "ユーザー名ようわからんし見やすしといて"
post-form-on-timeline: "タイムラインの上の方で投稿できるようにせえへん?" post-form-on-timeline: "タイムラインの上の方で投稿できるようにせえへん?"

View File

@ -109,7 +109,7 @@ common:
my-token-regenerated: "당신의 토큰이 업데이트되었으므로 로그아웃합니다." my-token-regenerated: "당신의 토큰이 업데이트되었으므로 로그아웃합니다."
i-like-sushi: "저는 (푸딩보다 차라리) 초밥이 좋아요" i-like-sushi: "저는 (푸딩보다 차라리) 초밥이 좋아요"
show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시" show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시"
use-avatar-reversi-stones: "リバーシの石にアバターを使う" use-avatar-reversi-stones: "리버시의 돌로 아바타를 사용"
verified-user: "공식 계정" verified-user: "공식 계정"
disable-animated-mfm: "글의 문자 애니메이션을 비활성화" disable-animated-mfm: "글의 문자 애니메이션을 비활성화"
suggest-recent-hashtags: "최근 해시태그를 글 작성란에 표시" suggest-recent-hashtags: "최근 해시태그를 글 작성란에 표시"
@ -120,6 +120,10 @@ common:
reduce-motion: "UI의 애니메이션 줄이기" reduce-motion: "UI의 애니메이션 줄이기"
this-setting-is-this-device-only: "이 장치만" this-setting-is-this-device-only: "이 장치만"
use-os-default-emojis: "운영체제의 기본 이모지 사용" use-os-default-emojis: "운영체제의 기본 이모지 사용"
line-width: "선 두께"
line-width-thin: "얇음"
line-width-normal: "보통"
line-width-thick: "두꺼움"
do-not-use-in-production: "이것은 개발 빌드입니다. 프로덕션 환경에서 사용하지 마십시오." do-not-use-in-production: "이것은 개발 빌드입니다. 프로덕션 환경에서 사용하지 마십시오."
user-suspended: "이 사용자는 정지된 상태입니다." user-suspended: "이 사용자는 정지된 상태입니다."
is-remote-user: "이 유저 정보는 복사본입니다." is-remote-user: "이 유저 정보는 복사본입니다."
@ -260,7 +264,7 @@ common/views/components/media-banner.vue:
sensitive: "열람주의" sensitive: "열람주의"
click-to-show: "클릭하여 표시" click-to-show: "클릭하여 표시"
common/views/components/theme.vue: common/views/components/theme.vue:
theme: "テーマ" theme: "테마"
light-theme: "다크 모드가 아닐 때 사용하는 테마" light-theme: "다크 모드가 아닐 때 사용하는 테마"
dark-theme: "다크 모드일 때 사용하는 테마" dark-theme: "다크 모드일 때 사용하는 테마"
light-themes: "밝은 테마" light-themes: "밝은 테마"
@ -277,7 +281,7 @@ common/views/components/theme.vue:
base-theme: "기본 테마" base-theme: "기본 테마"
base-theme-light: "밝음" base-theme-light: "밝음"
base-theme-dark: "어두움" base-theme-dark: "어두움"
find-more-theme: "その他のテーマを入手" find-more-theme: "그 외 테마 찾아보기"
theme-name: "테마명" theme-name: "테마명"
preview-created-theme: "미리보기" preview-created-theme: "미리보기"
invalid-theme: "테마가 올바르지 않습니다." invalid-theme: "테마가 올바르지 않습니다."
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "멘션" mention: "멘션"
detail: "상세" detail: "상세"
copy-content: "내용 복사"
copy-link: "링크 복사" copy-link: "링크 복사"
favorite: "이 노트 즐겨찾기" favorite: "이 노트 즐겨찾기"
unfavorite: "즐겨찾기에서 제거" unfavorite: "즐겨찾기에서 제거"
@ -471,7 +476,7 @@ common/views/components/profile-editor.vue:
is-bot: "이 계정은 Bot입니다" is-bot: "이 계정은 Bot입니다"
is-locked: "팔로우를 수동으로 승인" is-locked: "팔로우를 수동으로 승인"
careful-bot: "Bot의 팔로우만 수동으로 승인" careful-bot: "Bot의 팔로우만 수동으로 승인"
auto-accept-followed: "フォローしているユーザーからのフォローを自動承認する" auto-accept-followed: "팔로우중인 사용자로부터의 팔로우를 자동으로 승인"
advanced: "기타" advanced: "기타"
privacy: "프라이버시" privacy: "프라이버시"
save: "저장" save: "저장"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "다크 모드" dark-mode: "다크 모드"
use-shadow: "UI에 그림자 효과 적용" use-shadow: "UI에 그림자 효과 적용"
rounded-corners: "UI의 모서리를 둥글게 설정" rounded-corners: "UI의 모서리를 둥글게 설정"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "원형 아이콘 사용" circle-icons: "원형 아이콘 사용"
contrasted-acct: "사용자명에 대비 추가" contrasted-acct: "사용자명에 대비 추가"
post-form-on-timeline: "타임라인 상단에 글 작성란을 표시" post-form-on-timeline: "타임라인 상단에 글 작성란을 표시"
@ -855,7 +856,7 @@ desktop/views/components/settings.2fa.vue:
enter-password: "비밀번호를 입력하여 주십시오" enter-password: "비밀번호를 입력하여 주십시오"
authenticator: "먼저, 가지고 계신 장치에 Google Authenticator를 설치해야 합니다:" authenticator: "먼저, 가지고 계신 장치에 Google Authenticator를 설치해야 합니다:"
howtoinstall: "설치 방법은 여기에 있습니다" howtoinstall: "설치 방법은 여기에 있습니다"
token: "トークン" token: "토큰"
scan: "다음으로 표시되어 있는 QR 코드를 스캔합니다:" scan: "다음으로 표시되어 있는 QR 코드를 스캔합니다:"
done: "사용중이신 장치에 표시된 토큰을 입력해주시면 마무리됩니다:" done: "사용중이신 장치에 표시된 토큰을 입력해주시면 마무리됩니다:"
submit: "완료" submit: "완료"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "Deze notitie toevoegen aan favorieten" favorite: "Deze notitie toevoegen aan favorieten"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Donkere modus" dark-mode: "Donkere modus"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "Ronde pictogrammen gebruiken" circle-icons: "Ronde pictogrammen gebruiken"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "Berichtformulier boven de tijdlijn tonen" post-form-on-timeline: "Berichtformulier boven de tijdlijn tonen"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "Detaljer" detail: "Detaljer"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "Merket som favoritt" favorite: "Merket som favoritt"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -120,11 +120,15 @@ common:
reduce-motion: "Zredukuj ruch w UI" reduce-motion: "Zredukuj ruch w UI"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "Użyj domyślnych Emoji systemowych" use-os-default-emojis: "Użyj domyślnych Emoji systemowych"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "Informacje o użytkowniku są kopiowane." is-remote-user: "Informacje o użytkowniku są kopiowane."
is-remote-post: "この投稿情報はコピーです。" is-remote-post: "この投稿情報はコピーです。"
view-on-remote: "正確な情報を見る" view-on-remote: "Dla dopełnienia, zobacz to zdalnie."
renoted-by: "{user} udostępnił(a)" renoted-by: "{user} udostępnił(a)"
error: error:
title: "Coś poszło nie tak" title: "Coś poszło nie tak"
@ -257,11 +261,11 @@ common/views/components/connect-failed.troubleshooter.vue:
flush: "Wyczyść pamięć podręczną" flush: "Wyczyść pamięć podręczną"
set-version: "Określ wersję" set-version: "Określ wersję"
common/views/components/media-banner.vue: common/views/components/media-banner.vue:
sensitive: "閲覧注意" sensitive: "NSFW"
click-to-show: "クリックして表示" click-to-show: "Naciśnij aby wyświetlić"
common/views/components/theme.vue: common/views/components/theme.vue:
theme: "テーマ" theme: "Motyw"
light-theme: "非ダークモード時に使用するテーマ" light-theme: "Motyw"
dark-theme: "ダークモード時に使用するテーマ" dark-theme: "ダークモード時に使用するテーマ"
light-themes: "Jasny Motyw" light-themes: "Jasny Motyw"
dark-themes: "Ciemny motyw" dark-themes: "Ciemny motyw"
@ -277,22 +281,22 @@ common/views/components/theme.vue:
base-theme: "Podstawowy motyw" base-theme: "Podstawowy motyw"
base-theme-light: "Jasny" base-theme-light: "Jasny"
base-theme-dark: "Ciemny" base-theme-dark: "Ciemny"
find-more-theme: "その他のテーマを入手" find-more-theme: "Odkryj więcej motywów"
theme-name: "Nazwa motywu" theme-name: "Nazwa motywu"
preview-created-theme: "Pokaż podgląd" preview-created-theme: "Pokaż podgląd"
invalid-theme: "テーマが正しくありません。" invalid-theme: "Nieprawidłowy motyw"
already-installed: "Ten motyw jest już zainstalowany" already-installed: "Ten motyw jest już zainstalowany"
saved: "Zapisano" saved: "Zapisano"
manage-themes: "Zarządzanie motywami" manage-themes: "Zarządzanie motywami"
builtin-themes: "Standardowe motywy" builtin-themes: "Standardowe motywy"
my-themes: "Moje motywy" my-themes: "Moje motywy"
installed-themes: "Zainstalowane motywy" installed-themes: "Zainstalowane motywy"
select-theme: "テーマを選択してください" select-theme: "Wybierz motyw"
uninstall: "Odinstaluj" uninstall: "Odinstaluj"
uninstalled: "\"{}\" został odinstalowany" uninstalled: "\"{}\" został odinstalowany"
author: "Author" author: "Author"
desc: "Opis" desc: "Opis"
export: "エクスポート" export: "Eksportuj"
import: "Importuj" import: "Importuj"
import-by-code: "lub wklej kod" import-by-code: "lub wklej kod"
theme-name-required: "Nazwa motywu jest obowiązkowa." theme-name-required: "Nazwa motywu jest obowiązkowa."
@ -301,7 +305,7 @@ common/views/components/cw-button.vue:
show: "Pokaż więcej" show: "Pokaż więcej"
chars: "{count} znaków" chars: "{count} znaków"
files: "{count} plików" files: "{count} plików"
poll: "アンケート" poll: "Ankieta"
common/views/components/messaging.vue: common/views/components/messaging.vue:
search-user: "Znajdź użytkownika" search-user: "Znajdź użytkownika"
you: "Ty" you: "Ty"
@ -331,8 +335,9 @@ common/views/components/nav.vue:
develop: "Autorzy" develop: "Autorzy"
feedback: "Podziel się opinią" feedback: "Podziel się opinią"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "Wspomnij"
detail: "Szczegóły" detail: "Szczegóły"
copy-content: "内容をコピー"
copy-link: "Skopiuj adres" copy-link: "Skopiuj adres"
favorite: "Dodaj do ulubionych" favorite: "Dodaj do ulubionych"
unfavorite: "Usuń z ulubionych" unfavorite: "Usuń z ulubionych"
@ -408,7 +413,7 @@ common/views/components/stream-indicator.vue:
reconnecting: "Ponowne łączenie" reconnecting: "Ponowne łączenie"
connected: "Połączono" connected: "Połączono"
common/views/components/notification-settings.vue: common/views/components/notification-settings.vue:
title: "通知" title: "Powiadomienia"
mark-as-read-all-notifications: "すべての通知を既読にする" mark-as-read-all-notifications: "すべての通知を既読にする"
mark-as-read-all-unread-notes: "すべての投稿を既読にする" mark-as-read-all-unread-notes: "すべての投稿を既読にする"
mark-as-read-all-talk-messages: "すべてのトークを既読にする" mark-as-read-all-talk-messages: "すべてのトークを既読にする"
@ -417,7 +422,7 @@ common/views/components/notification-settings.vue:
common/views/components/integration-settings.vue: common/views/components/integration-settings.vue:
title: "サービス連携" title: "サービス連携"
connect: "Połącz" connect: "Połącz"
disconnect: "切断する" disconnect: "Rozłącz"
connected-to: "次のアカウントに接続されています" connected-to: "次のアカウントに接続されています"
common/views/components/github-setting.vue: common/views/components/github-setting.vue:
description: "お使いのGitHubアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでGitHubアカウント情報が表示されるようになったり、GitHubを用いた便利なサインインを利用できるようになります。" description: "お使いのGitHubアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでGitHubアカウント情報が表示されるようになったり、GitHubを用いた便利なサインインを利用できるようになります。"
@ -548,7 +553,7 @@ common/views/pages/follow.vue:
following: "Śledzisz" following: "Śledzisz"
follow: "Śledź" follow: "Śledź"
request-pending: "Oczekiwanie na pozwolenie" request-pending: "Oczekiwanie na pozwolenie"
follow-processing: "フォロー処理中" follow-processing: "Przetwarzanie śledzenia"
follow-request: "Poproś o śledzenie" follow-request: "Poproś o śledzenie"
desktop: desktop:
banner-crop-title: "バナーとして表示する部分を選択" banner-crop-title: "バナーとして表示する部分を選択"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "Tryb ciemny" dark-mode: "Tryb ciemny"
use-shadow: "Użyj cieni w UI" use-shadow: "Użyj cieni w UI"
rounded-corners: "Zaokrąglaj rogi w UI" rounded-corners: "Zaokrąglaj rogi w UI"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "Używaj okrągłych ikon" circle-icons: "Używaj okrągłych ikon"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu"
@ -908,7 +909,7 @@ desktop/views/components/sub-note-content.vue:
poll: "Ankieta" poll: "Ankieta"
desktop/views/components/settings.tags.vue: desktop/views/components/settings.tags.vue:
title: "Tagi" title: "Tagi"
query: "クエリ (省略可)" query: "Zapytanie (opcjonalne)"
add: "Dodaj" add: "Dodaj"
save: "Zapisz" save: "Zapisz"
desktop/views/components/taskmanager.vue: desktop/views/components/taskmanager.vue:
@ -1230,7 +1231,7 @@ desktop/views/pages/user/user.header.vue:
posts: "Wpisy" posts: "Wpisy"
following: "Śledzeni" following: "Śledzeni"
followers: "Śledzący" followers: "Śledzący"
mention: "メンション" mention: "Wspomnij"
is-bot: "To konto jest botem" is-bot: "To konto jest botem"
years-old: "{age} lat" years-old: "{age} lat"
year: "/" year: "/"
@ -1240,7 +1241,7 @@ desktop/views/pages/user/user.timeline.vue:
default: "Wpisy" default: "Wpisy"
with-replies: "Wpisy i odpowiedzi" with-replies: "Wpisy i odpowiedzi"
with-media: "Multimedia" with-media: "Multimedia"
my-posts: "私の投稿" my-posts: "Moje wpisy"
empty: "Ten użytkownik nie umieścił jeszcze niczego." empty: "Ten użytkownik nie umieścił jeszcze niczego."
desktop/views/widgets/messaging.vue: desktop/views/widgets/messaging.vue:
title: "Wiadomości" title: "Wiadomości"
@ -1304,7 +1305,7 @@ common/views/components/follow-button.vue:
following: "フォロー中" following: "フォロー中"
follow: "Śledź" follow: "Śledź"
request-pending: "フォロー許可待ち" request-pending: "フォロー許可待ち"
follow-processing: "フォロー処理中" follow-processing: "Przetwarzanie"
follow-request: "Poproś o śledzenie" follow-request: "Poproś o śledzenie"
mobile/views/components/friends-maker.vue: mobile/views/components/friends-maker.vue:
title: "Zacznij śledzić ludzi takich jak Ty" title: "Zacznij śledzić ludzi takich jak Ty"
@ -1524,7 +1525,7 @@ deck/deck.user-column.vue:
posts: "Wpisy" posts: "Wpisy"
following: "Śledzeni" following: "Śledzeni"
followers: "Śledzący" followers: "Śledzący"
mention: "メンション" mention: "Wspomnij"
images: "Zdjęcia" images: "Zdjęcia"
activity: "Aktywność" activity: "Aktywność"
timeline: "Oś czasu" timeline: "Oś czasu"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "UIの動きを減らす" reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ" this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "OS標準の絵文字を使用" use-os-default-emojis: "OS標準の絵文字を使用"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。" do-not-use-in-production: "これは開発ビルドです。本番環境で使用しないでください。"
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "Уменьшить движение в интерфейсе" reduce-motion: "Уменьшить движение в интерфейсе"
this-setting-is-this-device-only: "Только для этого устройства" this-setting-is-this-device-only: "Только для этого устройства"
use-os-default-emojis: "Использовать стандартные Emoji из ОС" use-os-default-emojis: "Использовать стандартные Emoji из ОС"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "Эта сборка для разработчиков. Не используйте в продакшне." do-not-use-in-production: "Эта сборка для разработчиков. Не используйте в продакшне."
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "このユーザー情報はコピーです。" is-remote-user: "このユーザー情報はコピーです。"
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "詳細" detail: "詳細"
copy-content: "内容をコピー"
copy-link: "リンクをコピー" copy-link: "リンクをコピー"
favorite: "お気に入り" favorite: "お気に入り"
unfavorite: "お気に入り解除" unfavorite: "お気に入り解除"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "ダークモード" dark-mode: "ダークモード"
use-shadow: "UIに影を使用" use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める" rounded-corners: "UIの角を丸める"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "円形のアイコンを使用" circle-icons: "円形のアイコンを使用"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"

View File

@ -120,6 +120,10 @@ common:
reduce-motion: "减弱UI中的动画效果" reduce-motion: "减弱UI中的动画效果"
this-setting-is-this-device-only: "设置仅在本设备中生效" this-setting-is-this-device-only: "设置仅在本设备中生效"
use-os-default-emojis: "使用设备系统默认的 emojis" use-os-default-emojis: "使用设备系统默认的 emojis"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
do-not-use-in-production: "这是一个开发者测试版. 请勿在生产环境中使用." do-not-use-in-production: "这是一个开发者测试版. 请勿在生产环境中使用."
user-suspended: "このユーザーは凍結されています。" user-suspended: "このユーザーは凍結されています。"
is-remote-user: "该用户的信息已被复制." is-remote-user: "该用户的信息已被复制."
@ -333,6 +337,7 @@ common/views/components/nav.vue:
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
mention: "メンション" mention: "メンション"
detail: "详细信息" detail: "详细信息"
copy-content: "内容をコピー"
copy-link: "复制链接" copy-link: "复制链接"
favorite: "收藏这个投稿" favorite: "收藏这个投稿"
unfavorite: "取消收藏" unfavorite: "取消收藏"
@ -782,10 +787,6 @@ desktop/views/components/settings.vue:
dark-mode: "黑暗模式" dark-mode: "黑暗模式"
use-shadow: "在UI中使用阴影效果" use-shadow: "在UI中使用阴影效果"
rounded-corners: "UI界面圆角效果" rounded-corners: "UI界面圆角效果"
line-width: "線の太さ"
line-width-thin: "細い"
line-width-normal: "普通"
line-width-thick: "太い"
circle-icons: "使用圆形图标" circle-icons: "使用圆形图标"
contrasted-acct: "增加用户名的对比度" contrasted-acct: "增加用户名的对比度"
post-form-on-timeline: "在时间线顶部显示帖子表单" post-form-on-timeline: "在时间线顶部显示帖子表单"

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "10.73.0", "version": "10.77.0",
"clientVersion": "2.0.13266", "clientVersion": "2.0.13397",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -20,8 +20,8 @@
"format": "gulp format" "format": "gulp format"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "1.2.8", "@fortawesome/fontawesome-svg-core": "1.2.12",
"@fortawesome/free-brands-svg-icons": "5.6.0", "@fortawesome/free-brands-svg-icons": "5.6.3",
"@fortawesome/free-regular-svg-icons": "5.5.0", "@fortawesome/free-regular-svg-icons": "5.5.0",
"@fortawesome/free-solid-svg-icons": "5.6.3", "@fortawesome/free-solid-svg-icons": "5.6.3",
"@fortawesome/vue-fontawesome": "0.1.2", "@fortawesome/vue-fontawesome": "0.1.2",
@ -34,7 +34,7 @@
"@types/debug": "0.0.31", "@types/debug": "0.0.31",
"@types/deep-equal": "1.0.1", "@types/deep-equal": "1.0.1",
"@types/double-ended-queue": "2.1.0", "@types/double-ended-queue": "2.1.0",
"@types/elasticsearch": "5.0.29", "@types/elasticsearch": "5.0.30",
"@types/file-type": "10.6.0", "@types/file-type": "10.6.0",
"@types/gulp": "3.8.36", "@types/gulp": "3.8.36",
"@types/gulp-mocha": "0.0.32", "@types/gulp-mocha": "0.0.32",
@ -43,10 +43,11 @@
"@types/gulp-uglify": "3.0.6", "@types/gulp-uglify": "3.0.6",
"@types/gulp-util": "3.0.34", "@types/gulp-util": "3.0.34",
"@types/is-root": "1.0.0", "@types/is-root": "1.0.0",
"@types/is-svg": "3.0.0",
"@types/is-url": "1.2.28", "@types/is-url": "1.2.28",
"@types/js-yaml": "3.11.4", "@types/js-yaml": "3.11.4",
"@types/katex": "0.5.0", "@types/katex": "0.5.0",
"@types/koa": "2.0.47", "@types/koa": "2.0.48",
"@types/koa-bodyparser": "5.0.2", "@types/koa-bodyparser": "5.0.2",
"@types/koa-compress": "2.0.8", "@types/koa-compress": "2.0.8",
"@types/koa-favicon": "2.0.19", "@types/koa-favicon": "2.0.19",
@ -60,9 +61,9 @@
"@types/minio": "7.0.1", "@types/minio": "7.0.1",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/mocha": "5.2.5", "@types/mocha": "5.2.5",
"@types/mongodb": "3.1.14", "@types/mongodb": "3.1.18",
"@types/ms": "0.7.30", "@types/ms": "0.7.30",
"@types/node": "10.12.10", "@types/node": "10.12.18",
"@types/nodemailer": "4.6.5", "@types/nodemailer": "4.6.5",
"@types/oauth": "0.9.1", "@types/oauth": "0.9.1",
"@types/parsimmon": "1.10.0", "@types/parsimmon": "1.10.0",
@ -70,13 +71,13 @@
"@types/pug": "2.0.4", "@types/pug": "2.0.4",
"@types/qrcode": "1.3.0", "@types/qrcode": "1.3.0",
"@types/ratelimiter": "2.1.28", "@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.8", "@types/redis": "2.8.10",
"@types/request": "2.48.1", "@types/request": "2.48.1",
"@types/request-promise-native": "1.0.15", "@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2", "@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.27", "@types/seedrandom": "2.4.27",
"@types/sharp": "0.21.0", "@types/sharp": "0.21.0",
"@types/showdown": "1.9.0", "@types/showdown": "1.9.1",
"@types/speakeasy": "2.0.3", "@types/speakeasy": "2.0.3",
"@types/systeminformation": "3.23.1", "@types/systeminformation": "3.23.1",
"@types/tinycolor2": "1.4.1", "@types/tinycolor2": "1.4.1",
@ -87,7 +88,7 @@
"@types/websocket": "0.0.40", "@types/websocket": "0.0.40",
"@types/ws": "6.0.1", "@types/ws": "6.0.1",
"animejs": "2.2.0", "animejs": "2.2.0",
"apexcharts": "2.4.2", "apexcharts": "2.5.1",
"autobind-decorator": "2.4.0", "autobind-decorator": "2.4.0",
"autosize": "4.0.2", "autosize": "4.0.2",
"autwh": "0.1.0", "autwh": "0.1.0",
@ -96,12 +97,12 @@
"bootstrap-vue": "2.0.0-rc.11", "bootstrap-vue": "2.0.0-rc.11",
"cafy": "12.0.0", "cafy": "12.0.0",
"chai": "4.2.0", "chai": "4.2.0",
"chai-http": "4.2.0", "chalk": "2.4.2",
"chalk": "2.4.1", "chai-http": "4.2.1",
"commander": "2.19.0", "commander": "2.19.0",
"crc-32": "1.2.0", "crc-32": "1.2.0",
"css-loader": "1.0.1", "css-loader": "1.0.1",
"cssnano": "4.1.7", "cssnano": "4.1.8",
"dateformat": "3.0.3", "dateformat": "3.0.3",
"debug": "4.1.0", "debug": "4.1.0",
"deep-equal": "1.0.1", "deep-equal": "1.0.1",
@ -111,12 +112,12 @@
"elasticsearch": "15.2.0", "elasticsearch": "15.2.0",
"emojilib": "2.4.0", "emojilib": "2.4.0",
"escape-regexp": "0.0.1", "escape-regexp": "0.0.1",
"eslint": "5.11.1", "eslint": "5.12.0",
"eslint-plugin-vue": "5.0.0", "eslint-plugin-vue": "5.0.0",
"eventemitter3": "3.1.0", "eventemitter3": "3.1.0",
"feed": "2.0.2", "feed": "2.0.2",
"file-loader": "2.0.0", "file-loader": "2.0.0",
"file-type": "10.6.0", "file-type": "10.7.0",
"fuckadblock": "3.2.1", "fuckadblock": "3.2.1",
"gulp": "3.9.1", "gulp": "3.9.1",
"gulp-cssnano": "2.1.3", "gulp-cssnano": "2.1.3",
@ -136,6 +137,7 @@
"http-signature": "1.2.0", "http-signature": "1.2.0",
"insert-text-at-cursor": "0.1.1", "insert-text-at-cursor": "0.1.1",
"is-root": "2.0.0", "is-root": "2.0.0",
"is-svg": "3.0.0",
"is-url": "1.2.4", "is-url": "1.2.4",
"js-yaml": "3.12.0", "js-yaml": "3.12.0",
"jsdom": "13.1.0", "jsdom": "13.1.0",
@ -156,17 +158,18 @@
"koa-views": "6.1.4", "koa-views": "6.1.4",
"langmap": "0.0.16", "langmap": "0.0.16",
"loader-utils": "1.2.3", "loader-utils": "1.2.3",
"minio": "7.0.2", "lookup-dns-cache": "2.1.0",
"minio": "7.0.3",
"mkdirp": "0.5.1", "mkdirp": "0.5.1",
"mocha": "5.2.0", "mocha": "5.2.0",
"moji": "0.5.1", "moji": "0.5.1",
"moment": "2.22.2", "moment": "2.23.0",
"mongodb": "3.1.10", "mongodb": "3.1.10",
"monk": "6.0.6", "monk": "6.0.6",
"ms": "2.1.1", "ms": "2.1.1",
"nan": "2.12.1", "nan": "2.12.1",
"nested-property": "0.0.7", "nested-property": "0.0.7",
"nodemailer": "4.7.0", "nodemailer": "5.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"object-assign-deep": "0.4.0", "object-assign-deep": "0.4.0",
"on-build-webpack": "0.1.0", "on-build-webpack": "0.1.0",
@ -176,6 +179,7 @@
"portscanner": "2.2.0", "portscanner": "2.2.0",
"postcss-loader": "3.0.0", "postcss-loader": "3.0.0",
"progress-bar-webpack-plugin": "1.11.0", "progress-bar-webpack-plugin": "1.11.0",
"promise-any": "0.2.0",
"promise-limit": "2.7.0", "promise-limit": "2.7.0",
"promise-sequential": "1.1.1", "promise-sequential": "1.1.1",
"pug": "2.0.3", "pug": "2.0.3",
@ -204,11 +208,11 @@
"summaly": "2.2.0", "summaly": "2.2.0",
"systeminformation": "3.52.2", "systeminformation": "3.52.2",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "1.1.0", "terser-webpack-plugin": "1.2.1",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"tinycolor2": "1.4.1", "tinycolor2": "1.4.1",
"tmp": "0.0.33", "tmp": "0.0.33",
"ts-loader": "5.3.1", "ts-loader": "5.3.3",
"ts-node": "7.0.1", "ts-node": "7.0.1",
"tslint": "5.12.0", "tslint": "5.12.0",
"tslint-sonarts": "1.8.0", "tslint-sonarts": "1.8.0",
@ -222,10 +226,10 @@
"vue-color": "2.7.0", "vue-color": "2.7.0",
"vue-content-loading": "1.5.3", "vue-content-loading": "1.5.3",
"vue-cropperjs": "3.0.0", "vue-cropperjs": "3.0.0",
"vue-i18n": "8.3.2", "vue-i18n": "8.7.0",
"vue-js-modal": "1.3.28", "vue-js-modal": "1.3.28",
"vue-loader": "15.4.2", "vue-loader": "15.4.2",
"vue-marquee-text-component": "1.1.0", "vue-marquee-text-component": "1.1.1",
"vue-router": "3.0.2", "vue-router": "3.0.2",
"vue-sequential-entrance": "1.1.3", "vue-sequential-entrance": "1.1.3",
"vue-style-loader": "4.1.2", "vue-style-loader": "4.1.2",
@ -237,8 +241,8 @@
"vuex-persistedstate": "2.5.4", "vuex-persistedstate": "2.5.4",
"web-push": "3.3.3", "web-push": "3.3.3",
"webfinger.js": "2.7.0", "webfinger.js": "2.7.0",
"webpack": "4.26.1", "webpack": "4.28.3",
"webpack-cli": "3.1.2", "webpack-cli": "3.2.1",
"websocket": "1.0.28", "websocket": "1.0.28",
"ws": "6.1.2", "ws": "6.1.2",
"xev": "2.0.1" "xev": "2.0.1"

View File

@ -39,6 +39,7 @@
</div> </div>
</div> </div>
<div v-show="file._open"> <div v-show="file._open">
<ui-input readonly :value="file.url"></ui-input>
<ui-horizon-group> <ui-horizon-group>
<ui-button @click="toggleSensitive(file)" v-if="file.isSensitive"><fa :icon="faEye"/> {{ $t('unmark-as-sensitive') }}</ui-button> <ui-button @click="toggleSensitive(file)" v-if="file.isSensitive"><fa :icon="faEye"/> {{ $t('unmark-as-sensitive') }}</ui-button>
<ui-button @click="toggleSensitive(file)" v-else><fa :icon="faEyeSlash"/> {{ $t('mark-as-sensitive') }}</ui-button> <ui-button @click="toggleSensitive(file)" v-else><fa :icon="faEyeSlash"/> {{ $t('mark-as-sensitive') }}</ui-button>

View File

@ -6,6 +6,7 @@
<ui-input :value="host" readonly>{{ $t('host') }}</ui-input> <ui-input :value="host" readonly>{{ $t('host') }}</ui-input>
<ui-input v-model="name">{{ $t('instance-name') }}</ui-input> <ui-input v-model="name">{{ $t('instance-name') }}</ui-input>
<ui-textarea v-model="description">{{ $t('instance-description') }}</ui-textarea> <ui-textarea v-model="description">{{ $t('instance-description') }}</ui-textarea>
<ui-input v-model="mascotImageUrl"><i slot="icon"><fa icon="link"/></i>{{ $t('logo-url') }}</ui-input>
<ui-input v-model="bannerUrl"><i slot="icon"><fa icon="link"/></i>{{ $t('banner-url') }}</ui-input> <ui-input v-model="bannerUrl"><i slot="icon"><fa icon="link"/></i>{{ $t('banner-url') }}</ui-input>
<ui-input v-model="errorImageUrl"><i slot="icon"><fa icon="link"/></i>{{ $t('error-image-url') }}</ui-input> <ui-input v-model="errorImageUrl"><i slot="icon"><fa icon="link"/></i>{{ $t('error-image-url') }}</ui-input>
<ui-input v-model="languages"><i slot="icon"><fa icon="language"/></i>{{ $t('languages') }}<span slot="desc">{{ $t('languages-desc') }}</span></ui-input> <ui-input v-model="languages"><i slot="icon"><fa icon="language"/></i>{{ $t('languages') }}<span slot="desc">{{ $t('languages-desc') }}</span></ui-input>
@ -21,6 +22,7 @@
<section> <section>
<ui-switch v-model="disableRegistration">{{ $t('disable-registration') }}</ui-switch> <ui-switch v-model="disableRegistration">{{ $t('disable-registration') }}</ui-switch>
<ui-switch v-model="disableLocalTimeline">{{ $t('disable-local-timeline') }}</ui-switch> <ui-switch v-model="disableLocalTimeline">{{ $t('disable-local-timeline') }}</ui-switch>
<ui-switch v-model="disableGlobalTimeline">{{ $t('disable-global-timeline') }}</ui-switch>
</section> </section>
<section class="fit-bottom"> <section class="fit-bottom">
<header><fa icon="cloud"/> {{ $t('drive-config') }}</header> <header><fa icon="cloud"/> {{ $t('drive-config') }}</header>
@ -53,7 +55,7 @@
</ui-horizon-group> </ui-horizon-group>
<ui-horizon-group inputs> <ui-horizon-group inputs>
<ui-input v-model="smtpUser" :disabled="!enableEmail">{{ $t('smtp-user') }}</ui-input> <ui-input v-model="smtpUser" :disabled="!enableEmail">{{ $t('smtp-user') }}</ui-input>
<ui-input v-model="smtpPass" :disabled="!enableEmail">{{ $t('smtp-pass') }}</ui-input> <ui-input v-model="smtpPass" type="password" :withPasswordToggle="true" :disabled="!enableEmail">{{ $t('smtp-pass') }}</ui-input>
</ui-horizon-group> </ui-horizon-group>
<ui-switch v-model="smtpSecure" :disabled="!enableEmail">{{ $t('smtp-secure') }}<span slot="desc">{{ $t('smtp-secure-info') }}</span></ui-switch> <ui-switch v-model="smtpSecure" :disabled="!enableEmail">{{ $t('smtp-secure') }}<span slot="desc">{{ $t('smtp-secure-info') }}</span></ui-switch>
</section> </section>
@ -149,6 +151,8 @@ export default Vue.extend({
maintainerEmail: null, maintainerEmail: null,
disableRegistration: false, disableRegistration: false,
disableLocalTimeline: false, disableLocalTimeline: false,
disableGlobalTimeline: false,
mascotImageUrl: null,
bannerUrl: null, bannerUrl: null,
errorImageUrl: null, errorImageUrl: null,
name: null, name: null,
@ -196,6 +200,8 @@ export default Vue.extend({
this.maintainerEmail = meta.maintainer.email; this.maintainerEmail = meta.maintainer.email;
this.disableRegistration = meta.disableRegistration; this.disableRegistration = meta.disableRegistration;
this.disableLocalTimeline = meta.disableLocalTimeline; this.disableLocalTimeline = meta.disableLocalTimeline;
this.disableGlobalTimeline = meta.disableGlobalTimeline;
this.mascotImageUrl = meta.mascotImageUrl;
this.bannerUrl = meta.bannerUrl; this.bannerUrl = meta.bannerUrl;
this.errorImageUrl = meta.errorImageUrl; this.errorImageUrl = meta.errorImageUrl;
this.name = meta.name; this.name = meta.name;
@ -253,6 +259,8 @@ export default Vue.extend({
maintainerEmail: this.maintainerEmail, maintainerEmail: this.maintainerEmail,
disableRegistration: this.disableRegistration, disableRegistration: this.disableRegistration,
disableLocalTimeline: this.disableLocalTimeline, disableLocalTimeline: this.disableLocalTimeline,
disableGlobalTimeline: this.disableGlobalTimeline,
mascotImageUrl: this.mascotImageUrl,
bannerUrl: this.bannerUrl, bannerUrl: this.bannerUrl,
errorImageUrl: this.errorImageUrl, errorImageUrl: this.errorImageUrl,
name: this.name, name: this.name,

View File

@ -6,7 +6,8 @@
<ui-input v-model="username" type="text"> <ui-input v-model="username" type="text">
<span slot="prefix">@</span> <span slot="prefix">@</span>
</ui-input> </ui-input>
<ui-button @click="add" :disabled="adding">{{ $t('add-moderator.add') }}</ui-button> <ui-button @click="add" :disabled="changing">{{ $t('add-moderator.add') }}</ui-button>
<ui-button @click="remove" :disabled="changing">{{ $t('add-moderator.remove') }}</ui-button>
</section> </section>
</ui-card> </ui-card>
</div> </div>
@ -23,13 +24,13 @@ export default Vue.extend({
data() { data() {
return { return {
username: '', username: '',
adding: false changing: false
}; };
}, },
methods: { methods: {
async add() { async add() {
this.adding = true; this.changing = true;
const process = async () => { const process = async () => {
const user = await this.$root.api('users/show', parseAcct(this.username)); const user = await this.$root.api('users/show', parseAcct(this.username));
@ -47,7 +48,29 @@ export default Vue.extend({
}); });
}); });
this.adding = false; this.changing = false;
},
async remove() {
this.changing = true;
const process = async () => {
const user = await this.$root.api('users/show', parseAcct(this.username));
await this.$root.api('admin/moderators/remove', { userId: user.id });
this.$root.dialog({
type: 'success',
text: this.$t('add-moderator.removed')
});
};
await process().catch(e => {
this.$root.dialog({
type: 'error',
text: e.toString()
});
});
this.changing = false;
}, },
} }
}); });

View File

@ -31,6 +31,14 @@
<option value="-updatedAt">{{ $t('users.sort.updatedAtAsc') }}</option> <option value="-updatedAt">{{ $t('users.sort.updatedAtAsc') }}</option>
<option value="+updatedAt">{{ $t('users.sort.updatedAtDesc') }}</option> <option value="+updatedAt">{{ $t('users.sort.updatedAtDesc') }}</option>
</ui-select> </ui-select>
<ui-select v-model="state">
<span slot="label">{{ $t('users.state.title') }}</span>
<option value="all">{{ $t('users.state.all') }}</option>
<option value="admin">{{ $t('users.state.admin') }}</option>
<option value="moderator">{{ $t('users.state.moderator') }}</option>
<option value="verified">{{ $t('users.state.verified') }}</option>
<option value="suspended">{{ $t('users.state.suspended') }}</option>
</ui-select>
<ui-select v-model="origin"> <ui-select v-model="origin">
<span slot="label">{{ $t('users.origin.title') }}</span> <span slot="label">{{ $t('users.origin.title') }}</span>
<option value="combined">{{ $t('users.origin.combined') }}</option> <option value="combined">{{ $t('users.origin.combined') }}</option>
@ -39,7 +47,7 @@
</ui-select> </ui-select>
</ui-horizon-group> </ui-horizon-group>
<sequential-entrance animation="entranceFromTop" delay="25"> <sequential-entrance animation="entranceFromTop" delay="25">
<div class="kofvwchc" v-for="user in users"> <div class="kofvwchc" v-for="user in users" :key="user.id">
<div> <div>
<a :href="user | userPage(null, true)"> <a :href="user | userPage(null, true)">
<mk-avatar class="avatar" :user="user" :disable-link="true"/> <mk-avatar class="avatar" :user="user" :disable-link="true"/>
@ -49,6 +57,10 @@
<header> <header>
<b><mk-user-name :user="user"/></b> <b><mk-user-name :user="user"/></b>
<span class="username">@{{ user | acct }}</span> <span class="username">@{{ user | acct }}</span>
<span class="is-admin" v-if="user.isAdmin">admin</span>
<span class="is-moderator" v-if="user.isModerator">moderator</span>
<span class="is-verified" v-if="user.isVerified" :title="$t('@.verified-user')"><fa icon="star"/></span>
<span class="is-suspended" v-if="user.isSuspended" :title="$t('@.suspended-user')"><fa :icon="faSnowflake"/></span>
</header> </header>
<div> <div>
<span>{{ $t('users.updatedAt') }}: <mk-time :time="user.updatedAt" mode="detail"/></span> <span>{{ $t('users.updatedAt') }}: <mk-time :time="user.updatedAt" mode="detail"/></span>
@ -84,6 +96,7 @@ export default Vue.extend({
suspending: false, suspending: false,
unsuspending: false, unsuspending: false,
sort: '+createdAt', sort: '+createdAt',
state: 'all',
origin: 'combined', origin: 'combined',
limit: 10, limit: 10,
offset: 0, offset: 0,
@ -100,6 +113,12 @@ export default Vue.extend({
this.fetchUsers(); this.fetchUsers();
}, },
state() {
this.users = [];
this.offset = 0;
this.fetchUsers();
},
origin() { origin() {
this.users = []; this.users = [];
this.offset = 0; this.offset = 0;
@ -236,7 +255,8 @@ export default Vue.extend({
}, },
fetchUsers() { fetchUsers() {
this.$root.api('users', { this.$root.api('admin/show-users', {
state: this.state,
origin: this.origin, origin: this.origin,
sort: this.sort, sort: this.sort,
offset: this.offset, offset: this.offset,
@ -284,4 +304,19 @@ export default Vue.extend({
margin-left 8px margin-left 8px
opacity 0.7 opacity 0.7
> .is-admin
> .is-moderator
flex-shrink 0
align-self center
margin 0 0 0 .5em
padding 1px 6px
font-size 80%
border-radius 3px
background var(--noteHeaderAdminBg)
color var(--noteHeaderAdminFg)
> .is-verified
> .is-suspended
margin 0 0 0 .5em
color #4dabf7
</style> </style>

View File

@ -2,6 +2,7 @@
<span class="mk-acct"> <span class="mk-acct">
<span class="name">@{{ user.username }}</span> <span class="name">@{{ user.username }}</span>
<span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="user.host || detail || $store.state.settings.showFullAcct">@{{ user.host || host }}</span> <span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="user.host || detail || $store.state.settings.showFullAcct">@{{ user.host || host }}</span>
<fa v-if="user.isLocked == true" class="locked" icon="lock" fixed-width/>
</span> </span>
</template> </template>
@ -23,4 +24,8 @@ export default Vue.extend({
.mk-acct .mk-acct
> .host.fade > .host.fade
opacity 0.5 opacity 0.5
> .locked
opacity 0.8
margin-left 0.5em
</style> </style>

View File

@ -18,7 +18,7 @@
<span class="visibility" v-if="note.visibility != 'public'"> <span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" icon="home"/> <fa v-if="note.visibility == 'home'" icon="home"/>
<fa v-if="note.visibility == 'followers'" icon="unlock"/> <fa v-if="note.visibility == 'followers'" icon="unlock"/>
<fa v-if="note.visibility == 'specified'" icon="lock"/> <fa v-if="note.visibility == 'specified'" icon="envelope"/>
</span> </span>
<span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span> <span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span>
</div> </div>

View File

@ -29,6 +29,10 @@ export default Vue.extend({
icon: 'info-circle', icon: 'info-circle',
text: this.$t('detail'), text: this.$t('detail'),
action: this.detail action: this.detail
}], [{
icon: 'align-left',
text: this.$t('copy-content'),
action: this.copyContent
}], [{ }], [{
icon: 'link', icon: 'link',
text: this.$t('copy-link'), text: this.$t('copy-link'),
@ -81,6 +85,10 @@ export default Vue.extend({
this.$router.push(`/notes/${this.note.id}`); this.$router.push(`/notes/${this.note.id}`);
}, },
copyContent() {
copyToClipboard(this.note.text);
},
copyLink() { copyLink() {
copyToClipboard(`${url}/notes/${this.note.id}`); copyToClipboard(`${url}/notes/${this.note.id}`);
}, },

View File

@ -13,7 +13,7 @@
<span class="visibility" v-if="note.visibility != 'public'"> <span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" icon="home"/> <fa v-if="note.visibility == 'home'" icon="home"/>
<fa v-if="note.visibility == 'followers'" icon="unlock"/> <fa v-if="note.visibility == 'followers'" icon="unlock"/>
<fa v-if="note.visibility == 'specified'" icon="lock"/> <fa v-if="note.visibility == 'specified'" icon="envelope"/>
</span> </span>
<span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span> <span class="localOnly" v-if="note.localOnly == true"><fa icon="heart"/></span>
</div> </div>

View File

@ -6,7 +6,7 @@
<span slot="prefix">@</span> <span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span> <span slot="suffix">@{{ host }}</span>
</ui-input> </ui-input>
<ui-input v-model="password" type="password" required styl="fill"> <ui-input v-model="password" type="password" :with-password-toggle="true" required styl="fill">
<span>{{ $t('password') }}</span> <span>{{ $t('password') }}</span>
<span slot="prefix"><fa icon="lock"/></span> <span slot="prefix"><fa icon="lock"/></span>
</ui-input> </ui-input>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="vnxwkwuf" :class="{ inputs, noGrow }"> <div class="vnxwkwuf" :class="{ inputs, noGrow }" :data-children-count="children">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
@ -21,6 +21,16 @@ export default Vue.extend({
required: false, required: false,
default: false default: false
} }
},
data() {
return {
children: 0
};
},
mounted() {
this.$nextTick(() => {
this.children = this.$slots.default.length;
});
} }
}); });
</script> </script>
@ -48,4 +58,19 @@ export default Vue.extend({
> *:not(:last-child) > *:not(:last-child)
margin-right 16px !important margin-right 16px !important
&[data-children-count="3"]
@media (max-width 600px)
display block
> *
display block
width 100% !important
margin 16px 0 !important
&:first-child
margin-top 0 !important
&:last-child
margin-bottom 0 !important
</style> </style>

View File

@ -39,6 +39,12 @@
</template> </template>
<div class="suffix" ref="suffix"><slot name="suffix"></slot></div> <div class="suffix" ref="suffix"><slot name="suffix"></slot></div>
</div> </div>
<div class="toggle" v-if="withPasswordToggle">
<a @click='togglePassword'>
<span v-if="type == 'password'"><fa :icon="['fa', 'eye']"/> {{ $t('@.show-password') }}</span>
<span v-if="type != 'password'"><fa :icon="['far', 'eye-slash']"/> {{ $t('@.hide-password') }}</span>
</a>
</div>
<div class="desc"><slot name="desc"></slot></div> <div class="desc"><slot name="desc"></slot></div>
</div> </div>
</template> </template>
@ -97,6 +103,11 @@ export default Vue.extend({
required: false, required: false,
default: false default: false
}, },
withPasswordToggle: {
type: Boolean,
required: false,
default: false
},
inline: { inline: {
type: Boolean, type: Boolean,
required: false, required: false,
@ -178,6 +189,13 @@ export default Vue.extend({
focus() { focus() {
this.$refs.input.focus(); this.$refs.input.focus();
}, },
togglePassword() {
if (this.type == 'password') {
this.type = 'text'
} else {
this.type = 'password'
}
},
chooseFile() { chooseFile() {
this.$refs.file.click(); this.$refs.file.click();
}, },
@ -356,6 +374,17 @@ root(fill)
if fill if fill
padding-right 12px padding-right 12px
> .toggle
cursor pointer
padding-left 0.5em
font-size 0.7em
opacity 0.7
text-align left
> a
color var(--inputLabel)
text-decoration none
> .desc > .desc
margin 6px 0 margin 6px 0
font-size 13px font-size 13px

View File

@ -8,16 +8,16 @@
</blockquote> </blockquote>
</div> </div>
<div v-else class="mk-url-preview"> <div v-else class="mk-url-preview">
<a :class="{ mini }" :href="url" target="_blank" :title="url" v-if="!fetching"> <a :class="{ mini, compact }" :href="url" target="_blank" :title="url" v-if="!fetching">
<div class="thumbnail" v-if="thumbnail" :style="`background-image: url(${thumbnail})`"></div> <div class="thumbnail" v-if="thumbnail" :style="`background-image: url(${thumbnail})`"></div>
<article> <article>
<header> <header>
<h1>{{ title }}</h1> <h1 :title="title">{{ title }}</h1>
</header> </header>
<p v-if="description">{{ description.length > 85 ? description.slice(0, 85) + '…' : description }}</p> <p v-if="description" :title="description">{{ description.length > 85 ? description.slice(0, 85) + '…' : description }}</p>
<footer> <footer>
<img class="icon" v-if="icon" :src="icon"/> <img class="icon" v-if="icon" :src="icon"/>
<p>{{ sitename }}</p> <p :title="sitename">{{ sitename }}</p>
</footer> </footer>
</article> </article>
</a> </a>
@ -120,6 +120,12 @@ export default Vue.extend({
default: false default: false
}, },
compact: {
type: Boolean,
required: false,
default: false
},
mini: { mini: {
type: Boolean, type: Boolean,
required: false, required: false,
@ -302,6 +308,23 @@ export default Vue.extend({
width 12px width 12px
height 12px height 12px
&.compact
> .thumbnail
position: absolute
width 56px
height 100%
> article
left 56px
width calc(100% - 56px)
padding 4px
> header
margin-bottom 2px
> footer
margin-top 2px
&.mini &.mini
font-size 10px font-size 10px
@ -325,4 +348,27 @@ export default Vue.extend({
width 12px width 12px
height 12px height 12px
&.compact
> .thumbnail
position: absolute
width 56px
height 100%
> article
left 56px
width calc(100% - 56px)
padding 4px
> header
margin-bottom 2px
> footer
margin-top 2px
&.compact
> article
> header h1, p, footer
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
</style> </style>

View File

@ -23,7 +23,7 @@
</div> </div>
</div> </div>
<div @click="choose('specified')" :class="{ active: v == 'specified' }"> <div @click="choose('specified')" :class="{ active: v == 'specified' }">
<div><fa icon="lock"/></div> <div><fa icon="envelope"/></div>
<div> <div>
<span>{{ $t('specified') }}</span> <span>{{ $t('specified') }}</span>
<span>{{ $t('specified-desc') }}</span> <span>{{ $t('specified-desc') }}</span>

View File

@ -32,7 +32,7 @@
<span class="visibility" v-if="appearNote.visibility != 'public'"> <span class="visibility" v-if="appearNote.visibility != 'public'">
<fa v-if="appearNote.visibility == 'home'" icon="home"/> <fa v-if="appearNote.visibility == 'home'" icon="home"/>
<fa v-if="appearNote.visibility == 'followers'" icon="unlock"/> <fa v-if="appearNote.visibility == 'followers'" icon="unlock"/>
<fa v-if="appearNote.visibility == 'specified'" icon="lock"/> <fa v-if="appearNote.visibility == 'specified'" icon="envelope"/>
</span> </span>
<span class="localOnly" v-if="appearNote.localOnly == true"><fa icon="heart"/></span> <span class="localOnly" v-if="appearNote.localOnly == true"><fa icon="heart"/></span>
</div> </div>
@ -70,7 +70,7 @@
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="['public', 'home'].includes(appearNote.visibility)" class="renoteButton" @click="renote()" :title="$t('renote')"> <button v-if="['public', 'home'].includes(appearNote.visibility)" class="renoteButton" @click="renote()" :title="$t('renote')">
<fa icon="retweet"/> <fa icon="retweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
</button> </button>
<button v-else class="inhibitedButton"> <button v-else class="inhibitedButton">
<fa icon="ban"/> <fa icon="ban"/>

View File

@ -36,7 +36,7 @@
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/> <mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> 位置情報</a> <a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> 位置情報</a>
<div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote" :mini="mini"/></div> <div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote" :mini="mini"/></div>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini"/> <mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini" :compact="compact"/>
</div> </div>
</div> </div>
<footer v-if="appearNote.deletedAt == null"> <footer v-if="appearNote.deletedAt == null">
@ -48,7 +48,7 @@
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="['public', 'home'].includes(appearNote.visibility)" class="renoteButton" @click="renote()" :title="$t('renote')"> <button v-if="['public', 'home'].includes(appearNote.visibility)" class="renoteButton" @click="renote()" :title="$t('renote')">
<fa icon="retweet"/> <fa icon="retweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
</button> </button>
<button v-else class="inhibitedButton"> <button v-else class="inhibitedButton">
<fa icon="ban"/> <fa icon="ban"/>
@ -102,6 +102,11 @@ export default Vue.extend({
required: false, required: false,
default: false default: false
}, },
compact: {
type: Boolean,
required: false,
default: false
},
mini: { mini: {
type: Boolean, type: Boolean,
required: false, required: false,

View File

@ -15,7 +15,7 @@
<!-- トランジションを有効にするとなぜかメモリリークする --> <!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="notes transition" tag="div" ref="notes"> <component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="notes transition" tag="div" ref="notes">
<template v-for="(note, i) in _notes"> <template v-for="(note, i) in _notes">
<x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" ref="note"/> <x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" :compact="true" ref="note"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date"> <p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span><fa icon="angle-up"/>{{ note._datetext }}</span> <span><fa icon="angle-up"/>{{ note._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span> <span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span>

View File

@ -50,7 +50,7 @@
<span v-if="visibility === 'public'"><fa icon="globe"/></span> <span v-if="visibility === 'public'"><fa icon="globe"/></span>
<span v-if="visibility === 'home'"><fa icon="home"/></span> <span v-if="visibility === 'home'"><fa icon="home"/></span>
<span v-if="visibility === 'followers'"><fa icon="unlock"/></span> <span v-if="visibility === 'followers'"><fa icon="unlock"/></span>
<span v-if="visibility === 'specified'"><fa icon="lock"/></span> <span v-if="visibility === 'specified'"><fa icon="envelope"/></span>
</button> </button>
<p class="text-count" :class="{ over: trimmedLength(text) > maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}</p> <p class="text-count" :class="{ over: trimmedLength(text) > maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}</p>
<ui-button primary :wait="posting" class="submit" :disabled="!canPost" @click="post"> <ui-button primary :wait="posting" class="submit" :disabled="!canPost" @click="post">
@ -77,6 +77,7 @@ import extractMentions from '../../../../../misc/extract-mentions';
export default Vue.extend({ export default Vue.extend({
i18n: i18n('desktop/views/components/post-form.vue'), i18n: i18n('desktop/views/components/post-form.vue'),
components: { components: {
XDraggable, XDraggable,
MkVisibilityChooser MkVisibilityChooser
@ -197,11 +198,11 @@ export default Vue.extend({
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`; const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
// 自分は除外 // 自分は除外
if (this.$store.state.i.username == x.username && x.host == null) return; if (this.$store.state.i.username == x.username && x.host == null) continue;
if (this.$store.state.i.username == x.username && x.host == host) return; if (this.$store.state.i.username == x.username && x.host == host) continue;
// 重複は除外 // 重複は除外
if (this.text.indexOf(`${mention} `) != -1) return; if (this.text.indexOf(`${mention} `) != -1) continue;
this.text += `${mention} `; this.text += `${mention} `;
} }

View File

@ -21,7 +21,14 @@ import i18n from '../../../i18n';
export default Vue.extend({ export default Vue.extend({
i18n: i18n('desktop/views/components/renote-form.vue'), i18n: i18n('desktop/views/components/renote-form.vue'),
props: ['note'],
props: {
note: {
type: Object,
required: true
}
},
data() { data() {
return { return {
wait: false, wait: false,
@ -29,6 +36,7 @@ export default Vue.extend({
visibility: this.$store.state.settings.defaultNoteVisibility visibility: this.$store.state.settings.defaultNoteVisibility
}; };
}, },
methods: { methods: {
ok(v: string) { ok(v: string) {
this.wait = true; this.wait = true;
@ -44,9 +52,11 @@ export default Vue.extend({
this.wait = false; this.wait = false;
}); });
}, },
cancel() { cancel() {
this.$emit('canceled'); this.$emit('canceled');
}, },
onQuote() { onQuote() {
this.quote = true; this.quote = true;
@ -54,6 +64,7 @@ export default Vue.extend({
(this.$refs.form as any).focus(); (this.$refs.form as any).focus();
}); });
}, },
onChildFormPosted() { onChildFormPosted() {
this.$emit('posted'); this.$emit('posted');
} }

View File

@ -4,7 +4,7 @@
<span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span> <span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
<span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span> <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span> <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
<span :data-active="src == 'global'" @click="src = 'global'"><fa icon="globe"/> {{ $t('global') }}</span> <span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
<span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span> <span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span>
<span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.title }}</span> <span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.title }}</span>
<div class="buttons"> <div class="buttons">
@ -43,7 +43,8 @@ export default Vue.extend({
src: 'home', src: 'home',
list: null, list: null,
tagTl: null, tagTl: null,
enableLocalTimeline: false enableLocalTimeline: false,
enableGlobalTimeline: false,
}; };
}, },
@ -65,7 +66,8 @@ export default Vue.extend({
created() { created() {
this.$root.getMeta().then(meta => { this.$root.getMeta().then(meta => {
this.enableLocalTimeline = !meta.disableLocalTimeline; this.enableLocalTimeline = !meta.disableLocalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
this.enableGlobalTimeline = !meta.disableGlobalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
}); });
if (this.$store.state.device.tl) { if (this.$store.state.device.tl) {

View File

@ -7,7 +7,8 @@
<router-link :to="user | userPage" class="name"> <router-link :to="user | userPage" class="name">
<mk-user-name :user="user"/> <mk-user-name :user="user"/>
</router-link> </router-link>
<span class="username">@{{ user | acct }}</span> <span class="username">@{{ user | acct }} <fa v-if="user.isLocked == true" class="locked" icon="lock" fixed-width/></span>
<div class="description"> <div class="description">
<misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/> <misskey-flavored-markdown v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
</div> </div>
@ -75,6 +76,9 @@ export default Vue.extend({
display block display block
opacity 0.7 opacity 0.7
> .locked
opacity 0.8
> .description > .description
margin 8px 0 16px 0 margin 8px 0 16px 0

View File

@ -18,6 +18,7 @@
:key="note.id" :key="note.id"
@update:note="onNoteUpdated(i, $event)" @update:note="onNoteUpdated(i, $event)"
:media-view="mediaView" :media-view="mediaView"
:compact="true"
:mini="true"/> :mini="true"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date"> <p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span><fa icon="angle-up"/>{{ note._datetext }}</span> <span><fa icon="angle-up"/>{{ note._datetext }}</span>

View File

@ -19,7 +19,7 @@
<span class="name"> <span class="name">
<mk-user-name :user="user"/> <mk-user-name :user="user"/>
</span> </span>
<span class="acct">@{{ user | acct }}</span> <span class="acct">@{{ user | acct }} <fa v-if="user.isLocked == true" class="locked" icon="lock" fixed-width/></span>
</div> </div>
</header> </header>
<div class="info"> <div class="info">
@ -169,6 +169,7 @@ export default Vue.extend({
this.$root.api('users/notes', { this.$root.api('users/notes', {
userId: this.user.id, userId: this.user.id,
fileType: image, fileType: image,
excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
limit: 9, limit: 9,
untilDate: new Date().getTime() + 1000 * 86400 * 365 untilDate: new Date().getTime() + 1000 * 86400 * 365
}).then(notes => { }).then(notes => {
@ -411,6 +412,9 @@ export default Vue.extend({
opacity 0.7 opacity 0.7
text-shadow 0 0 8px #000 text-shadow 0 0 8px #000
> .locked
opacity 0.8
> .info > .info
padding 16px padding 16px
font-size 12px font-size 12px

View File

@ -29,9 +29,11 @@ export default Vue.extend({
'image/png', 'image/png',
'image/gif' 'image/gif'
]; ];
this.$root.api('users/notes', { this.$root.api('users/notes', {
userId: this.user.id, userId: this.user.id,
fileType: image, fileType: image,
excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
limit: 9, limit: 9,
untilDate: new Date().getTime() + 1000 * 86400 * 365 untilDate: new Date().getTime() + 1000 * 86400 * 365
}).then(notes => { }).then(notes => {

View File

@ -35,7 +35,7 @@
<span class="signin" @click="signin">{{ $t('signin') }}</span> <span class="signin" @click="signin">{{ $t('signin') }}</span>
</p> </p>
<img src="/assets/ai.png" alt="" title="藍" class="char"> <img :src="meta.mascotImageUrl" alt="" title="藍" class="char">
</div> </div>
</div> </div>

View File

@ -124,6 +124,7 @@ import {
faMapMarker, faMapMarker,
faRobot, faRobot,
faHourglassHalf, faHourglassHalf,
faAlignLeft
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import { import {
@ -255,6 +256,7 @@ library.add(
faMapMarker, faMapMarker,
faRobot, faRobot,
faHourglassHalf, faHourglassHalf,
faAlignLeft,
farBell, farBell,
farEnvelope, farEnvelope,

View File

@ -37,6 +37,7 @@
</div> </div>
<div class="menu"> <div class="menu">
<div> <div>
<ui-input readonly :value="file.url">URL</ui-input>
<ui-button link :href="`${file.url}?download`" :download="file.name"><fa icon="download"/> {{ $t('download') }}</ui-button> <ui-button link :href="`${file.url}?download`" :download="file.name"><fa icon="download"/> {{ $t('download') }}</ui-button>
<ui-button @click="rename"><fa icon="pencil-alt"/> {{ $t('rename') }}</ui-button> <ui-button @click="rename"><fa icon="pencil-alt"/> {{ $t('rename') }}</ui-button>
<ui-button @click="move"><fa :icon="['far', 'folder-open']"/> {{ $t('move') }}</ui-button> <ui-button @click="move"><fa :icon="['far', 'folder-open']"/> {{ $t('move') }}</ui-button>
@ -200,7 +201,7 @@ export default Vue.extend({
color #bf4633 color #bf4633
> .menu > .menu
padding 14px padding 0 14px 14px 14px
border-top solid 1px var(--faceDivider) border-top solid 1px var(--faceDivider)
> div > div

View File

@ -54,7 +54,7 @@
<span class="visibility" v-if="appearNote.visibility != 'public'"> <span class="visibility" v-if="appearNote.visibility != 'public'">
<fa v-if="appearNote.visibility == 'home'" icon="home"/> <fa v-if="appearNote.visibility == 'home'" icon="home"/>
<fa v-if="appearNote.visibility == 'followers'" icon="unlock"/> <fa v-if="appearNote.visibility == 'followers'" icon="unlock"/>
<fa v-if="appearNote.visibility == 'specified'" icon="lock"/> <fa v-if="appearNote.visibility == 'specified'" icon="envelope"/>
</span> </span>
<span class="localOnly" v-if="appearNote.localOnly == true"><fa icon="heart"/></span> <span class="localOnly" v-if="appearNote.localOnly == true"><fa icon="heart"/></span>
</div> </div>
@ -66,7 +66,7 @@
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="['public', 'home'].includes(appearNote.visibility)" @click="renote()" title="Renote"> <button v-if="['public', 'home'].includes(appearNote.visibility)" @click="renote()" title="Renote">
<fa icon="retweet"/> <fa icon="retweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
</button> </button>
<button v-else> <button v-else>
<fa icon="ban"/> <fa icon="ban"/>

View File

@ -30,7 +30,7 @@
<mk-media-list :media-list="appearNote.files"/> <mk-media-list :media-list="appearNote.files"/>
</div> </div>
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/> <mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url"/> <mk-url-preview v-for="url in urls" :url="url" :key="url" :compact="compact"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> {{ $t('location') }}</a> <a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> {{ $t('location') }}</a>
<div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote"/></div> <div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote"/></div>
</div> </div>
@ -44,7 +44,7 @@
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="['public', 'home'].includes(appearNote.visibility)" @click="renote()" title="Renote"> <button v-if="['public', 'home'].includes(appearNote.visibility)" @click="renote()" title="Renote">
<fa icon="retweet"/> <fa icon="retweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
</button> </button>
<button v-else> <button v-else>
<fa icon="ban"/> <fa icon="ban"/>
@ -90,6 +90,11 @@ export default Vue.extend({
note: { note: {
type: Object, type: Object,
required: true required: true
},
compact: {
type: Boolean,
required: false,
default: false
} }
} }
}); });

View File

@ -15,7 +15,7 @@
<!-- トランジションを有効にするとなぜかメモリリークする --> <!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="transition" tag="div"> <component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notes" class="transition" tag="div">
<template v-for="(note, i) in _notes"> <template v-for="(note, i) in _notes">
<mk-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)"/> <mk-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" :compact="true"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date"> <p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span><fa icon="angle-up"/>{{ note._datetext }}</span> <span><fa icon="angle-up"/>{{ note._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span> <span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span>

View File

@ -41,7 +41,7 @@
<span v-if="visibility === 'public'"><fa icon="globe"/></span> <span v-if="visibility === 'public'"><fa icon="globe"/></span>
<span v-if="visibility === 'home'"><fa icon="home"/></span> <span v-if="visibility === 'home'"><fa icon="home"/></span>
<span v-if="visibility === 'followers'"><fa icon="unlock"/></span> <span v-if="visibility === 'followers'"><fa icon="unlock"/></span>
<span v-if="visibility === 'specified'"><fa icon="lock"/></span> <span v-if="visibility === 'specified'"><fa icon="envelope"/></span>
</button> </button>
</footer> </footer>
<input ref="file" class="file" type="file" multiple="multiple" @change="onChangeFile"/> <input ref="file" class="file" type="file" multiple="multiple" @change="onChangeFile"/>
@ -187,11 +187,11 @@ export default Vue.extend({
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`; const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
// 自分は除外 // 自分は除外
if (this.$store.state.i.username == x.username && x.host == null) return; if (this.$store.state.i.username == x.username && x.host == null) continue;
if (this.$store.state.i.username == x.username && x.host == host) return; if (this.$store.state.i.username == x.username && x.host == host) continue;
// 重複は除外 // 重複は除外
if (this.text.indexOf(`${mention} `) != -1) return; if (this.text.indexOf(`${mention} `) != -1) continue;
this.text += `${mention} `; this.text += `${mention} `;
} }

View File

@ -31,7 +31,7 @@
<span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span> <span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
<span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span> <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span> <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
<span :data-active="src == 'global'" @click="src = 'global'"><fa icon="globe"/> {{ $t('global') }}</span> <span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
<div class="hr"></div> <div class="hr"></div>
<span :data-active="src == 'mentions'" @click="src = 'mentions'"><fa icon="at"/> {{ $t('mentions') }}<i class="badge" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></span> <span :data-active="src == 'mentions'" @click="src = 'mentions'"><fa icon="at"/> {{ $t('mentions') }}<i class="badge" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></span>
<span :data-active="src == 'messages'" @click="src = 'messages'"><fa :icon="['far', 'envelope']"/> {{ $t('messages') }}<i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></span> <span :data-active="src == 'messages'" @click="src = 'messages'"><fa :icon="['far', 'envelope']"/> {{ $t('messages') }}<i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></span>
@ -79,7 +79,8 @@ export default Vue.extend({
lists: null, lists: null,
tagTl: null, tagTl: null,
showNav: false, showNav: false,
enableLocalTimeline: false enableLocalTimeline: false,
enableGlobalTimeline: false,
}; };
}, },
@ -112,7 +113,8 @@ export default Vue.extend({
created() { created() {
this.$root.getMeta().then(meta => { this.$root.getMeta().then(meta => {
this.enableLocalTimeline = !meta.disableLocalTimeline; this.enableLocalTimeline = !meta.disableLocalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
this.enableGlobalTimeline = !meta.disableGlobalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
}); });
if (this.$store.state.device.tl) { if (this.$store.state.device.tl) {

View File

@ -34,6 +34,7 @@ export default Vue.extend({
this.$root.api('users/notes', { this.$root.api('users/notes', {
userId: this.user.id, userId: this.user.id,
fileType: image, fileType: image,
excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
limit: 9, limit: 9,
untilDate: new Date().getTime() + 1000 * 86400 * 365 untilDate: new Date().getTime() + 1000 * 86400 * 365
}).then(notes => { }).then(notes => {

View File

@ -20,8 +20,9 @@ export const japaneseSushiSetTheme: Theme = require('../theme/japanese-sushi-set
export const gruvboxDarkTheme: Theme = require('../theme/gruvbox-dark.json5'); export const gruvboxDarkTheme: Theme = require('../theme/gruvbox-dark.json5');
export const monokaiTheme: Theme = require('../theme/monokai.json5'); export const monokaiTheme: Theme = require('../theme/monokai.json5');
export const colorfulTheme: Theme = require('../theme/colorful.json5'); export const colorfulTheme: Theme = require('../theme/colorful.json5');
export const naturalTheme: Theme = require('../theme/natural.json5'); export const rainyTheme: Theme = require('../theme/rainy.json5');
export const mauveTheme: Theme = require('../theme/mauve.json5'); export const mauveTheme: Theme = require('../theme/mauve.json5');
export const grayTheme: Theme = require('../theme/gray.json5');
export const builtinThemes = [ export const builtinThemes = [
lightTheme, lightTheme,
@ -34,8 +35,9 @@ export const builtinThemes = [
gruvboxDarkTheme, gruvboxDarkTheme,
monokaiTheme, monokaiTheme,
colorfulTheme, colorfulTheme,
naturalTheme, rainyTheme,
mauveTheme, mauveTheme,
grayTheme,
]; ];
export function applyTheme(theme: Theme, persisted = true) { export function applyTheme(theme: Theme, persisted = true) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -16,5 +16,6 @@
renoteGradient: '#ffe1c7', renoteGradient: '#ffe1c7',
renoteText: '$primary', renoteText: '$primary',
quoteBorder: '$primary', quoteBorder: '$primary',
mfmMention: '#56907b',
}, },
} }

View File

@ -0,0 +1,21 @@
{
id: '56ff14eb-1e6d-4c0c-9e84-71eb156234e5',
name: 'Gray',
author: 'syuilo',
base: 'light',
vars: {
primary: '#C03233',
secondary: 'rgb(213, 213, 213)',
text: 'rgb(102, 102, 102)',
},
props: {
renoteGradient: '#bdbdbd',
renoteText: '$primary',
quoteBorder: '$primary',
desktopPostFormBg: '#ececec',
},
}

View File

@ -1,23 +0,0 @@
{
id: 'b4b7d5fc-08d0-4915-b1cf-4090771e1a84',
name: 'Natural',
author: 'syuilo',
base: 'light',
vars: {
primary: 'rgb(0, 179, 104)',
secondary: '#fef8ec',
text: 'rgb(136, 132, 119)',
},
props: {
bg: 'rgb(248, 239, 221)',
mfmMention: 'rgb(238, 150, 43)',
mfmMentionForeground: '#fff',
mfmUrl: 'rgb(0, 189, 214)',
mfmLink: 'rgb(255, 87, 146)',
mfmHashtag: 'rgb(179, 134, 0)'
},
}

View File

@ -0,0 +1,20 @@
{
id: '2058b33e-5127-4e63-ae67-a900f3a11723',
name: 'Rainy',
author: 'syuilo',
base: 'light',
vars: {
primary: 'rgb(100, 184, 193)',
secondary: 'rgb(228, 234, 234)',
text: 'rgb(85, 94, 92)',
},
props: {
renoteGradient: '#bcd0d0',
renoteText: '$primary',
quoteBorder: '$primary',
},
}

View File

@ -1,3 +1,3 @@
{ {
"copyright": "Copyright (c) 2014-2018 syuilo" "copyright": "Copyright (c) 2014-2019 syuilo"
} }

View File

@ -205,7 +205,7 @@ const mfm = P.createLanguage({
hashtag: r => hashtag: r =>
P((input, i) => { P((input, i) => {
const text = input.substr(i); const text = input.substr(i);
const match = text.match(/^#([^\s\.,!\?#]+)/i); const match = text.match(/^#([^\s\.,!\?#:]+)/i);
if (!match) return P.makeFailure(i, 'not a hashtag'); if (!match) return P.makeFailure(i, 'not a hashtag');
let hashtag = match[1]; let hashtag = match[1];
hashtag = removeOrphanedBrackets(hashtag); hashtag = removeOrphanedBrackets(hashtag);

View File

@ -19,6 +19,7 @@ const defaultMeta: any = {
enableExternalUserRecommendation: false, enableExternalUserRecommendation: false,
externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}', externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}',
externalUserRecommendationTimeout: 300000, externalUserRecommendationTimeout: 300000,
mascotImageUrl: '/assets/ai.png',
errorImageUrl: 'https://ai.misskey.xyz/aiart/yubitun.png', errorImageUrl: 'https://ai.misskey.xyz/aiart/yubitun.png',
enableServiceWorker: false enableServiceWorker: false
}; };

View File

@ -184,7 +184,9 @@ export type IMeta = {
disableRegistration?: boolean; disableRegistration?: boolean;
disableLocalTimeline?: boolean; disableLocalTimeline?: boolean;
disableGlobalTimeline?: boolean;
hidedTags?: string[]; hidedTags?: string[];
mascotImageUrl?: string;
bannerUrl?: string; bannerUrl?: string;
errorImageUrl?: string; errorImageUrl?: string;

View File

@ -372,7 +372,14 @@ export const pack = async (
//#endregion //#endregion
if (_note.user.isCat && _note.text) { if (_note.user.isCat && _note.text) {
_note.text = _note.text.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ'); _note.text = (_note.text
// ja-JP
.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
// ko-KR
.replace(/[나-낳]/g, (match: string) => String.fromCharCode(
match.codePointAt(0) + '냐'.charCodeAt(0) - '나'.charCodeAt(0)
))
);
} }
if (!opts.skipHide) { if (!opts.skipHide) {

View File

@ -376,6 +376,8 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
$set: { $set: {
'_follower.sharedInbox': person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined) '_follower.sharedInbox': person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined)
} }
}, {
multi: true
}); });
await updateFeatured(exist._id).catch(err => console.log(err)); await updateFeatured(exist._id).catch(err => console.log(err));

View File

@ -3,6 +3,8 @@ const { sign } = require('http-signature');
import { URL } from 'url'; import { URL } from 'url';
import * as debug from 'debug'; import * as debug from 'debug';
const crypto = require('crypto'); const crypto = require('crypto');
const { lookup } = require('lookup-dns-cache');
const promiseAny = require('promise-any');
import config from '../../config'; import config from '../../config';
import { ILocalUser } from '../../models/user'; import { ILocalUser } from '../../models/user';
@ -10,12 +12,12 @@ import { publishApLogStream } from '../../stream';
const log = debug('misskey:activitypub:deliver'); const log = debug('misskey:activitypub:deliver');
export default (user: ILocalUser, url: string, object: any) => new Promise((resolve, reject) => { export default (user: ILocalUser, url: string, object: any) => new Promise(async (resolve, reject) => {
log(`--> ${url}`); log(`--> ${url}`);
const timeout = 10 * 1000; const timeout = 10 * 1000;
const { protocol, hostname, port, pathname, search } = new URL(url); const { protocol, host, hostname, port, pathname, search } = new URL(url);
const data = JSON.stringify(object); const data = JSON.stringify(object);
@ -23,14 +25,19 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso
sha256.update(data); sha256.update(data);
const hash = sha256.digest('base64'); const hash = sha256.digest('base64');
const addr = await resolveAddr(hostname).catch(e => reject(e));
if (!addr) return;
const req = request({ const req = request({
protocol, protocol,
hostname, hostname: addr,
setHost: false,
port, port,
method: 'POST', method: 'POST',
path: pathname + search, path: pathname + search,
timeout, timeout,
headers: { headers: {
'Host': host,
'User-Agent': config.user_agent, 'User-Agent': config.user_agent,
'Content-Type': 'application/activity+json', 'Content-Type': 'application/activity+json',
'Digest': `SHA-256=${hash}` 'Digest': `SHA-256=${hash}`
@ -75,3 +82,23 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso
}); });
//#endregion //#endregion
}); });
/**
* Resolve host (with cached, asynchrony)
*/
async function resolveAddr(domain: string) {
// v4/v6で先に取得できた方を採用する
return await promiseAny([
resolveAddrInner(domain, { ipv6: false }),
resolveAddrInner(domain, { ipv6: true })
]);
}
function resolveAddrInner(domain: string, options = { }): Promise<string> {
return new Promise((res, rej) => {
lookup(domain, options, (error: any, address: string) => {
if (error) return rej(error);
return res(address);
});
});
}

View File

@ -83,7 +83,7 @@ router.get('/notes/:note', async (ctx, next) => {
} }
ctx.body = pack(await renderNote(note, false)); ctx.body = pack(await renderNote(note, false));
ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); ctx.set('Cache-Control', 'public, max-age=180');
setResponseType(ctx); setResponseType(ctx);
}); });
@ -162,7 +162,9 @@ async function userInfo(ctx: Router.IRouterContext, user: IUser) {
setResponseType(ctx); setResponseType(ctx);
} }
router.get('/users/:user', async ctx => { router.get('/users/:user', async (ctx, next) => {
if (!isActivityPubReq(ctx)) return await next();
if (!ObjectID.isValid(ctx.params.user)) { if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404; ctx.status = 404;
return; return;

View File

@ -77,5 +77,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
skip: ps.offset skip: ps.offset
}); });
res(await packMany(files, { detail: true, withUser: true })); res(await packMany(files, { detail: true, withUser: true, self: true }));
})); }));

View File

@ -0,0 +1,123 @@
import $ from 'cafy';
import User, { pack } from '../../../../models/user';
import define from '../../define';
export const meta = {
requireCredential: true,
requireModerator: true,
params: {
limit: {
validator: $.num.optional.range(1, 100),
default: 10
},
offset: {
validator: $.num.optional.min(0),
default: 0
},
sort: {
validator: $.str.optional.or([
'+follower',
'-follower',
'+createdAt',
'-createdAt',
'+updatedAt',
'-updatedAt',
]),
},
state: {
validator: $.str.optional.or([
'all',
'admin',
'moderator',
'adminOrModerator',
'verified',
'suspended',
]),
default: 'all'
},
origin: {
validator: $.str.optional.or([
'combined',
'local',
'remote',
]),
default: 'local'
}
}
};
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
let _sort;
if (ps.sort) {
if (ps.sort == '+follower') {
_sort = {
followersCount: -1
};
} else if (ps.sort == '-follower') {
_sort = {
followersCount: 1
};
} else if (ps.sort == '+createdAt') {
_sort = {
createdAt: -1
};
} else if (ps.sort == '+updatedAt') {
_sort = {
updatedAt: -1
};
} else if (ps.sort == '-createdAt') {
_sort = {
createdAt: 1
};
} else if (ps.sort == '-updatedAt') {
_sort = {
updatedAt: 1
};
}
} else {
_sort = {
_id: -1
};
}
const q = {
$and: []
} as any;
// state
q.$and.push(
ps.state == 'admin' ? { isAdmin: true } :
ps.state == 'moderator' ? { isModerator: true } :
ps.state == 'adminOrModerator' ? {
$or: [{
isAdmin: true
}, {
isModerator: true
}]
} :
ps.state == 'verified' ? { isVerified: true } :
ps.state == 'suspended' ? { isSuspended: true } :
{}
);
// origin
q.$and.push(
ps.origin == 'local' ? { host: null } :
ps.origin == 'remote' ? { host: { $ne: null } } :
{}
);
const users = await User
.find(q, {
limit: ps.limit,
sort: _sort,
skip: ps.offset
});
res(await Promise.all(users.map(user => pack(user, me, { detail: true }))));
}));

View File

@ -37,6 +37,10 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
return rej('cannot suspend admin'); return rej('cannot suspend admin');
} }
if (user.isModerator) {
return rej('cannot suspend moderator');
}
await User.findOneAndUpdate({ await User.findOneAndUpdate({
_id: user._id _id: user._id
}, { }, {

View File

@ -32,6 +32,13 @@ export const meta = {
} }
}, },
disableGlobalTimeline: {
validator: $.bool.optional.nullable,
desc: {
'ja-JP': 'グローバルタイムラインを無効にするか否か'
}
},
hidedTags: { hidedTags: {
validator: $.arr($.str).optional.nullable, validator: $.arr($.str).optional.nullable,
desc: { desc: {
@ -39,6 +46,13 @@ export const meta = {
} }
}, },
mascotImageUrl: {
validator: $.str.optional.nullable,
desc: {
'ja-JP': 'インスタンスキャラクター画像のURL'
}
},
bannerUrl: { bannerUrl: {
validator: $.str.optional.nullable, validator: $.str.optional.nullable,
desc: { desc: {
@ -324,10 +338,18 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
set.disableLocalTimeline = ps.disableLocalTimeline; set.disableLocalTimeline = ps.disableLocalTimeline;
} }
if (typeof ps.disableGlobalTimeline === 'boolean') {
set.disableGlobalTimeline = ps.disableGlobalTimeline;
}
if (Array.isArray(ps.hidedTags)) { if (Array.isArray(ps.hidedTags)) {
set.hidedTags = ps.hidedTags; set.hidedTags = ps.hidedTags;
} }
if (ps.mascotImageUrl !== undefined) {
set.mascotImageUrl = ps.mascotImageUrl;
}
if (ps.bannerUrl !== undefined) { if (ps.bannerUrl !== undefined) {
set.bannerUrl = ps.bannerUrl; set.bannerUrl = ps.bannerUrl;
} }

View File

@ -40,6 +40,16 @@ export const meta = {
markAsRead: { markAsRead: {
validator: $.bool.optional, validator: $.bool.optional,
default: true default: true
},
includeTypes: {
validator: $.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'poll_vote', 'receiveFollowRequest'])).optional,
default: [] as string[]
},
excludeTypes: {
validator: $.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'poll_vote', 'receiveFollowRequest'])).optional,
default: [] as string[]
} }
} }
}; };
@ -89,6 +99,16 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}; };
} }
if (ps.includeTypes.length > 0) {
query.type = {
$in: ps.includeTypes
};
} else if (ps.excludeTypes.length > 0) {
query.type = {
$nin: ps.excludeTypes
};
}
const notifications = await Notification const notifications = await Notification
.find(query, { .find(query, {
limit: ps.limit, limit: ps.limit,

View File

@ -59,12 +59,14 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
broadcasts: instance.broadcasts || [], broadcasts: instance.broadcasts || [],
disableRegistration: instance.disableRegistration, disableRegistration: instance.disableRegistration,
disableLocalTimeline: instance.disableLocalTimeline, disableLocalTimeline: instance.disableLocalTimeline,
disableGlobalTimeline: instance.disableGlobalTimeline,
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb, driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb, driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
cacheRemoteFiles: instance.cacheRemoteFiles, cacheRemoteFiles: instance.cacheRemoteFiles,
enableRecaptcha: instance.enableRecaptcha, enableRecaptcha: instance.enableRecaptcha,
recaptchaSiteKey: instance.recaptchaSiteKey, recaptchaSiteKey: instance.recaptchaSiteKey,
swPublickey: instance.swPublicKey, swPublickey: instance.swPublicKey,
mascotImageUrl: instance.mascotImageUrl,
bannerUrl: instance.bannerUrl, bannerUrl: instance.bannerUrl,
errorImageUrl: instance.errorImageUrl, errorImageUrl: instance.errorImageUrl,
maxNoteTextLength: instance.maxNoteTextLength, maxNoteTextLength: instance.maxNoteTextLength,
@ -80,6 +82,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
response.features = { response.features = {
registration: !instance.disableRegistration, registration: !instance.disableRegistration,
localTimeLine: !instance.disableLocalTimeline, localTimeLine: !instance.disableLocalTimeline,
globalTimeLine: !instance.disableGlobalTimeline,
elasticsearch: config.elasticsearch ? true : false, elasticsearch: config.elasticsearch ? true : false,
recaptcha: instance.enableRecaptcha, recaptcha: instance.enableRecaptcha,
objectStorage: config.drive && config.drive.storage === 'minio', objectStorage: config.drive && config.drive.storage === 'minio',

View File

@ -4,6 +4,7 @@ import Mute from '../../../../models/mute';
import { packMany } from '../../../../models/note'; import { packMany } from '../../../../models/note';
import define from '../../define'; import define from '../../define';
import { countIf } from '../../../../prelude/array'; import { countIf } from '../../../../prelude/array';
import fetchMeta from '../../../../misc/fetch-meta';
export const meta = { export const meta = {
desc: { desc: {
@ -51,6 +52,13 @@ export const meta = {
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, (ps, user) => new Promise(async (res, rej) => {
const meta = await fetchMeta();
if (meta.disableGlobalTimeline) {
if (user == null || (!user.isAdmin && !user.isModerator)) {
return rej('global timeline disabled');
}
}
// Check if only one of sinceId, untilId, sinceDate, untilDate specified // Check if only one of sinceId, untilId, sinceDate, untilDate specified
if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) {
return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified'); return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');

View File

@ -5,6 +5,7 @@ import { getFriends } from '../../common/get-friends';
import { packMany } from '../../../../models/note'; import { packMany } from '../../../../models/note';
import define from '../../define'; import define from '../../define';
import { countIf } from '../../../../prelude/array'; import { countIf } from '../../../../prelude/array';
import fetchMeta from '../../../../misc/fetch-meta';
export const meta = { export const meta = {
desc: { desc: {
@ -91,6 +92,11 @@ export const meta = {
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, (ps, user) => new Promise(async (res, rej) => {
const meta = await fetchMeta();
if (meta.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
return rej('local timeline disabled');
}
// Check if only one of sinceId, untilId, sinceDate, untilDate specified // Check if only one of sinceId, untilId, sinceDate, untilDate specified
if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) {
return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified'); return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');
@ -135,13 +141,30 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}] }]
}); });
const visibleQuery = user == null ? [{
visibility: { $in: [ 'public', 'home' ] }
}] : [{
visibility: { $in: [ 'public', 'home' ] }
}, {
// myself (for specified/private)
userId: user._id
}, {
// to me (for specified)
visibleUserIds: { $in: [ user._id ] }
}];
const query = { const query = {
$and: [{ $and: [{
deletedAt: null, deletedAt: null,
$or: [{ $or: [{
// フォローしている人の投稿 $and: [{
$or: followQuery // フォローしている人の投稿
$or: followQuery
}, {
// visible for me
$or: visibleQuery
}]
}, { }, {
// public only // public only
visibility: 'public', visibility: 'public',

View File

@ -4,6 +4,7 @@ import Mute from '../../../../models/mute';
import { packMany } from '../../../../models/note'; import { packMany } from '../../../../models/note';
import define from '../../define'; import define from '../../define';
import { countIf } from '../../../../prelude/array'; import { countIf } from '../../../../prelude/array';
import fetchMeta from '../../../../misc/fetch-meta';
export const meta = { export const meta = {
desc: { desc: {
@ -66,6 +67,13 @@ export const meta = {
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, (ps, user) => new Promise(async (res, rej) => {
const meta = await fetchMeta();
if (meta.disableLocalTimeline) {
if (user == null || (!user.isAdmin && !user.isModerator)) {
return rej('local timeline disabled');
}
}
// Check if only one of sinceId, untilId, sinceDate, untilDate specified // Check if only one of sinceId, untilId, sinceDate, untilDate specified
if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) {
return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified'); return rej('only one of sinceId, untilId, sinceDate, untilDate can be specified');

View File

@ -45,7 +45,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
if (note.deletedAt != null) { if (note.deletedAt != null) {
return rej('this not is already deleted'); return rej('this note is already deleted');
} }
try { try {

View File

@ -103,6 +103,18 @@ export const meta = {
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, (ps, me) => new Promise(async (res, rej) => {
const visibleQuery = me == null ? [{
visibility: { $in: [ 'public', 'home' ] }
}] : [{
visibility: { $in: [ 'public', 'home' ] }
}, {
// myself (for specified/private)
userId: me._id
}, {
// to me (for specified)
visibleUserIds: { $in: [ me._id ] }
}];
const q: any = { const q: any = {
$and: [ps.tag ? { $and: [ps.tag ? {
tagsLower: ps.tag.toLowerCase() tagsLower: ps.tag.toLowerCase()
@ -113,7 +125,8 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
})) }))
})) }))
}], }],
deletedAt: { $exists: false } deletedAt: { $exists: false },
$or: visibleQuery
}; };
const push = (x: any) => q.$and.push(x); const push = (x: any) => q.$and.push(x);

View File

@ -139,12 +139,29 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}] }]
}); });
const visibleQuery = user == null ? [{
visibility: { $in: [ 'public', 'home' ] }
}] : [{
visibility: { $in: [ 'public', 'home' ] }
}, {
// myself (for specified/private)
userId: user._id
}, {
// to me (for specified)
visibleUserIds: { $in: [ user._id ] }
}];
const query = { const query = {
$and: [{ $and: [{
deletedAt: null, deletedAt: null,
// フォローしている人の投稿 $and: [{
$or: followQuery, // フォローしている人の投稿
$or: followQuery
}, {
// visible for me
$or: visibleQuery
}],
// mute // mute
userId: { userId: {

View File

@ -146,12 +146,29 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}] }]
})); }));
const visibleQuery = user == null ? [{
visibility: { $in: [ 'public', 'home' ] }
}] : [{
visibility: { $in: [ 'public', 'home' ] }
}, {
// myself (for specified/private)
userId: user._id
}, {
// to me (for specified)
visibleUserIds: { $in: [ user._id ] }
}];
const query = { const query = {
$and: [{ $and: [{
deletedAt: null, deletedAt: null,
// リストに入っている人のタイムラインへの投稿 $and: [{
$or: listQuery, // リストに入っている人のタイムラインへの投稿
$or: listQuery
}, {
// visible for me
$or: visibleQuery
}],
// mute // mute
userId: { userId: {

View File

@ -124,6 +124,14 @@ export const meta = {
'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します' 'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します'
} }
}, },
excludeNsfw: {
validator: $.bool.optional,
default: false,
desc: {
'ja-JP': 'true にすると、NSFW指定されたファイルを除外します(fileTypeが指定されている場合のみ有効)'
}
},
} }
}; };
@ -155,10 +163,23 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
//#region Construct query //#region Construct query
const sort = { } as any; const sort = { } as any;
const visibleQuery = me == null ? [{
visibility: { $in: [ 'public', 'home' ] }
}] : [{
visibility: { $in: [ 'public', 'home' ] }
}, {
// myself (for specified/private)
userId: me._id
}, {
// to me (for specified)
visibleUserIds: { $in: [ me._id ] }
}];
const query = { const query = {
$and: [ {} ], $and: [ {} ],
deletedAt: null, deletedAt: null,
userId: user._id userId: user._id,
$or: visibleQuery
} as any; } as any;
if (ps.sinceId) { if (ps.sinceId) {
@ -220,6 +241,12 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
query['_files.contentType'] = { query['_files.contentType'] = {
$in: ps.fileType $in: ps.fileType
}; };
if (ps.excludeNsfw) {
query['_files.metadata.isSensitive'] = {
$ne: true
};
}
} }
//#endregion //#endregion

View File

@ -3,6 +3,7 @@ import Mute from '../../../../models/mute';
import { pack } from '../../../../models/note'; import { pack } from '../../../../models/note';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'globalTimeline'; public readonly chName = 'globalTimeline';
@ -13,6 +14,11 @@ export default class extends Channel {
@autobind @autobind
public async init(params: any) { public async init(params: any) {
const meta = await fetchMeta();
if (meta.disableGlobalTimeline) {
if (this.user == null || (!this.user.isAdmin && !this.user.isModerator)) return;
}
// Subscribe events // Subscribe events
this.subscriber.on('globalTimeline', this.onNote); this.subscriber.on('globalTimeline', this.onNote);

View File

@ -3,6 +3,7 @@ import Mute from '../../../../models/mute';
import { pack } from '../../../../models/note'; import { pack } from '../../../../models/note';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'hybridTimeline'; public readonly chName = 'hybridTimeline';
@ -13,6 +14,9 @@ export default class extends Channel {
@autobind @autobind
public async init(params: any) { public async init(params: any) {
const meta = await fetchMeta();
if (meta.disableLocalTimeline && !this.user.isAdmin && !this.user.isModerator) return;
// Subscribe events // Subscribe events
this.subscriber.on('hybridTimeline', this.onNewNote); this.subscriber.on('hybridTimeline', this.onNewNote);
this.subscriber.on(`hybridTimeline:${this.user._id}`, this.onNewNote); this.subscriber.on(`hybridTimeline:${this.user._id}`, this.onNewNote);

View File

@ -3,6 +3,7 @@ import Mute from '../../../../models/mute';
import { pack } from '../../../../models/note'; import { pack } from '../../../../models/note';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel'; import Channel from '../channel';
import fetchMeta from '../../../../misc/fetch-meta';
export default class extends Channel { export default class extends Channel {
public readonly chName = 'localTimeline'; public readonly chName = 'localTimeline';
@ -13,6 +14,11 @@ export default class extends Channel {
@autobind @autobind
public async init(params: any) { public async init(params: any) {
const meta = await fetchMeta();
if (meta.disableLocalTimeline) {
if (this.user == null || (!this.user.isAdmin && !this.user.isModerator)) return;
}
// Subscribe events // Subscribe events
this.subscriber.on('localTimeline', this.onNote); this.subscriber.on('localTimeline', this.onNote);

View File

@ -2,6 +2,7 @@
* Web Client Server * Web Client Server
*/ */
import * as os from 'os';
import ms = require('ms'); import ms = require('ms');
import * as Koa from 'koa'; import * as Koa from 'koa';
import * as Router from 'koa-router'; import * as Router from 'koa-router';
@ -18,6 +19,8 @@ import config from '../../config';
import Note, { pack as packNote } from '../../models/note'; import Note, { pack as packNote } from '../../models/note';
import getNoteSummary from '../../misc/get-note-summary'; import getNoteSummary from '../../misc/get-note-summary';
import fetchMeta from '../../misc/fetch-meta'; import fetchMeta from '../../misc/fetch-meta';
import Emoji from '../../models/emoji';
const pkg = require('../../../package.json');
const client = `${__dirname}/../../client/`; const client = `${__dirname}/../../client/`;
@ -148,6 +151,27 @@ router.get('/@:user', async (ctx, next) => {
} }
}); });
router.get('/users/:user', async ctx => {
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
const user = await User.findOne({
_id: userId,
host: null
});
if (user === null) {
ctx.status = 404;
return;
}
ctx.redirect(`/@${user.username}${ user.host == null ? '' : '@' + user.host}`);
});
// Note // Note
router.get('/notes/:note', async ctx => { router.get('/notes/:note', async ctx => {
if (ObjectID.isValid(ctx.params.note)) { if (ObjectID.isValid(ctx.params.note)) {
@ -159,7 +183,12 @@ router.get('/notes/:note', async ctx => {
note: _note, note: _note,
summary: getNoteSummary(_note) summary: getNoteSummary(_note)
}); });
ctx.set('Cache-Control', 'private, max-age=0, must-revalidate');
if (['public', 'home'].includes(note.visibility)) {
ctx.set('Cache-Control', 'public, max-age=180');
} else {
ctx.set('Cache-Control', 'private, max-age=0, must-revalidate');
}
return; return;
} }
@ -169,6 +198,27 @@ router.get('/notes/:note', async ctx => {
}); });
//#endregion //#endregion
router.get('/info', async ctx => {
const meta = await fetchMeta();
const emojis = await Emoji.find({ host: null }, {
fields: {
_id: false
}
});
await ctx.render('info', {
version: pkg.version,
machine: os.hostname(),
os: os.platform(),
node: process.version,
cpu: {
model: os.cpus()[0].model,
cores: os.cpus().length
},
emojis: emojis,
meta: meta
});
});
// Render base html for all requests // Render base html for all requests
router.get('*', async ctx => { router.get('*', async ctx => {
const meta = await fetchMeta(); const meta = await fetchMeta();

View File

@ -0,0 +1,128 @@
doctype html
html
head
meta(charset='utf-8')
meta(name='application-name' content='Misskey')
title Misskey
style.
html {
font-family: sans-serif;
}
main {
max-width: 934px;
margin: 0 auto;
}
header {
padding: 5px;
background: rgb(153, 153, 204);
border: 1px solid #000;
}
header:after {
content: '';
display: block;
clear: both;
}
header > h1 {
float: left;
font-size: 2em;
}
header > img {
float: right;
width: 220px;
}
table {
margin: 1em 0;
width: 100%;
border-collapse: collapse;
}
table tr th {
background-color: #ccf;
border: 1px solid #000;
width: 300px;
font-weight: bold;
padding: 4px 5px;
text-align: left;
}
table tr td {
background-color: #ddd;
border: 1px solid #000;
padding: 4px 5px;
}
body
main
header
h1 Misskey Version #{version}
img(src='/assets/misskey-php-like-logo.png' alt='')
table
tr
th Instance
td= meta.name
tr
th Description
td= meta.description
tr
th Maintainer
td
= meta.maintainer.name
| &lt;#{meta.maintainer.email}&gt;
tr
th System
td= os
tr
th Node version
td= node
tr
th Machine
td= machine
tr
th CPU
td= cpu.model
tr
th Original users
td= meta.stats.originalUsersCount
tr
th Original notes
td= meta.stats.originalNotesCount
tr
th Registration
td= !meta.disableRegistration ? 'yes' : 'no'
tr
th reCAPTCHA enabled
td= meta.enableRecaptcha ? 'enabled' : 'disabled'
tr
th LTL(STL) enabled
td= !meta.disableLocalTimeline ? 'enabled' : 'disabled'
tr
th GTL enabled
td= !meta.disableGlobalTimeline ? 'enabled' : 'disabled'
tr
th Cache remote files
td= meta.cacheRemoteFiles ? 'yes' : 'no'
tr
th Drive capacity per local user
td
= meta.localDriveCapacityMb
| MB
tr
th Drive capacity per remote user
td
= meta.remoteDriveCapacityMb
| MB
tr
th Max text length
td= meta.maxNoteTextLength
tr
th Emojis
td
each emoji in emojis
| :#{emoji.name}:
= ' '

View File

@ -4,10 +4,11 @@ import * as fs from 'fs';
import * as mongodb from 'mongodb'; import * as mongodb from 'mongodb';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import * as debug from 'debug'; import * as debug from 'debug';
import fileType = require('file-type');
import * as Minio from 'minio'; import * as Minio from 'minio';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
import * as sharp from 'sharp'; import * as sharp from 'sharp';
import * as fileType from 'file-type';
import * as isSvg from 'is-svg';
import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file'; import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file';
import DriveFolder from '../../models/drive-folder'; import DriveFolder from '../../models/drive-folder';
@ -320,6 +321,8 @@ export default async function(
const type = fileType(buffer); const type = fileType(buffer);
if (type) { if (type) {
res([type.mime, type.ext]); res([type.mime, type.ext]);
} else if (isSvg(buffer)) {
res(['image/svg+xml', 'svg'])
} else { } else {
// 種類が同定できなかったら application/octet-stream にする // 種類が同定できなかったら application/octet-stream にする
res(['application/octet-stream', null]); res(['application/octet-stream', null]);

View File

@ -183,11 +183,6 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
data.visibleUsers.push(u); data.visibleUsers.push(u);
} }
} }
// ダイレクト投稿でユーザーが指定されていなかったらreject
if (data.visibleUsers.length === 0) {
return rej('Target user is not specified');
}
} }
const note = await insertNote(user, data, tags, emojis, mentionedUsers); const note = await insertNote(user, data, tags, emojis, mentionedUsers);
@ -546,7 +541,7 @@ async function publishToFollowers(note: INote, user: IUser, noteActivity: any) {
if (!following.stalk) { if (!following.stalk) {
// この投稿が返信ならスキップ // この投稿が返信ならスキップ
if (note.replyId && !note._reply.userId.equals(following.followerId) && !note._reply.userId.equals(note.userId)) if (note.replyId && !note._reply.userId.equals(following.followerId) && !note._reply.userId.equals(note.userId))
return; continue;
} }
// Publish event to followers stream // Publish event to followers stream

View File

@ -1,31 +1,17 @@
import * as mongo from 'mongodb'; import * as mongo from 'mongodb';
import redis from './db/redis'; import redis from './db/redis';
import Xev from 'xev'; import Xev from 'xev';
import { IMeta } from './models/meta';
import fetchMeta from './misc/fetch-meta';
type ID = string | mongo.ObjectID; type ID = string | mongo.ObjectID;
class Publisher { class Publisher {
private ev: Xev; private ev: Xev;
private meta: IMeta;
constructor() { constructor() {
// Redisがインストールされてないときはプロセス間通信を使う // Redisがインストールされてないときはプロセス間通信を使う
if (redis == null) { if (redis == null) {
this.ev = new Xev(); this.ev = new Xev();
} }
setInterval(async () => {
this.meta = await fetchMeta();
}, 5000);
}
public fetchMeta = async () => {
if (this.meta != null) return this.meta;
this.meta = await fetchMeta();
return this.meta;
} }
private publish = (channel: string, type: string, value?: any): void => { private publish = (channel: string, type: string, value?: any): void => {
@ -83,14 +69,10 @@ class Publisher {
} }
public publishLocalTimelineStream = async (note: any): Promise<void> => { public publishLocalTimelineStream = async (note: any): Promise<void> => {
const meta = await this.fetchMeta();
if (meta.disableLocalTimeline) return;
this.publish('localTimeline', null, note); this.publish('localTimeline', null, note);
} }
public publishHybridTimelineStream = async (userId: ID, note: any): Promise<void> => { public publishHybridTimelineStream = async (userId: ID, note: any): Promise<void> => {
const meta = await this.fetchMeta();
if (meta.disableLocalTimeline) return;
this.publish(userId ? `hybridTimeline:${userId}` : 'hybridTimeline', null, note); this.publish(userId ? `hybridTimeline:${userId}` : 'hybridTimeline', null, note);
} }

View File

@ -0,0 +1,57 @@
// node built/tools/show-signin-history username
// => {Success} {Date} {IPAddrsss}
// node built/tools/show-signin-history username user-agent,x-forwarded-for
// with user-agent and x-forwarded-for
// node built/tools/show-signin-history username all
// with full request headers
import User from '../models/user';
import Signin from '../models/signin';
async function main(username: string, headers: string[]) {
const user = await User.findOne({
host: null,
usernameLower: username.toLowerCase(),
});
if (user === null) throw 'User not found';
const history = await Signin.find({
userId: user._id
});
for (const signin of history) {
console.log(`${signin.success ? 'OK' : 'NG'} ${signin.createdAt ? signin.createdAt.toISOString() : 'Unknown'} ${signin.ip}`);
// headers
if (headers != null) {
for (const key of Object.keys(signin.headers)) {
if (headers.includes('all') || headers.includes(key)) {
console.log(` ${key}: ${signin.headers[key]}`);
}
}
}
}
}
// get args
const args = process.argv.slice(2);
let username = args[0];
let headers: string[];
if (args[1] != null) {
headers = args[1].split(/,/).map(header => header.toLowerCase());
}
// normalize args
username = username.replace(/^@/, '');
main(username, headers).then(() => {
process.exit(0);
}).catch(e => {
console.warn(e);
process.exit(1);
});

View File

@ -808,6 +808,20 @@ describe('API', () => {
expect(res).have.status(400); expect(res).have.status(400);
})); }));
it('SVGファイルを作成できる', async(async () => {
const izumi = await signup({ username: 'izumi' });
const res = await assert.request(server)
.post('/drive/files/create')
.field('i', izumi.token)
.attach('file', fs.readFileSync(__dirname + '/resources/image.svg'), 'image.svg');
expect(res).have.status(200);
expect(res.body).be.a('object');
expect(res.body).have.property('name').eql('image.svg');
expect(res.body).have.property('type').eql('image/svg+xml');
}));
}); });
describe('drive/files/update', () => { describe('drive/files/update', () => {

View File

@ -357,6 +357,14 @@ describe('MFM', () => {
]); ]);
}); });
it('ignore colon', () => {
const tokens = analyze('#Foo:');
assert.deepStrictEqual(tokens, [
leaf('hashtag', { hashtag: 'Foo' }),
text(':'),
]);
});
it('allow including number', () => { it('allow including number', () => {
const tokens = analyze('#foo123'); const tokens = analyze('#foo123');
assert.deepStrictEqual(tokens, [ assert.deepStrictEqual(tokens, [

1
test/resources/image.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path fill="#FF40A4" d="M128 80c-16 4-20 24-20 48v16c0 8-8 16-20.3 8 4.3 20 24.3 28 40.3 24s20-24 20-48v-16c0-8 8-16 20.3-8C164 84 144 76 128 80"/><path fill="#FFBF40" d="M192 80c-16 4-20 24-20 48v16c0 8-8 16-20.3 8 4.3 20 24.3 28 40.3 24s20-24 20-48v-16c0-8 8-16 20.3-8C228 84 208 76 192 80"/><path fill="#408EFF" d="M64 80c-16 4-20 24-20 48v16c0 8-8 16-20.3 8C28 172 48 180 64 176s20-24 20-48v-16c0-8 8-16 20.3-8C100 84 80 76 64 80"/></svg>

After

Width:  |  Height:  |  Size: 505 B