Compare commits
131 Commits
Author | SHA1 | Date | |
---|---|---|---|
14b16b4733 | |||
256c216dfb | |||
13cee2b4f5 | |||
eb45eeb1ae | |||
3154350b64 | |||
519c9c4499 | |||
c2f6b09969 | |||
c8e2b22942 | |||
f433182c4c | |||
957392aaae | |||
bd8d06e133 | |||
c617b60f70 | |||
018837db0b | |||
00d5fdfc13 | |||
2debb0c2ca | |||
148d6737cc | |||
c15cb8d28c | |||
1d5471db70 | |||
086b83c1fe | |||
c509e0b86c | |||
e8a1ad9823 | |||
6446b1cfb1 | |||
2b9216c441 | |||
28656a701f | |||
cd628eaf54 | |||
3d62bd8007 | |||
7ad9560f53 | |||
c135d02895 | |||
0757f67bde | |||
c5dc25cb9e | |||
0fcf422dec | |||
21e801a325 | |||
183faf3b2a | |||
9fc66a2d1e | |||
12cf598e6b | |||
dd6cd6332c | |||
20ee2118ee | |||
1546160f6a | |||
dd77a6194e | |||
203fba0216 | |||
826a2466b7 | |||
273bc6507a | |||
2b13969b26 | |||
2f10ff1a2e | |||
1f52aea193 | |||
0a0e76679e | |||
845f3436cc | |||
f6a8c8cf76 | |||
53298933e4 | |||
af61a7a17f | |||
667ad8fe96 | |||
e1cc2394fa | |||
e7cfae3ccb | |||
ebb03113ab | |||
04e1e48f17 | |||
b3a0fe823e | |||
c417e2f4a1 | |||
02a27a8b12 | |||
d775e19059 | |||
35e7dca2bb | |||
6c4ea5e087 | |||
54a1e500e2 | |||
450ed2c471 | |||
bf97fcb2fd | |||
4edeae07a0 | |||
8e19e4d33b | |||
2a774c9414 | |||
6f50ed327d | |||
a51d384f19 | |||
e2b2e4633a | |||
46ec773128 | |||
1827a65874 | |||
1b4dd64cbe | |||
95b7d84025 | |||
137b081b8a | |||
76af9bbda7 | |||
17ab07ae9c | |||
4c4d06e49b | |||
5d9ef68f14 | |||
4689cf5591 | |||
58e7edf08a | |||
9c6c281ac3 | |||
2326d6208b | |||
cd4be4116b | |||
6697ca243c | |||
15ce89a88d | |||
4b13278a41 | |||
e01167fcab | |||
719ff26e79 | |||
2657328ac1 | |||
4b7cef239e | |||
49d9e51f72 | |||
40a5f79d76 | |||
9cfd0b7351 | |||
2223ecf890 | |||
06bad9c501 | |||
a479e65f3e | |||
a2e99e46b9 | |||
07a27cfb9a | |||
77f3a0d3a9 | |||
f9065943c5 | |||
d0aff4409d | |||
84ea1fbd4d | |||
d1d92be09a | |||
52b23af97e | |||
b76cd18dea | |||
cd3b30bf5c | |||
b87ebc6f9d | |||
4d7d119524 | |||
b4b6e9548d | |||
ebf9cd18c8 | |||
b1ccbb2deb | |||
562cd6ad0b | |||
a832672b59 | |||
309058f209 | |||
2a344dfbd8 | |||
866d4cd59a | |||
165350cca6 | |||
8c21b8a9a6 | |||
41e3a9a004 | |||
4dc6ec5387 | |||
96515c4544 | |||
b3637b5e8a | |||
43bcdf397e | |||
22c5db7121 | |||
1c6a8f8691 | |||
31b5175bb0 | |||
9add59aca9 | |||
16c65173c1 | |||
4f6ae4633f | |||
8aa1577713 |
@ -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}' | \
|
||||||
|
38
CHANGELOG.md
38
CHANGELOG.md
@ -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
|
||||||
-------
|
-------
|
||||||
* テーマの強化
|
* テーマの強化
|
||||||
|
60
README.md
60
README.md
@ -7,7 +7,7 @@
|
|||||||
[](https://david-dm.org/syuilo/misskey)
|
[](https://david-dm.org/syuilo/misskey)
|
||||||
[](http://makeapullrequest.com)
|
[](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]
|
||||||
|
|
||||||
|
@ -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
67
docs/docker.fr.md
Normal 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
18
docs/manage.fr.md
Normal 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
|
||||||
|
```
|
@ -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 :
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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 l’avatar 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 l’adresse complète de l’utilisateur"
|
show-full-acct: "Afficher l’adresse complète de l’utilisateur"
|
||||||
@ -120,8 +120,12 @@ common:
|
|||||||
reduce-motion: "Réduire les animations dans l’interface utilisateur"
|
reduce-motion: "Réduire les animations dans l’interface 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 s’agit d’une version de développement. Ne pas utiliser dans un environnement de production."
|
do-not-use-in-production: "Il s’agit d’une 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 d’autres 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 n’est pas valide."
|
invalid-theme: "Thème n’est 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 d’Accueil 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 d’envoi …"
|
||||||
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 l’utilisation 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 d’utilisateur contrasté"
|
contrasted-acct: "Nom d’utilisateur 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 d’utilisateurs : augmentation/diminution"
|
users: "Nombre d’utilisateurs : 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 d’actualité"
|
||||||
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 d’actualité"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
follow-requests: "Demandes d’abonnement"
|
follow-requests: "Demandes d’abonnement"
|
||||||
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 n’a rien publié pour le moment."
|
no-notes: "Il semble que cet utilisateur n’a 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 d’utilisateur contrasté"
|
contrasted-acct: "Nom d’utilisateur contrasté"
|
||||||
timeline: "Fil d'actualité"
|
timeline: "Fil d’actualité"
|
||||||
show-reply-target: "Afficher les réponses"
|
show-reply-target: "Afficher les réponses"
|
||||||
show-my-renotes: "Afficher mes 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 d’actualité"
|
||||||
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 d’actualité"
|
timeline: "Fil d’actualité"
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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:
|
||||||
|
@ -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: "タイムラインの上の方で投稿できるようにせえへん?"
|
||||||
|
@ -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: "완료"
|
||||||
|
@ -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"
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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"
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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: "タイムライン上部に投稿フォームを表示する"
|
||||||
|
@ -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: "在时间线顶部显示帖子表单"
|
||||||
|
54
package.json
54
package.json
@ -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"
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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}`);
|
||||||
},
|
},
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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"/>
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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} `;
|
||||||
}
|
}
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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 => {
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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"/>
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
|
@ -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} `;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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 => {
|
||||||
|
@ -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) {
|
||||||
|
BIN
src/client/assets/misskey-php-like-logo.png
Normal file
BIN
src/client/assets/misskey-php-like-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
@ -16,5 +16,6 @@
|
|||||||
renoteGradient: '#ffe1c7',
|
renoteGradient: '#ffe1c7',
|
||||||
renoteText: '$primary',
|
renoteText: '$primary',
|
||||||
quoteBorder: '$primary',
|
quoteBorder: '$primary',
|
||||||
|
mfmMention: '#56907b',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
21
src/client/theme/gray.json5
Normal file
21
src/client/theme/gray.json5
Normal 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',
|
||||||
|
},
|
||||||
|
}
|
@ -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)'
|
|
||||||
},
|
|
||||||
}
|
|
20
src/client/theme/rainy.json5
Normal file
20
src/client/theme/rainy.json5
Normal 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',
|
||||||
|
},
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"copyright": "Copyright (c) 2014-2018 syuilo"
|
"copyright": "Copyright (c) 2014-2019 syuilo"
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 }));
|
||||||
}));
|
}));
|
||||||
|
123
src/server/api/endpoints/admin/show-users.ts
Normal file
123
src/server/api/endpoints/admin/show-users.ts
Normal 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 }))));
|
||||||
|
}));
|
@ -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
|
||||||
}, {
|
}, {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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',
|
||||||
|
@ -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');
|
||||||
|
@ -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',
|
||||||
|
@ -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');
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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: {
|
||||||
|
@ -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: {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
128
src/server/web/views/info.pug
Normal file
128
src/server/web/views/info.pug
Normal 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
|
||||||
|
| <#{meta.maintainer.email}>
|
||||||
|
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}:
|
||||||
|
= ' '
|
||||||
|
|
@ -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]);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
57
src/tools/show-signin-history.ts
Normal file
57
src/tools/show-signin-history.ts
Normal 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);
|
||||||
|
});
|
14
test/api.ts
14
test/api.ts
@ -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', () => {
|
||||||
|
@ -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
1
test/resources/image.svg
Normal 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 |
Reference in New Issue
Block a user