Compare commits
257 Commits
Author | SHA1 | Date | |
---|---|---|---|
629b765abc | |||
63a89fa84a | |||
a3f89236a0 | |||
01560abafb | |||
b5698026ba | |||
6258ce75b7 | |||
6f34c74027 | |||
8add4f359b | |||
d8933c135f | |||
eb350e8d6c | |||
615fedd64d | |||
25bd82ecaa | |||
e0938e5e3a | |||
ec5e6c8443 | |||
25d8077474 | |||
06083f40d9 | |||
ec203f7f79 | |||
1b30d7d47a | |||
d9be9c958f | |||
ed09796e0d | |||
4bfa29c0ab | |||
4804bbb211 | |||
749102f9c2 | |||
0bcb1434b0 | |||
2e537e618c | |||
fe3b7a2ad3 | |||
90db793fd0 | |||
7bd2a6ad61 | |||
745f4d2439 | |||
254cfaea28 | |||
d4da5a1eea | |||
c0f8297414 | |||
834cb2ea1a | |||
d82769abd4 | |||
adf01ed4a4 | |||
09c007b3aa | |||
526ff177aa | |||
0e40d4e796 | |||
172ebab7bd | |||
aa4493fe5c | |||
a68a88f79e | |||
1de7dc94e1 | |||
59cb7992e2 | |||
87b15df47b | |||
6932d86240 | |||
87f61e714a | |||
5762e2d9ba | |||
f0691c8a4f | |||
6d7e4fe2a1 | |||
7dc789f470 | |||
190d1bbf3c | |||
a755dd5f9e | |||
0846a7b94e | |||
d8be0511f1 | |||
fb07116a4c | |||
fe453c15e3 | |||
059aeef6a0 | |||
30e25451d6 | |||
7f0fd55c9a | |||
0e9b496deb | |||
8294c18e70 | |||
39575b4696 | |||
29e9801d5c | |||
eaf83bffb0 | |||
bb25ece745 | |||
754b5629e4 | |||
ee63403548 | |||
87edeb41da | |||
41fe804587 | |||
02466acc4b | |||
8470a64e6b | |||
9939e0f9a9 | |||
ce5f552d0c | |||
7d4c535233 | |||
57cd0fb93f | |||
a15299ae53 | |||
1df7abfbb9 | |||
85a0f696bc | |||
ba3c62bf9c | |||
c17e97b6a6 | |||
2d80cd0e7b | |||
eedc572f0c | |||
2de1df3514 | |||
2d96af1255 | |||
163325ef89 | |||
23979bf09a | |||
7199e6f4e0 | |||
a40f38b2b5 | |||
00a17ed5d4 | |||
b594366f06 | |||
e9284930df | |||
ea7504f564 | |||
c1f6d996f6 | |||
df71dbb024 | |||
f104e9b6cc | |||
e29b5c2326 | |||
925868dcdb | |||
d7df26d92b | |||
42d1c67d56 | |||
c2d7929391 | |||
5864b52a81 | |||
493d32b3dc | |||
ed141338fb | |||
95db488c48 | |||
d5e1e523b6 | |||
cd0f8a4ef9 | |||
6dac505af9 | |||
9d398040cb | |||
aa55acedc9 | |||
eb70d6f226 | |||
36f0963d78 | |||
c3c111529e | |||
2dbab66cfe | |||
01238d6b1a | |||
c34f302b1c | |||
6870262f8d | |||
c54d5e7040 | |||
0ace009a54 | |||
48e8ee440b | |||
9855405b89 | |||
122076e8ea | |||
7c5ac2cbb4 | |||
ccda2181c1 | |||
b5fe4ba9be | |||
fd9c7d525a | |||
080574e13d | |||
ee0a445590 | |||
bb342c7601 | |||
ed17636fb9 | |||
c59d7d941a | |||
377377595a | |||
d63aef9963 | |||
e9b28fa3c0 | |||
be255dc583 | |||
18eb7c6087 | |||
cf29e69813 | |||
132da7e3c0 | |||
26df23bb64 | |||
76389ad619 | |||
7cde8cfbf2 | |||
4eb2ddac4e | |||
dc51eef27c | |||
bff8a23cbc | |||
9c5efb9da0 | |||
48b8320e5e | |||
9b2ed96c1c | |||
69d9aa71f2 | |||
13683780cd | |||
d780e5b251 | |||
917d3d0bd3 | |||
4b19c53697 | |||
2d40a15d2b | |||
2bdcd22ad4 | |||
f73a4e1304 | |||
b265cdbd84 | |||
a04d8b95c2 | |||
0e9a8c0cd4 | |||
5ae8a3c7e8 | |||
70ee172128 | |||
b9febc00f9 | |||
0112e2f7ec | |||
60736bab2a | |||
fb7c4ee21a | |||
e93c06cd00 | |||
0a99345909 | |||
3d08ff7cb4 | |||
057ce73ba1 | |||
66b07578c5 | |||
de3b365563 | |||
7bb8d8b27e | |||
9008664606 | |||
7374905c28 | |||
718e20de60 | |||
73d166323d | |||
3589fc6f4f | |||
feed6c7acc | |||
2522e7388d | |||
09cfd620bb | |||
362e95263d | |||
c6837b9fdf | |||
71878f93e4 | |||
f5d43b1f25 | |||
770e7378be | |||
b9a8620d2f | |||
d1c8b2993e | |||
01e9b3c2f6 | |||
57203de4cb | |||
74d0e83a8a | |||
9eee5644b9 | |||
9fe6f9417e | |||
e7de5f6051 | |||
60d81d74e3 | |||
2701a7e85f | |||
31a0afdaab | |||
9f87545901 | |||
9f94f60ede | |||
0ca3c0bca1 | |||
27611cef77 | |||
30df8ea121 | |||
595ad04ddb | |||
6b8354ccbf | |||
1b9d316e7c | |||
a8adc46f3b | |||
0efa969a15 | |||
14b7f05af4 | |||
cf43dd6ec5 | |||
b5a1fdd4c7 | |||
b32737cdff | |||
8e9717a5fc | |||
3e28b296e3 | |||
056fef70da | |||
55be9cc9d1 | |||
3f2ffcea97 | |||
b07d037cb5 | |||
4feccdfd92 | |||
f1ef85b636 | |||
cf9266eab9 | |||
4a1552fb3c | |||
e5863c2867 | |||
58211fc6a7 | |||
bd54e44b35 | |||
e1f2e364a4 | |||
186b26e103 | |||
74706a8d2c | |||
7e2b6b6369 | |||
1a2de1a051 | |||
83900cbca6 | |||
166bc19131 | |||
da874f3383 | |||
9c30b23358 | |||
b8350d5093 | |||
58f7af8927 | |||
c3b9c7b74b | |||
9415618992 | |||
1c200c9b94 | |||
ce8fa8e423 | |||
a4b7a9db03 | |||
280eeb9d75 | |||
3f71b14637 | |||
705d40ab37 | |||
b39850de01 | |||
b9c5e95b85 | |||
0c1de7b1b6 | |||
0a4499fd03 | |||
b663a47331 | |||
eb275a62a6 | |||
e18caa3396 | |||
eb15d31ebf | |||
e7f1ab2d01 | |||
9d3beb3174 | |||
b6c3399abe | |||
b505874613 | |||
0a28573845 | |||
937df577f1 | |||
e54fd6c2cb | |||
3caea9d33e | |||
b9e9631195 |
@ -154,3 +154,6 @@ id: 'aid'
|
|||||||
|
|
||||||
# Media Proxy
|
# Media Proxy
|
||||||
#mediaProxy: https://example.com/proxy
|
#mediaProxy: https://example.com/proxy
|
||||||
|
|
||||||
|
# Sign to ActivityPub GET request (default: false)
|
||||||
|
#signToActivityPubGet: true
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
.vscode
|
.vscode
|
||||||
Dockerfile
|
Dockerfile
|
||||||
build/
|
build/
|
||||||
|
built/
|
||||||
db/
|
db/
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
elasticsearch/
|
elasticsearch/
|
||||||
node_modules/
|
node_modules/
|
||||||
redis/
|
redis/
|
||||||
|
files/
|
||||||
|
2440
CHANGELOG.md
2440
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,12 @@
|
|||||||
# Contribution guide
|
# Contribution guide
|
||||||
:v: Thanks for your contributions :v:
|
:v: Thanks for your contributions :v:
|
||||||
|
|
||||||
|
## When you contribute...
|
||||||
|
- 任意のIssueについて、せっかく実装してくださっても、実装方法や設計の認識が揃ってないとマージできない/しないことになりかねないので、初めにそのIssue上で着手することを宣言し、必要に応じて他メンバーと実装方法や設計のすり合わせを行ってください。宣言することは作業が他の人と被るのを防止する効果もあります。
|
||||||
|
- 設計に迷った時はプロジェクトリーダーの判断を仰いでください。
|
||||||
|
- 時間や優先度の都合上、提出してくださったPRが長期間放置されることもありますがご理解ください。
|
||||||
|
- 温度感高めで見てほしいものは責付いてください。
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
Feature suggestions and bug reports are filed in https://github.com/syuilo/misskey/issues .
|
Feature suggestions and bug reports are filed in https://github.com/syuilo/misskey/issues .
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ RUN apk add --no-cache \
|
|||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
file \
|
file \
|
||||||
|
git \
|
||||||
g++ \
|
g++ \
|
||||||
gcc \
|
gcc \
|
||||||
libc-dev \
|
libc-dev \
|
||||||
|
39
README.md
39
README.md
@ -6,8 +6,9 @@
|
|||||||
[](https://circleci.com/gh/syuilo/misskey)
|
[](https://circleci.com/gh/syuilo/misskey)
|
||||||
[](https://david-dm.org/syuilo/misskey)
|
[](https://david-dm.org/syuilo/misskey)
|
||||||
[](http://makeapullrequest.com)
|
[](http://makeapullrequest.com)
|
||||||
|
[](https://github.com/humanetech-community/awesome-humane-tech)
|
||||||
|
|
||||||
**A forever evolving, sophisticated microblogging platform.**
|
**A forever evolving, professional microblogging platform.**
|
||||||
|
|
||||||
<p align="justify">
|
<p align="justify">
|
||||||
<a href="https://join.misskey.page/">Misskey</a> is a decentralized microblogging platform born on Earth.
|
<a href="https://join.misskey.page/">Misskey</a> is a decentralized microblogging platform born on Earth.
|
||||||
@ -112,7 +113,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c8.patreon.com/2/200/20832595" alt="Roujo " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/20832595" alt="Roujo " width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/27956229" alt="Oliver Maximilian Seidel" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/27956229" alt="Oliver Maximilian Seidel" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/605366/c9dc408fdcbf412fb183ca5b06235f8d/1.jpeg?token-time=2145916800&token-hash=oaqsjLqOFjWN5I9hm2epOaTXaEtKwQUy5OW-EpAz6-g%3D" alt="Jon Leibowitz" width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan " width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/27648259" alt="みなしま " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/27648259" alt="みなしま " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24430516/b1964ac5b9f746d2a12ff53dbc9aa40a/1.jpg?token-time=2145916800&token-hash=bmEiMGYpp3bS7hCCbymjGGsHBZM3AXuBOFO3Kro37PU%3D" alt="Eduardo Quiros" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24430516/b1964ac5b9f746d2a12ff53dbc9aa40a/1.jpg?token-time=2145916800&token-hash=bmEiMGYpp3bS7hCCbymjGGsHBZM3AXuBOFO3Kro37PU%3D" alt="Eduardo Quiros" width="100"></td>
|
||||||
@ -120,7 +120,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=20832595">Roujo </a></td>
|
<td><a href="https://www.patreon.com/user?u=20832595">Roujo </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=27956229">Oliver Maximilian Seidel</a></td>
|
<td><a href="https://www.patreon.com/user?u=27956229">Oliver Maximilian Seidel</a></td>
|
||||||
<td><a href="https://www.patreon.com/weepjp">weepjp </a></td>
|
<td><a href="https://www.patreon.com/weepjp">weepjp </a></td>
|
||||||
<td><a href="https://www.patreon.com/jonleibowitz">Jon Leibowitz</a></td>
|
|
||||||
<td><a href="https://www.patreon.com/user?u=19045173">kiritan </a></td>
|
<td><a href="https://www.patreon.com/user?u=19045173">kiritan </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=27648259">みなしま </a></td>
|
<td><a href="https://www.patreon.com/user?u=27648259">みなしま </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=24430516">Eduardo Quiros</a></td>
|
<td><a href="https://www.patreon.com/user?u=24430516">Eduardo Quiros</a></td>
|
||||||
@ -132,10 +131,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/23915207/25428766ecd745478e600b3d7f871eb2/1.png?token-time=2145916800&token-hash=urCLLA4KjJZX92Y1CxcBP4d8bVTHGkiaPnQZp-Tqz68%3D" alt="kabo2468y " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/23915207/25428766ecd745478e600b3d7f871eb2/1.png?token-time=2145916800&token-hash=urCLLA4KjJZX92Y1CxcBP4d8bVTHGkiaPnQZp-Tqz68%3D" alt="kabo2468y " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/8249688/4aacf36b6b244ab1bc6653591b6640df/2.png?token-time=2145916800&token-hash=1ZEf2w6L34253cZXS_HlVevLEENWS9QqrnxGUAYblPo%3D" alt="AureoleArk " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/8249688/4aacf36b6b244ab1bc6653591b6640df/2.png?token-time=2145916800&token-hash=1ZEf2w6L34253cZXS_HlVevLEENWS9QqrnxGUAYblPo%3D" alt="AureoleArk " width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/21285325" alt="Nie(sha) " width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon " width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61 " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/36813045/29876ea679d443bcbba3c3f16edab8c2/2.jpeg?token-time=2145916800&token-hash=YCKWnIhrV9rjUCV9KqtJnEqjy_uGYF3WMXftjUdpi7o%3D" alt="Wataru Manji (manji0)" width="100"></td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><a href="https://www.patreon.com/Nesakko">Nesakko</a></td>
|
<td><a href="https://www.patreon.com/Nesakko">Nesakko</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=776209">Demogrognard</a></td>
|
<td><a href="https://www.patreon.com/user?u=776209">Demogrognard</a></td>
|
||||||
@ -143,72 +141,75 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=557245">mkatze </a></td>
|
<td><a href="https://www.patreon.com/user?u=557245">mkatze </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=23915207">kabo2468y </a></td>
|
<td><a href="https://www.patreon.com/user?u=23915207">kabo2468y </a></td>
|
||||||
<td><a href="https://www.patreon.com/AureoleArk">AureoleArk </a></td>
|
<td><a href="https://www.patreon.com/AureoleArk">AureoleArk </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=21285325">Nie(sha) </a></td>
|
|
||||||
<td><a href="https://www.patreon.com/osapon">osapon </a></td>
|
<td><a href="https://www.patreon.com/osapon">osapon </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ </a></td>
|
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ </a></td>
|
||||||
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61 </a></td>
|
<td><a href="https://www.patreon.com/user?u=36813045">Wataru Manji (manji0)</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61 " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5788159/af42076ab3354bb49803cfba65f94bee/1.jpg?token-time=2145916800&token-hash=iSaxp_Yr2-ZiU2YVi9rcpZZj9mj3UvNSMrZr4CU4qtA%3D" alt="mewl hayabusa" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5788159/af42076ab3354bb49803cfba65f94bee/1.jpg?token-time=2145916800&token-hash=iSaxp_Yr2-ZiU2YVi9rcpZZj9mj3UvNSMrZr4CU4qtA%3D" alt="mewl hayabusa" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/28779508/3cd4cb7f017f4ee0864341e3464d42f9/1.png?token-time=2145916800&token-hash=eGQtR15be44kgvh8fw2Jx8Db4Bv15YBp2ldxh0EKRxA%3D" alt="S Y" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/28779508/3cd4cb7f017f4ee0864341e3464d42f9/1.png?token-time=2145916800&token-hash=eGQtR15be44kgvh8fw2Jx8Db4Bv15YBp2ldxh0EKRxA%3D" alt="S Y" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/16542964" alt="Takumi Sugita" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/16542964" alt="Takumi Sugita" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/38837364/9421361c54c645ac8f5fc442a40c32e9/1.png?token-time=2145916800&token-hash=TUZB48Nem3BeUPLBH6s3P6WyKBnQOy0xKaDSTBBUNzA%3D" alt="xianon" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/26340354/08834cf767b3449e93098ef73a434e2f/2.png?token-time=2145916800&token-hash=nyM8DnKRL8hR47HQ619mUzsqVRpkWZjgtgBU9RY15Uc%3D" alt="totokoro " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/26340354/08834cf767b3449e93098ef73a434e2f/2.png?token-time=2145916800&token-hash=nyM8DnKRL8hR47HQ619mUzsqVRpkWZjgtgBU9RY15Uc%3D" alt="totokoro " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s " width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5827393/59893c191dda408f9cabd0f20a3a5627/1.jpeg?token-time=2145916800&token-hash=i9N05vOph-eP1LTLb9_npATjYOpntL0ZsHNaZFSsPmE%3D" alt="motcha " width="100"></td>
|
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61 </a></td>
|
||||||
<td><a href="https://www.patreon.com/hs_sh_net">mewl hayabusa</a></td>
|
<td><a href="https://www.patreon.com/hs_sh_net">mewl hayabusa</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=28779508">S Y</a></td>
|
<td><a href="https://www.patreon.com/user?u=28779508">S Y</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=16542964">Takumi Sugita</a></td>
|
<td><a href="https://www.patreon.com/user?u=16542964">Takumi Sugita</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin </a></td>
|
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin </a></td>
|
||||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=38837364">xianon</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=26340354">totokoro </a></td>
|
<td><a href="https://www.patreon.com/user?u=26340354">totokoro </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s </a></td>
|
|
||||||
<td><a href="https://www.patreon.com/user?u=5827393">motcha </a></td>
|
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s " width="100"></td>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5827393/59893c191dda408f9cabd0f20a3a5627/1.jpeg?token-time=2145916800&token-hash=i9N05vOph-eP1LTLb9_npATjYOpntL0ZsHNaZFSsPmE%3D" alt="motcha " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/20494440/540beaf2445f408ea6597bc61e077bb3/1.png?token-time=2145916800&token-hash=UJ0JQge64Bx9XmN_qYA1inMQhrWf4U91fqz7VAKJeSg%3D" alt="axtuki1 " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/20494440/540beaf2445f408ea6597bc61e077bb3/1.png?token-time=2145916800&token-hash=UJ0JQge64Bx9XmN_qYA1inMQhrWf4U91fqz7VAKJeSg%3D" alt="axtuki1 " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpg?token-time=2145916800&token-hash=nVAntpybQrznE0rg05keLrSE6ogPKJXB13rmrJng42c%3D" alt="takimura " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpg?token-time=2145916800&token-hash=nVAntpybQrznE0rg05keLrSE6ogPKJXB13rmrJng42c%3D" alt="takimura " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13100201/fc5be4fa90444f09a9c8a06f72385272/1.png?token-time=2145916800&token-hash=i8PjlgfOB2LPEdbtWyx8ZPsBKhGcNZqcw_FQmH71UGU%3D" alt="aqz tamaina" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13100201/fc5be4fa90444f09a9c8a06f72385272/1.png?token-time=2145916800&token-hash=i8PjlgfOB2LPEdbtWyx8ZPsBKhGcNZqcw_FQmH71UGU%3D" alt="aqz tamaina" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/28295158/cd2451bfb94a449dbf705ef4718cd355/2.jpeg?token-time=2145916800&token-hash=MRv3BxufHPuCyiBSxU5UYmLGvD6YZlhtSFRfMWg2k4U%3D" alt="012 " width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/9109588/e3cffc48d20a4e43afe04123e696781d/3.png?token-time=2145916800&token-hash=T_VIUA0IFIbleZv4pIjiszZGnQonwn34sLCYFIhakBo%3D" alt="nafuchoco " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/9109588/e3cffc48d20a4e43afe04123e696781d/3.png?token-time=2145916800&token-hash=T_VIUA0IFIbleZv4pIjiszZGnQonwn34sLCYFIhakBo%3D" alt="nafuchoco " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/619ab87cc08448439222631ebb26802f/1.gif?token-time=2145916800&token-hash=o27K7M02s1z-LkDUEO5Oa7cu-GviRXeOXxryi4o_6VU%3D" alt="Atsuko Tominaga" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/619ab87cc08448439222631ebb26802f/1.gif?token-time=2145916800&token-hash=o27K7M02s1z-LkDUEO5Oa7cu-GviRXeOXxryi4o_6VU%3D" alt="Atsuko Tominaga" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/26144593/9514b10a5c1b42a3af58621aee213d1d/1.png?token-time=2145916800&token-hash=v1PYRsjzu4c_mndN4Hvi_dlispZJsuGRCQeNS82pUSM%3D" alt="EBISUME" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/26144593/9514b10a5c1b42a3af58621aee213d1d/1.png?token-time=2145916800&token-hash=v1PYRsjzu4c_mndN4Hvi_dlispZJsuGRCQeNS82pUSM%3D" alt="EBISUME" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5923936/2a743cbfbff946c2af3f09026047c0da/2.png?token-time=2145916800&token-hash=h6yphW1qnM0n_NOWaf8qtszMRLXEwIxfk5beu4RxdT0%3D" alt="noellabo " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5923936/2a743cbfbff946c2af3f09026047c0da/2.png?token-time=2145916800&token-hash=h6yphW1qnM0n_NOWaf8qtszMRLXEwIxfk5beu4RxdT0%3D" alt="noellabo " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG " width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpg?token-time=2145916800&token-hash=7bkMqTwHPRsJPGAq42PYdDXDZBVGLqdgr1ZmBxX8GFQ%3D" alt="Hekovic " width="100"></td>
|
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s </a></td>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=5827393">motcha </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=20494440">axtuki1 </a></td>
|
<td><a href="https://www.patreon.com/user?u=20494440">axtuki1 </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
|
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
|
||||||
<td><a href="https://www.patreon.com/takimura">takimura </a></td>
|
<td><a href="https://www.patreon.com/takimura">takimura </a></td>
|
||||||
<td><a href="https://www.patreon.com/aqz">aqz tamaina</a></td>
|
<td><a href="https://www.patreon.com/aqz">aqz tamaina</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=28295158">012 </a></td>
|
<td><a href="https://www.patreon.com/user?u=9109588">nafuchoco </a></td>
|
||||||
<td><a href="https://www.patreon.com/nijimiss">nafuchoco </a></td>
|
|
||||||
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
|
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=26144593">EBISUME</a></td>
|
<td><a href="https://www.patreon.com/user?u=26144593">EBISUME</a></td>
|
||||||
<td><a href="https://www.patreon.com/noellabo">noellabo </a></td>
|
<td><a href="https://www.patreon.com/noellabo">noellabo </a></td>
|
||||||
<td><a href="https://www.patreon.com/Corset">CG </a></td>
|
|
||||||
<td><a href="https://www.patreon.com/hekovic">Hekovic </a></td>
|
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG " width="100"></td>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpg?token-time=2145916800&token-hash=7bkMqTwHPRsJPGAq42PYdDXDZBVGLqdgr1ZmBxX8GFQ%3D" alt="Hekovic " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24641572/b4fd175424814f15b0ca9178d2d2d2e4/1.png?token-time=2145916800&token-hash=e2fyqdbuJbpCckHcwux7rbuW6OPkKdERcus0u2wIEWU%3D" alt="uroco @99" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24641572/b4fd175424814f15b0ca9178d2d2d2e4/1.png?token-time=2145916800&token-hash=e2fyqdbuJbpCckHcwux7rbuW6OPkKdERcus0u2wIEWU%3D" alt="uroco @99" width="100"></td>
|
||||||
|
<td><img src="https://c8.patreon.com/2/200/14661394" alt="Chandler " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/23932002" alt="nenohi " width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/23932002" alt="nenohi " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/9481273/7fa89168e72943859c3d3c96e424ed31/4.jpeg?token-time=2145916800&token-hash=5w1QV1qXe-NdWbdFmp1H7O_-QBsSiV0haumk3XTHIEg%3D" alt="Efertone " width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/9481273/7fa89168e72943859c3d3c96e424ed31/4.jpeg?token-time=2145916800&token-hash=5w1QV1qXe-NdWbdFmp1H7O_-QBsSiV0haumk3XTHIEg%3D" alt="Efertone " width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/Corset">CG </a></td>
|
||||||
|
<td><a href="https://www.patreon.com/hekovic">Hekovic </a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=24641572">uroco @99</a></td>
|
<td><a href="https://www.patreon.com/user?u=24641572">uroco @99</a></td>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=14661394">Chandler </a></td>
|
||||||
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=23932002">nenohi </a></td>
|
<td><a href="https://www.patreon.com/user?u=23932002">nenohi </a></td>
|
||||||
<td><a href="https://www.patreon.com/efertone">Efertone </a></td>
|
<td><a href="https://www.patreon.com/efertone">Efertone </a></td>
|
||||||
<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, 02 Jun 2020 00:00:08 UTC
|
**Last updated:** Sun, 26 Jul 2020 07:00:10 UTC
|
||||||
<!-- PATREON_END -->
|
<!-- PATREON_END -->
|
||||||
|
|
||||||
[backer-url]: #backers
|
[backer-url]: #backers
|
||||||
|
@ -13,6 +13,8 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- internal_network
|
- internal_network
|
||||||
- external_network
|
- external_network
|
||||||
|
volumes:
|
||||||
|
- ./files:/misskey/files
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
restart: always
|
restart: always
|
||||||
|
@ -4,3 +4,30 @@ Docs for users are located in `src/docs`.
|
|||||||
|
|
||||||
これらのドキュメントはMisskeyの開発者またはMisskeyインスタンス運営者向けです。
|
これらのドキュメントはMisskeyの開発者またはMisskeyインスタンス運営者向けです。
|
||||||
利用者向けのドキュメントは`src/docs`にあります。
|
利用者向けのドキュメントは`src/docs`にあります。
|
||||||
|
|
||||||
|
这些文档是为 Misskey 的贡献者,或是 Misskey 实例的管理者准备的。
|
||||||
|
为用户准备的文档放置在 `src/docs` 文件夹中。
|
||||||
|
|
||||||
|
## 日本語版
|
||||||
|
|
||||||
|
- [Misskey構築の手引き](./setup.ja.md)
|
||||||
|
- [運営ガイド](./manage.ja.md)
|
||||||
|
- [Dockerを使ったMisskey構築方法](./docker.ja.md)
|
||||||
|
|
||||||
|
## English Version
|
||||||
|
|
||||||
|
- [Misskey Setup and Installation Guide](./setup.en.md)
|
||||||
|
- [Management guide](./manage.en.md)
|
||||||
|
- [Docker Guide](./docker.en.md)
|
||||||
|
|
||||||
|
## Française Version
|
||||||
|
|
||||||
|
- [Guide d'installation et de configuration de Misskey](./setup.fr.md)
|
||||||
|
- [Guide d'administration](./manage.fr.md)
|
||||||
|
- [Guide Docker](./docker.fr.md)
|
||||||
|
|
||||||
|
## 简体中文版
|
||||||
|
|
||||||
|
- [Misskey 设置和安装指南](./setup.zh.md)
|
||||||
|
- [运营指南](./manage.zh.md)
|
||||||
|
- [Docker 部署指南](./docker.zh.md)
|
||||||
|
@ -3,7 +3,8 @@ Docker Guide
|
|||||||
|
|
||||||
This guide describes how to install and setup Misskey with Docker.
|
This guide describes how to install and setup Misskey with Docker.
|
||||||
|
|
||||||
[Japanese version also available - 日本語版もあります](./docker.ja.md)
|
- [Japanese version also available - 日本語版もあります](./docker.ja.md)
|
||||||
|
- [Simplified Chinese version also available - 简体中文版同样可用](./docker.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@ Guide Docker
|
|||||||
|
|
||||||
Ce guide explique comment installer et configurer Misskey avec Docker.
|
Ce guide explique comment installer et configurer Misskey avec Docker.
|
||||||
|
|
||||||
[Version japonaise également disponible - Japanese version also available - 日本語版もあります](./docker.ja.md)
|
- [Version japonaise également disponible - Japanese version also available - 日本語版もあります](./docker.ja.md)
|
||||||
[Version anglaise également disponible - English version also available - 英語版もあります](./docker.en.md)
|
- [Version anglaise également disponible - English version also available - 英語版もあります](./docker.en.md)
|
||||||
|
- [Version Chinois simplifié également disponible - Simplified Chinese version also available - 简体中文版同样可用](./docker.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ Dockerを使ったMisskey構築方法
|
|||||||
|
|
||||||
このガイドはDockerを使ったMisskeyセットアップ方法について解説します。
|
このガイドはDockerを使ったMisskeyセットアップ方法について解説します。
|
||||||
|
|
||||||
[英語版もあります - English version also available](./docker.en.md)
|
- [英語版もあります - English version also available](./docker.en.md)
|
||||||
|
- [简体中文版同样可用 - Simplified Chinese version also available](./docker.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
96
docs/docker.zh.md
Normal file
96
docs/docker.zh.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
Docker 部署指南
|
||||||
|
================================================================
|
||||||
|
|
||||||
|
这份指南描述了如何使用Docker安装并设置 Misskey 。
|
||||||
|
|
||||||
|
- [日本語版もあります - Japanese version also available](./docker.ja.md)
|
||||||
|
- [英語版もあります - English version also available](./docker.en.md)
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
*1.* 下载 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
1. 克隆 Misskey 项目的 master 分支。
|
||||||
|
|
||||||
|
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||||
|
|
||||||
|
2. 进入 misskey 文件夹。
|
||||||
|
|
||||||
|
`cd misskey`
|
||||||
|
|
||||||
|
3. 检查 [最新发布版](https://github.com/syuilo/misskey/releases/latest) 标签。
|
||||||
|
|
||||||
|
`git checkout master`
|
||||||
|
|
||||||
|
*2.* 配置 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
可以按照如下方式创建配置文件:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
cd .config
|
||||||
|
cp example.yml default.yml
|
||||||
|
cp docker_example.env docker.env
|
||||||
|
```
|
||||||
|
|
||||||
|
### `default.yml`
|
||||||
|
|
||||||
|
这个文件的编辑工作基本与非 Docker 环境的版本相同。
|
||||||
|
但请注意, Postgresql、 Redis 和 Elasticsearch 的 **主机名(hostname)** 配置不应该是 `localhost` ,它们被设置在 `docker-compose.yml` 文件中。
|
||||||
|
以下是默认的主机名:
|
||||||
|
|
||||||
|
| 服务 | 主机名 |
|
||||||
|
|---------------|----------|
|
||||||
|
| Postgresql | `db` |
|
||||||
|
| Redis | `redis` |
|
||||||
|
| Elasticsearch | `es` |
|
||||||
|
|
||||||
|
### `docker.env`
|
||||||
|
|
||||||
|
在这个文件中配置 Postgresql 。
|
||||||
|
至少需要如下这些配置:
|
||||||
|
|
||||||
|
| 名称 | 描述 |
|
||||||
|
|---------------------|---------------|
|
||||||
|
| `POSTGRES_PASSWORD` | 数据库密码 |
|
||||||
|
| `POSTGRES_USER` | 数据库用户名 |
|
||||||
|
| `POSTGRES_DB` | 数据库名 |
|
||||||
|
|
||||||
|
*3.* 配置 Docker
|
||||||
|
----------------------------------------------------------------
|
||||||
|
编辑 `docker-compose.yml` 文件。
|
||||||
|
|
||||||
|
*4.* 构建 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
使用如下的方式构建Misskey:
|
||||||
|
|
||||||
|
`docker-compose build`
|
||||||
|
|
||||||
|
*5.* 初始化数据库
|
||||||
|
----------------------------------------------------------------
|
||||||
|
``` bash
|
||||||
|
docker-compose run --rm web yarn run init
|
||||||
|
```
|
||||||
|
|
||||||
|
*6.* 完成了!
|
||||||
|
----------------------------------------------------------------
|
||||||
|
干得不错!现在您拥有了一个可以运行Misskey的环境啦。
|
||||||
|
|
||||||
|
### 正常启动
|
||||||
|
只需要 `docker-compose up -d` 即可。玩得愉快!
|
||||||
|
|
||||||
|
### 如何将您的 Misskey 服务器升级至最新版本
|
||||||
|
1. `git stash`
|
||||||
|
2. `git checkout master`
|
||||||
|
3. `git pull`
|
||||||
|
4. `git stash pop`
|
||||||
|
5. `docker-compose build`
|
||||||
|
6. 检查 [更新日志](../CHANGELOG.md) 以获取升级迁移信息。
|
||||||
|
7. `docker-compose stop && docker-compose up -d`
|
||||||
|
|
||||||
|
### 如何执行 [控制台指令](manage.zh.md):
|
||||||
|
`docker-compose run --rm web node built/tools/mark-admin @example`
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
如果您有任何疑问或是困惑,欢迎与我们联系!
|
14
docs/manage.zh.md
Normal file
14
docs/manage.zh.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# 运营指南
|
||||||
|
|
||||||
|
## 检查任务队列的状态
|
||||||
|
即将到来……
|
||||||
|
|
||||||
|
## 设置用户为管理员
|
||||||
|
``` shell
|
||||||
|
node built/tools/mark-admin (用户名)
|
||||||
|
```
|
||||||
|
|
||||||
|
样例
|
||||||
|
``` shell
|
||||||
|
node built/tools/mark-admin @syuilo
|
||||||
|
```
|
@ -4,7 +4,8 @@ Misskey Setup and Installation Guide
|
|||||||
We thank you for your interest in setting up your Misskey server!
|
We thank you for your interest in setting up your Misskey server!
|
||||||
This guide describes how to install and setup Misskey.
|
This guide describes how to install and setup Misskey.
|
||||||
|
|
||||||
[Japanese version also available - 日本語版もあります](./setup.ja.md)
|
- [Japanese version also available - 日本語版もあります](./setup.ja.md)
|
||||||
|
- [Simplified Chinese version also available - 简体中文版同样可用](./setup.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ Guide d'installation et de configuration de Misskey
|
|||||||
Nous vous remerçions de l'intrêt que vous manifestez pour l'installation de votre propre instance Misskey !
|
Nous vous remerçions de l'intrêt que vous manifestez pour l'installation de votre propre instance Misskey !
|
||||||
Ce guide décrit les étapes à suivre afin d'installer et de configurer une instance Misskey.
|
Ce guide décrit les étapes à suivre afin d'installer et de configurer une instance Misskey.
|
||||||
|
|
||||||
[La version en japonnais est également disponible sur - 日本語版もあります](./setup.ja.md)
|
- [La version en japonnais est également disponible sur - 日本語版もあります](./setup.ja.md)
|
||||||
|
- [Version anglaise également disponible - English version also available - 英語版もあります](./setup.en.md)
|
||||||
|
- [Version Chinois simplifié également disponible - Simplified Chinese version also available - 简体中文版同样可用](./setup.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@ Misskey構築の手引き
|
|||||||
Misskeyサーバーの構築にご関心をお寄せいただきありがとうございます!
|
Misskeyサーバーの構築にご関心をお寄せいただきありがとうございます!
|
||||||
このガイドではMisskeyのインストール・セットアップ方法について解説します。
|
このガイドではMisskeyのインストール・セットアップ方法について解説します。
|
||||||
|
|
||||||
[英語版もあります - English version also available](./setup.en.md)
|
- [英語版もあります - English version also available](./setup.en.md)
|
||||||
|
- [简体中文版同样可用 - Simplified Chinese version also available](./setup.zh.md)
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
146
docs/setup.zh.md
Normal file
146
docs/setup.zh.md
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
Misskey 设置和安装指南
|
||||||
|
================================================================
|
||||||
|
|
||||||
|
非常感谢您对构建 Misskey 服务器的关注!
|
||||||
|
这份指南描述了 Misskey 的安装与设置流程。
|
||||||
|
|
||||||
|
- [日本語版もあります - Japanese version also available](./setup.ja.md)
|
||||||
|
- [英語版もあります - English version also available](./setup.en.md)
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
*1.* 创建 Misskey 用户
|
||||||
|
----------------------------------------------------------------
|
||||||
|
直接使用 root 用户来运行 misskey 也许并不是一个好主意,因此我们有必要创建一个专用的用户。
|
||||||
|
以 Debian 为例:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
adduser --disabled-password --disabled-login misskey
|
||||||
|
```
|
||||||
|
|
||||||
|
*2.* 安装依赖
|
||||||
|
----------------------------------------------------------------
|
||||||
|
请安装并设置如下这些软件:
|
||||||
|
|
||||||
|
#### Dependencies :package:
|
||||||
|
* **[Node.js](https://nodejs.org/en/)** (12.x, 14.x)
|
||||||
|
* **[PostgreSQL](https://www.postgresql.org/)** (>= 10)
|
||||||
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
|
##### Optional
|
||||||
|
* [Yarn](https://yarnpkg.com/) *可选,但出于安全因素考虑还是推荐安装。如果您没有安装, 您需要使用 `npx yarn` 来代替 `yarn`.*
|
||||||
|
* [Elasticsearch](https://www.elastic.co/) - 为了启用搜索功能,这个搜索引擎是有必要的。
|
||||||
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
|
*3.* 安装 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
1. 连接至 misskey 用户.
|
||||||
|
|
||||||
|
`su - misskey`
|
||||||
|
|
||||||
|
2. 克隆 Misskey 项目的 master 分支。
|
||||||
|
|
||||||
|
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||||
|
|
||||||
|
3. 进入 misskey 文件夹。
|
||||||
|
|
||||||
|
`cd misskey`
|
||||||
|
|
||||||
|
4. 检查 [最新发布版](https://github.com/syuilo/misskey/releases/latest) 标签。
|
||||||
|
|
||||||
|
`git checkout master`
|
||||||
|
|
||||||
|
5. 安装 Misskey 的依赖。
|
||||||
|
|
||||||
|
`yarn`
|
||||||
|
|
||||||
|
*4.* 配置 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
1. 复制 `.config/example.yml` 并重命名为 `default.yml`。
|
||||||
|
|
||||||
|
`cp .config/example.yml .config/default.yml`
|
||||||
|
|
||||||
|
2. 编辑 `default.yml`
|
||||||
|
|
||||||
|
*5.* 构建 Misskey
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
使用如下的指令构建 Misskey :
|
||||||
|
|
||||||
|
`NODE_ENV=production yarn build`
|
||||||
|
|
||||||
|
如果您使用的是 Debian , 您需要安装 `build-essential`, `python` 环境包。
|
||||||
|
|
||||||
|
如果您仍然遇到有关某些模块的错误,您可以使用 node-gyp:
|
||||||
|
|
||||||
|
1. `npx node-gyp configure`
|
||||||
|
2. `npx node-gyp build`
|
||||||
|
3. `NODE_ENV=production yarn build`
|
||||||
|
|
||||||
|
*6.* 初始化数据库
|
||||||
|
----------------------------------------------------------------
|
||||||
|
``` bash
|
||||||
|
yarn run init
|
||||||
|
```
|
||||||
|
|
||||||
|
*7.* 完成了!
|
||||||
|
----------------------------------------------------------------
|
||||||
|
干得不错!现在您拥有了一个可以运行Misskey的环境啦。
|
||||||
|
|
||||||
|
### 正常启动
|
||||||
|
只需要 `NODE_ENV=production npm start` 即可。玩得愉快!
|
||||||
|
|
||||||
|
### 使用 systemd 来启动
|
||||||
|
|
||||||
|
1. 在此处创建一个 systemd 服务:
|
||||||
|
|
||||||
|
`/etc/systemd/system/misskey.service`
|
||||||
|
|
||||||
|
2. 编辑它,粘贴如下内容并保存:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Unit]
|
||||||
|
Description=Misskey daemon
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=misskey
|
||||||
|
ExecStart=/usr/bin/npm start
|
||||||
|
WorkingDirectory=/home/misskey/misskey
|
||||||
|
Environment="NODE_ENV=production"
|
||||||
|
TimeoutSec=60
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=misskey
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 重启 systemd 并设置 misskey 服务自动启动:
|
||||||
|
|
||||||
|
`systemctl daemon-reload ; systemctl enable misskey`
|
||||||
|
|
||||||
|
4. 启动 misskey 服务:
|
||||||
|
|
||||||
|
`systemctl start misskey`
|
||||||
|
|
||||||
|
您可以使用 `systemctl status misskey` 来检查服务是否正在运行。
|
||||||
|
|
||||||
|
### 如何将您的 Misskey 服务器升级至最新版本
|
||||||
|
1. `git checkout master`
|
||||||
|
2. `git pull`
|
||||||
|
3. `yarn install`
|
||||||
|
4. `NODE_ENV=production yarn build`
|
||||||
|
5. `yarn migrate`
|
||||||
|
6. 重启您的 Misskey 进程来应用改变。
|
||||||
|
7. 尽情享受吧!
|
||||||
|
|
||||||
|
如果您在更新时遇到任何问题,请尝试以下操作:
|
||||||
|
1. `yarn clean` 或是 `yarn cleanall`
|
||||||
|
2. 重试升级 (请不要忘记 `yarn install` )
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
如果您有任何疑问或是困惑,欢迎与我们联系!
|
11
gulpfile.ts
11
gulpfile.ts
@ -7,9 +7,6 @@ import * as gulp from 'gulp';
|
|||||||
import * as ts from 'gulp-typescript';
|
import * as ts from 'gulp-typescript';
|
||||||
import * as rimraf from 'rimraf';
|
import * as rimraf from 'rimraf';
|
||||||
import * as rename from 'gulp-rename';
|
import * as rename from 'gulp-rename';
|
||||||
const cleanCSS = require('gulp-clean-css');
|
|
||||||
const sass = require('gulp-dart-sass');
|
|
||||||
const fiber = require('fibers');
|
|
||||||
|
|
||||||
const locales: { [x: string]: any } = require('./locales');
|
const locales: { [x: string]: any } = require('./locales');
|
||||||
const meta = require('./package.json');
|
const meta = require('./package.json');
|
||||||
@ -61,13 +58,6 @@ gulp.task('cleanall', gulp.parallel('clean', cb =>
|
|||||||
rimraf('./node_modules', cb)
|
rimraf('./node_modules', cb)
|
||||||
));
|
));
|
||||||
|
|
||||||
gulp.task('build:client:styles', () =>
|
|
||||||
gulp.src('./src/client/style.scss')
|
|
||||||
.pipe(sass({ fiber }))
|
|
||||||
.pipe(cleanCSS())
|
|
||||||
.pipe(gulp.dest('./built/client/assets/'))
|
|
||||||
);
|
|
||||||
|
|
||||||
gulp.task('copy:client', () =>
|
gulp.task('copy:client', () =>
|
||||||
gulp.src([
|
gulp.src([
|
||||||
'./assets/**/*',
|
'./assets/**/*',
|
||||||
@ -87,7 +77,6 @@ gulp.task('copy:docs', () =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
gulp.task('build:client', gulp.parallel(
|
gulp.task('build:client', gulp.parallel(
|
||||||
'build:client:styles',
|
|
||||||
'copy:client',
|
'copy:client',
|
||||||
'copy:docs'
|
'copy:docs'
|
||||||
));
|
));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
_lang_: "العربية"
|
_lang_: "العربية"
|
||||||
|
introMisskey: "اهلا بك! ميسكي هو منصة تدوين مصغر لا مركزية ومفتوحة المصدر.\nيمكنك مشاركة \"ملاحظات\" عن ما يجري حولك، وإخبار الجميع عن نفسك 📡\nتسمح لك \"الانفعالات\" بتعبير عن شعورك حول ملاحظات الآخرين 👍\nاكتشف عالمًا جديدًا 🚀"
|
||||||
monthAndDay: "{day}/{month}"
|
monthAndDay: "{day}/{month}"
|
||||||
search: "البحث"
|
search: "البحث"
|
||||||
notifications: "الإشعارات"
|
notifications: "الإشعارات"
|
||||||
@ -14,8 +15,12 @@ noNotes: "لم يتم العثور على أية ملاحظات"
|
|||||||
noNotifications: "ليس هناك أية اشعارات"
|
noNotifications: "ليس هناك أية اشعارات"
|
||||||
instance: "مثيل الخادم"
|
instance: "مثيل الخادم"
|
||||||
settings: "الاعدادات"
|
settings: "الاعدادات"
|
||||||
|
basicSettings: "الاعدادات الأساسية"
|
||||||
|
otherSettings: "إعدادات أخرى"
|
||||||
|
openInWindow: "افتح في نافذة جديدة"
|
||||||
profile: "الملف التعريفي"
|
profile: "الملف التعريفي"
|
||||||
timeline: "الخيط الزمني"
|
timeline: "الخيط الزمني"
|
||||||
|
noAccountDescription: "لم يكتب هذا المستخدم سيرته بعد."
|
||||||
login: "لِج"
|
login: "لِج"
|
||||||
loggingIn: "جارٍ تسجيل الدخول"
|
loggingIn: "جارٍ تسجيل الدخول"
|
||||||
logout: "الخروج"
|
logout: "الخروج"
|
||||||
@ -28,22 +33,31 @@ favorite: "إضافة إلى المفضلة"
|
|||||||
favorites: "المفضلات"
|
favorites: "المفضلات"
|
||||||
unfavorite: "إزالة من المفضلة"
|
unfavorite: "إزالة من المفضلة"
|
||||||
pin: "دبّسها على الصفحة الشخصية"
|
pin: "دبّسها على الصفحة الشخصية"
|
||||||
|
unpin: "ألغ تثبيتها من ملفك الشخصي"
|
||||||
copyContent: "انسخ المحتوى"
|
copyContent: "انسخ المحتوى"
|
||||||
copyLink: "انسخ الرابط"
|
copyLink: "انسخ الرابط"
|
||||||
delete: "حذف"
|
delete: "حذف"
|
||||||
deleteAndEdit: "إزالة وإعادة الصياغة"
|
deleteAndEdit: "إزالة وإعادة الصياغة"
|
||||||
|
deleteAndEditConfirm: "أمتأكد من حذف الملاحظة؟ ستفقد كل مشاركاتها، والتفاعلات، والردود عليها."
|
||||||
addToList: "أضفه إلى قائمة"
|
addToList: "أضفه إلى قائمة"
|
||||||
sendMessage: "أرسل رسالة"
|
sendMessage: "أرسل رسالة"
|
||||||
copyUsername: "انسخ اسم المستخدم"
|
copyUsername: "انسخ اسم المستخدم"
|
||||||
|
searchUser: "ابحث عن مستخدمين"
|
||||||
reply: "رد"
|
reply: "رد"
|
||||||
loadMore: "عرض المزيد"
|
loadMore: "عرض المزيد"
|
||||||
youGotNewFollower: "يتابعك"
|
youGotNewFollower: "يتابعك"
|
||||||
|
receiveFollowRequest: "تلقيت طلب متابعة"
|
||||||
|
followRequestAccepted: "قُبل طلب المتابعة"
|
||||||
|
mention: "أشر الى"
|
||||||
mentions: "الإشارات"
|
mentions: "الإشارات"
|
||||||
directNotes: "الملاحظات المباشرة"
|
directNotes: "الملاحظات المباشرة"
|
||||||
|
importAndExport: "إستورد / صدر"
|
||||||
import: "استيراد"
|
import: "استيراد"
|
||||||
export: "تصدير"
|
export: "تصدير"
|
||||||
files: "الملفات"
|
files: "الملفات"
|
||||||
download: "تنزيل"
|
download: "تنزيل"
|
||||||
|
driveFileDeleteConfirm: "أمتأكد من حذف ملف {name}؟ كل الملاحظات المُرفق بها هذا الملف ستحذف."
|
||||||
|
unfollowConfirm: "أمتأكد من إلغاء متابعة {name}؟"
|
||||||
lists: "القوائم"
|
lists: "القوائم"
|
||||||
noLists: "ليس لديك أية قائمة"
|
noLists: "ليس لديك أية قائمة"
|
||||||
note: "ملاحظة"
|
note: "ملاحظة"
|
||||||
@ -53,8 +67,10 @@ followers: "المتابِعين"
|
|||||||
followsYou: "يتابعك"
|
followsYou: "يتابعك"
|
||||||
createList: "إنشاء قائمة"
|
createList: "إنشاء قائمة"
|
||||||
manageLists: "إدارة القوائم"
|
manageLists: "إدارة القوائم"
|
||||||
error: "حدث خطأ ما"
|
error: "خطأ"
|
||||||
|
somethingHappened: "حدث خطأ"
|
||||||
retry: "حاول مجددًا"
|
retry: "حاول مجددًا"
|
||||||
|
pageLoadError: "فشل تحميل الصفحة"
|
||||||
enterListName: "اسم القائمة"
|
enterListName: "اسم القائمة"
|
||||||
privacy: "الخصوصية"
|
privacy: "الخصوصية"
|
||||||
makeFollowManuallyApprove: "القبول يدويا طلبات الإشتراك"
|
makeFollowManuallyApprove: "القبول يدويا طلبات الإشتراك"
|
||||||
@ -64,6 +80,7 @@ followRequest: "طلب اشتراك"
|
|||||||
followRequests: "طلبات الإشتراك"
|
followRequests: "طلبات الإشتراك"
|
||||||
unfollow: "إلغاء الاشتراك"
|
unfollow: "إلغاء الاشتراك"
|
||||||
followRequestPending: "طلبات الإشتراك المعلّقة"
|
followRequestPending: "طلبات الإشتراك المعلّقة"
|
||||||
|
enterEmoji: "أدخل إيموجي"
|
||||||
unrenote: "إلغاء مشاركة الملاحظة"
|
unrenote: "إلغاء مشاركة الملاحظة"
|
||||||
quote: "اقتبس"
|
quote: "اقتبس"
|
||||||
pinnedNote: "ملاحظة مدبسة"
|
pinnedNote: "ملاحظة مدبسة"
|
||||||
@ -71,16 +88,26 @@ you: "أنت"
|
|||||||
clickToShow: "اضغط للعرض"
|
clickToShow: "اضغط للعرض"
|
||||||
sensitive: "محتوى حساس"
|
sensitive: "محتوى حساس"
|
||||||
add: "إضافة"
|
add: "إضافة"
|
||||||
|
reaction: "تفاعل"
|
||||||
rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات"
|
rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات"
|
||||||
|
attachCancel: "أزل المرفق"
|
||||||
enterFileName: "ادخل اسم الملف"
|
enterFileName: "ادخل اسم الملف"
|
||||||
mute: "اكتم"
|
mute: "اكتم"
|
||||||
unmute: "إلغاء الكتم"
|
unmute: "إلغاء الكتم"
|
||||||
block: "احجب"
|
block: "احجب"
|
||||||
unblock: "إلغاء الحجب"
|
unblock: "إلغاء الحجب"
|
||||||
|
suspend: "علِق"
|
||||||
|
unsuspend: "ألغ التعليق"
|
||||||
|
blockConfirm: "أمتأكد من حجب هذا الحساب؟"
|
||||||
|
unblockConfirm: "أمتأكد من إلغاء حجب هذا الحساب؟"
|
||||||
selectList: "اختر قائمة"
|
selectList: "اختر قائمة"
|
||||||
|
editWidgetsExit: "تم"
|
||||||
customEmojis: "إيموجي مخصص"
|
customEmojis: "إيموجي مخصص"
|
||||||
addEmoji: "إضافة إيموجي"
|
addEmoji: "إضافة إيموجي"
|
||||||
|
cacheRemoteFiles: "خزن مؤقتا الملفات البعيدة"
|
||||||
|
autoAcceptFollowed: "اقبل طلبات المتابعة تلقائيا من الحسابات المتابَعة"
|
||||||
addAcount: "إضافة حساب"
|
addAcount: "إضافة حساب"
|
||||||
|
loginFailed: "فشل الولوج"
|
||||||
showOnRemote: "رؤيته على مثيل الخادم البُعدي"
|
showOnRemote: "رؤيته على مثيل الخادم البُعدي"
|
||||||
general: "الرئيسية"
|
general: "الرئيسية"
|
||||||
wallpaper: "خلفية الشاشة"
|
wallpaper: "خلفية الشاشة"
|
||||||
@ -88,6 +115,7 @@ setWallpaper: "استخدم خلفية الشاشة"
|
|||||||
removeWallpaper: "إزالة خلفية الشاشة"
|
removeWallpaper: "إزالة خلفية الشاشة"
|
||||||
searchWith: "البحث: {q}"
|
searchWith: "البحث: {q}"
|
||||||
youHaveNoLists: "لا تمتلك أية قائمة"
|
youHaveNoLists: "لا تمتلك أية قائمة"
|
||||||
|
followConfirm: "أتريد متابعة {name}؟"
|
||||||
proxyAccount: "حساب وكيل البروكسي"
|
proxyAccount: "حساب وكيل البروكسي"
|
||||||
host: "المضيف"
|
host: "المضيف"
|
||||||
selectUser: "حدّد مستخدمًا"
|
selectUser: "حدّد مستخدمًا"
|
||||||
@ -96,6 +124,8 @@ annotation: "التعليقات"
|
|||||||
federation: "الفديرالية"
|
federation: "الفديرالية"
|
||||||
instances: "مثيل الخادم"
|
instances: "مثيل الخادم"
|
||||||
latestRequestSentAt: "آخر طلب أرسِل في"
|
latestRequestSentAt: "آخر طلب أرسِل في"
|
||||||
|
latestRequestReceivedAt: "آخر طلب تُلقي في"
|
||||||
|
storageUsage: "مساحة التخزين المستخدمة"
|
||||||
charts: "المنحنيات البيانية"
|
charts: "المنحنيات البيانية"
|
||||||
perHour: "في الساعة"
|
perHour: "في الساعة"
|
||||||
perDay: "في اليوم"
|
perDay: "في اليوم"
|
||||||
@ -127,7 +157,6 @@ processing: "المعالجة جارية"
|
|||||||
preview: "معاينة"
|
preview: "معاينة"
|
||||||
default: "افتراضي"
|
default: "افتراضي"
|
||||||
noCustomEmojis: "ليس هناك إيموجيات"
|
noCustomEmojis: "ليس هناك إيموجيات"
|
||||||
customEmojisOfRemote: "الإيموجيات القادمة مِن مثيلات الخوادم الأخرى"
|
|
||||||
federating: "الفديرالية جارية"
|
federating: "الفديرالية جارية"
|
||||||
blocked: "محجوب"
|
blocked: "محجوب"
|
||||||
suspended: "مُعلّق"
|
suspended: "مُعلّق"
|
||||||
@ -193,6 +222,7 @@ rename: "إعادة التسمية"
|
|||||||
avatar: "الصورة الرمزية"
|
avatar: "الصورة الرمزية"
|
||||||
banner: "الصورة الرأسية"
|
banner: "الصورة الرأسية"
|
||||||
nsfw: "محتوى حساس"
|
nsfw: "محتوى حساس"
|
||||||
|
disconnectedFromServer: "قُطِع الإتصال بالخادم"
|
||||||
reload: "انعش"
|
reload: "انعش"
|
||||||
doNothing: "تجاهل"
|
doNothing: "تجاهل"
|
||||||
watch: "راقب"
|
watch: "راقب"
|
||||||
@ -279,6 +309,7 @@ noteOf: "ملاحظات {user}"
|
|||||||
inviteToGroup: "دعوة إلى فريق"
|
inviteToGroup: "دعوة إلى فريق"
|
||||||
noMessagesYet: "ليس هناك رسائل بعد"
|
noMessagesYet: "ليس هناك رسائل بعد"
|
||||||
newMessageExists: "لقد تلقيت رسالة جديدة"
|
newMessageExists: "لقد تلقيت رسالة جديدة"
|
||||||
|
invitations: "دعوة"
|
||||||
invitationCode: "رمز الدعوة"
|
invitationCode: "رمز الدعوة"
|
||||||
checking: "التحقق جارٍ"
|
checking: "التحقق جارٍ"
|
||||||
available: "متوفر"
|
available: "متوفر"
|
||||||
@ -311,7 +342,7 @@ remote: "بُعدي"
|
|||||||
total: "المجموع"
|
total: "المجموع"
|
||||||
weekOverWeekChanges: "أسبوعيا"
|
weekOverWeekChanges: "أسبوعيا"
|
||||||
dayOverDayChanges: "يوميا"
|
dayOverDayChanges: "يوميا"
|
||||||
clinetSettings: "إعدادات التطبيق"
|
appearance: "المظهر"
|
||||||
accountSettings: "إعدادات الحساب"
|
accountSettings: "إعدادات الحساب"
|
||||||
promotion: "ترقية"
|
promotion: "ترقية"
|
||||||
promote: "روِّج"
|
promote: "روِّج"
|
||||||
@ -341,9 +372,32 @@ addRelay: "إضافة مُرحّل"
|
|||||||
addedRelays: "المرحلات التي تم إضافتها"
|
addedRelays: "المرحلات التي تم إضافتها"
|
||||||
deletedNote: "ملاحظة محذوفة"
|
deletedNote: "ملاحظة محذوفة"
|
||||||
invisibleNote: "ملاحظة مخفية"
|
invisibleNote: "ملاحظة مخفية"
|
||||||
|
poll: "استطلاع رأي"
|
||||||
|
themeEditor: "مصمم القوالب"
|
||||||
|
plugins: "الإضافات"
|
||||||
|
pluginInstallWarn: "يرجى تنصيب إضافات ذات مصدر موثوق منه فقط."
|
||||||
|
smtpHost: "المضيف"
|
||||||
|
smtpUser: "اسم المستخدم"
|
||||||
|
smtpPass: "الكلمة السرية"
|
||||||
|
display: "المظهر"
|
||||||
|
_reversi:
|
||||||
|
total: "المجموع"
|
||||||
|
_channel:
|
||||||
|
featured: "المتداوَلة"
|
||||||
|
_sidebar:
|
||||||
|
full: "كامل"
|
||||||
|
icon: "الصورة الرمزية"
|
||||||
|
hide: "إخفاء"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "استكشف قوالب المظهر"
|
explore: "استكشف قوالب المظهر"
|
||||||
|
install: "تنصيب قالب"
|
||||||
|
manage: "إدارة القوالب"
|
||||||
|
code: "شيفرة القالب"
|
||||||
|
installed: "تم تنصيب {name}"
|
||||||
|
make: "إنشاء قالب"
|
||||||
|
alpha: "الشفافية"
|
||||||
keys:
|
keys:
|
||||||
|
mention: "أشر الى"
|
||||||
messageBg: "خلفية الدردشة"
|
messageBg: "خلفية الدردشة"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "الملاحظات"
|
note: "الملاحظات"
|
||||||
@ -392,18 +446,29 @@ _widgets:
|
|||||||
rss: "تدفق RSS"
|
rss: "تدفق RSS"
|
||||||
activity: "النشاط"
|
activity: "النشاط"
|
||||||
photos: "الصور"
|
photos: "الصور"
|
||||||
|
federation: "الفديرالية"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "إخفاء"
|
hide: "إخفاء"
|
||||||
show: "عرض المزيد"
|
show: "عرض المزيد"
|
||||||
chars: "{count} أحرف"
|
chars: "{count} أحرف"
|
||||||
files: "{count} ملفات"
|
files: "{count} ملفات"
|
||||||
_poll:
|
_poll:
|
||||||
|
noOnlyOneChoice: "تحتاج إلى خيارَين على الأقل"
|
||||||
|
choiceN: "الخيار {n}"
|
||||||
|
noMore: "لا يمكنك إضافة خيارات أخرى"
|
||||||
|
canMultipleVote: "السماح بالإجابات المتعددة"
|
||||||
|
expiration: "ينتهي استطلاع الرأي في"
|
||||||
|
infinite: "أبدًا"
|
||||||
at: "تاريخ الإنتهاء"
|
at: "تاريخ الإنتهاء"
|
||||||
|
after: "ينتهي بعد…"
|
||||||
deadlineDate: "تاريخ الانتهاء"
|
deadlineDate: "تاريخ الانتهاء"
|
||||||
deadlineTime: "سا"
|
deadlineTime: "سا"
|
||||||
duration: "المدة"
|
duration: "المدة"
|
||||||
|
votesCount: "{n} أصوات"
|
||||||
|
totalVotes: "المجموع {n} أصوات"
|
||||||
vote: "قم بالتصويت"
|
vote: "قم بالتصويت"
|
||||||
showResult: "اعرض النتائج"
|
showResult: "اعرض النتائج"
|
||||||
|
voted: "تم التصويت"
|
||||||
closed: "انتهى"
|
closed: "انتهى"
|
||||||
remainingDays: "{d} أيام و {h} ساعات متبقية"
|
remainingDays: "{d} أيام و {h} ساعات متبقية"
|
||||||
remainingHours: "{h} ساعات و {m} دقائق متبقية"
|
remainingHours: "{h} ساعات و {m} دقائق متبقية"
|
||||||
@ -469,9 +534,15 @@ _pages:
|
|||||||
types:
|
types:
|
||||||
array: "القوائم"
|
array: "القوائم"
|
||||||
_notification:
|
_notification:
|
||||||
|
youGotPoll: "شارك {name} في استطلاع الرأي"
|
||||||
youGotMessagingMessageFromUser: "لقد تلقيت رسالة مِن {name}"
|
youGotMessagingMessageFromUser: "لقد تلقيت رسالة مِن {name}"
|
||||||
youGotMessagingMessageFromGroup: "لقد أرسِلَت رسالة إلى الفريق {name}"
|
youGotMessagingMessageFromGroup: "لقد أرسِلَت رسالة إلى الفريق {name}"
|
||||||
youWereFollowed: "يتابعك"
|
youWereFollowed: "يتابعك"
|
||||||
|
_types:
|
||||||
|
follow: "المتابَعون"
|
||||||
|
mention: "أشر الى"
|
||||||
|
quote: "اقتبس"
|
||||||
|
reaction: "تفاعل"
|
||||||
_deck:
|
_deck:
|
||||||
_columns:
|
_columns:
|
||||||
notifications: "الإشعارات"
|
notifications: "الإشعارات"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "Keine Notizen"
|
|||||||
noNotifications: "Keine Benachrichtigungen"
|
noNotifications: "Keine Benachrichtigungen"
|
||||||
instance: "Instanz"
|
instance: "Instanz"
|
||||||
settings: "Einstellungen"
|
settings: "Einstellungen"
|
||||||
|
basicSettings: "Allgemeine Einstellungen"
|
||||||
|
otherSettings: "Andere Einstellungen"
|
||||||
|
openInWindow: "In Fenster öffnen"
|
||||||
profile: "Profil"
|
profile: "Profil"
|
||||||
timeline: "Chronik"
|
timeline: "Chronik"
|
||||||
noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt."
|
noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt."
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "Möchtest du diese Notiz wirklich löschen und bearbeiten
|
|||||||
addToList: "Zu Liste hinzufügen"
|
addToList: "Zu Liste hinzufügen"
|
||||||
sendMessage: "Nachricht senden"
|
sendMessage: "Nachricht senden"
|
||||||
copyUsername: "Benutzernamen kopieren"
|
copyUsername: "Benutzernamen kopieren"
|
||||||
|
searchUser: "Benutzersuche"
|
||||||
reply: "Antworten"
|
reply: "Antworten"
|
||||||
loadMore: "Mehr anzeigen"
|
loadMore: "Mehr anzeigen"
|
||||||
youGotNewFollower: "Du hast einen neuen Follower"
|
youGotNewFollower: "Du hast einen neuen Follower"
|
||||||
@ -66,8 +70,11 @@ followers: "Gefolgt von"
|
|||||||
followsYou: "Folgt dir"
|
followsYou: "Folgt dir"
|
||||||
createList: "Liste erstellen"
|
createList: "Liste erstellen"
|
||||||
manageLists: "Listen verwalten"
|
manageLists: "Listen verwalten"
|
||||||
error: "Ein Problem ist aufgetreten"
|
error: "Fehler"
|
||||||
|
somethingHappened: "Ein Fehler ist aufgetreten"
|
||||||
retry: "Wiederholen"
|
retry: "Wiederholen"
|
||||||
|
pageLoadError: "Laden der Seite fehlgeschlagen."
|
||||||
|
pageLoadErrorDescription: "Dieser Fehler wird meist durch Netzwerkfehler oder den Browser-Cache verursacht. Versuche den Browser-Cache zu leeren und es nach kurzer Zeit noch einmal zu probieren."
|
||||||
enterListName: "Listennamen eingeben"
|
enterListName: "Listennamen eingeben"
|
||||||
privacy: "Privatsphäre"
|
privacy: "Privatsphäre"
|
||||||
makeFollowManuallyApprove: "Follow-Anfragen benötigen Bestätigung"
|
makeFollowManuallyApprove: "Follow-Anfragen benötigen Bestätigung"
|
||||||
@ -84,14 +91,14 @@ quote: "Zitieren"
|
|||||||
pinnedNote: "Angepinnte Notiz"
|
pinnedNote: "Angepinnte Notiz"
|
||||||
you: "Du"
|
you: "Du"
|
||||||
clickToShow: "Klicke, um diesen Inhalt anzusehen"
|
clickToShow: "Klicke, um diesen Inhalt anzusehen"
|
||||||
sensitive: "Dieser Inhalt ist NSFW"
|
sensitive: "NSFW"
|
||||||
add: "Hinzufügen"
|
add: "Hinzufügen"
|
||||||
reaction: "Reaktionen"
|
reaction: "Reaktionen"
|
||||||
reactionSettingDescription: "Gib deine Lieblingsreaktionen ein, um sie der Reaktionsauswahl hinzuzufügen."
|
reactionSettingDescription: "Gib deine Lieblingsreaktionen ein, um sie der Reaktionsauswahl hinzuzufügen."
|
||||||
rememberNoteVisibility: "Notizsichtbarkeit merken"
|
rememberNoteVisibility: "Notizsichtbarkeit merken"
|
||||||
attachCancel: "Anhang entfernen"
|
attachCancel: "Anhang entfernen"
|
||||||
markAsSensitive: "Als sensitiv markieren"
|
markAsSensitive: "Als NSFW markieren"
|
||||||
unmarkAsSensitive: "Markierung als sensitiv zurücknehmen"
|
unmarkAsSensitive: "Markierung als NSFW zurücknehmen"
|
||||||
enterFileName: "Dateinamen eingeben"
|
enterFileName: "Dateinamen eingeben"
|
||||||
mute: "Stummschalten"
|
mute: "Stummschalten"
|
||||||
unmute: "Stummschaltung aufheben"
|
unmute: "Stummschaltung aufheben"
|
||||||
@ -104,6 +111,10 @@ unblockConfirm: "Möchtest du diese Blockierung wirklich aufheben?"
|
|||||||
suspendConfirm: "Möchtest du diesen Benutzer wirklich sperren?"
|
suspendConfirm: "Möchtest du diesen Benutzer wirklich sperren?"
|
||||||
unsuspendConfirm: "Möchtest du die Sperrung dieses Benutzers wirklich aufheben?"
|
unsuspendConfirm: "Möchtest du die Sperrung dieses Benutzers wirklich aufheben?"
|
||||||
selectList: "Wähle eine Liste aus"
|
selectList: "Wähle eine Liste aus"
|
||||||
|
selectAntenna: "Antenne auswählen"
|
||||||
|
selectWidget: "Widget auswählen"
|
||||||
|
editWidgets: "Widgets bearbeiten"
|
||||||
|
editWidgetsExit: "Fertig"
|
||||||
customEmojis: "Benutzerdefinierte Emojis"
|
customEmojis: "Benutzerdefinierte Emojis"
|
||||||
emoji: "Emoji"
|
emoji: "Emoji"
|
||||||
emojiName: "Emojiname"
|
emojiName: "Emojiname"
|
||||||
@ -163,7 +174,7 @@ clearCachedFilesConfirm: "Sollen alle im Cache gespeicherten Dateien von anderen
|
|||||||
blockedInstances: "Blockierte Instanzen"
|
blockedInstances: "Blockierte Instanzen"
|
||||||
blockedInstancesDescription: "Gib den Hostnamen der Instanz an, die blockiert werden soll. Blockierte Instanzen können nicht mehr mit dieser kommunizieren."
|
blockedInstancesDescription: "Gib den Hostnamen der Instanz an, die blockiert werden soll. Blockierte Instanzen können nicht mehr mit dieser kommunizieren."
|
||||||
muteAndBlock: "Stummgeschaltet / Blockiert"
|
muteAndBlock: "Stummgeschaltet / Blockiert"
|
||||||
mutedUsers: "Stummgestellte Benutzer"
|
mutedUsers: "Stummgeschaltete Benutzer"
|
||||||
blockedUsers: "Blockierte Benutzer"
|
blockedUsers: "Blockierte Benutzer"
|
||||||
noUsers: "Keine Benutzer"
|
noUsers: "Keine Benutzer"
|
||||||
editProfile: "Profil bearbeiten"
|
editProfile: "Profil bearbeiten"
|
||||||
@ -175,7 +186,6 @@ processing: "In Bearbeitung"
|
|||||||
preview: "Vorschau"
|
preview: "Vorschau"
|
||||||
default: "Standard"
|
default: "Standard"
|
||||||
noCustomEmojis: "Es existieren keine Emojis"
|
noCustomEmojis: "Es existieren keine Emojis"
|
||||||
customEmojisOfRemote: "Emojis von anderen Instanzen"
|
|
||||||
noJobs: "Es gibt keine Jobs"
|
noJobs: "Es gibt keine Jobs"
|
||||||
federating: "Föderiert"
|
federating: "Föderiert"
|
||||||
blocked: "Blockiert"
|
blocked: "Blockiert"
|
||||||
@ -261,7 +271,8 @@ copyUrl: "URL kopieren"
|
|||||||
rename: "Umbenennen"
|
rename: "Umbenennen"
|
||||||
avatar: "Profilbild"
|
avatar: "Profilbild"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
nsfw: "Dieser Inhalt ist NSFW"
|
nsfw: "NSFW"
|
||||||
|
whenServerDisconnected: "Bei Verbindungsverlust zum Server"
|
||||||
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
|
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
|
||||||
reload: "Aktualisieren"
|
reload: "Aktualisieren"
|
||||||
doNothing: "Ignorieren"
|
doNothing: "Ignorieren"
|
||||||
@ -362,7 +373,6 @@ unregister: "Deaktivieren"
|
|||||||
passwordLessLogin: "Passwortloses Anmelden einrichten"
|
passwordLessLogin: "Passwortloses Anmelden einrichten"
|
||||||
resetPassword: "Passwort zurücksetzen"
|
resetPassword: "Passwort zurücksetzen"
|
||||||
newPasswordIs: "Das neue Passwort ist \"{password}\""
|
newPasswordIs: "Das neue Passwort ist \"{password}\""
|
||||||
autoReloadWhenDisconnected: "Automatisch aktualisieren wenn die Serververbindung getrennt wird"
|
|
||||||
autoNoteWatch: "Notizen automatisch beobachten"
|
autoNoteWatch: "Notizen automatisch beobachten"
|
||||||
autoNoteWatchDescription: "Werde über Notizen, auf die du reagiert oder geantwortet hast, informiert"
|
autoNoteWatchDescription: "Werde über Notizen, auf die du reagiert oder geantwortet hast, informiert"
|
||||||
reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren"
|
reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren"
|
||||||
@ -402,6 +412,7 @@ noMessagesYet: "Noch keine Nachrichten"
|
|||||||
newMessageExists: "Du hast eine neue Nachricht"
|
newMessageExists: "Du hast eine neue Nachricht"
|
||||||
onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden"
|
onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden"
|
||||||
signinRequired: "Anmeldung erforderlich"
|
signinRequired: "Anmeldung erforderlich"
|
||||||
|
invitations: "Einladen"
|
||||||
invitationCode: "Einladungscode"
|
invitationCode: "Einladungscode"
|
||||||
checking: "Wird überprüft..."
|
checking: "Wird überprüft..."
|
||||||
available: "Verfügbar"
|
available: "Verfügbar"
|
||||||
@ -442,8 +453,8 @@ remote: "Fremd"
|
|||||||
total: "Gesamt"
|
total: "Gesamt"
|
||||||
weekOverWeekChanges: "Wöchentlich"
|
weekOverWeekChanges: "Wöchentlich"
|
||||||
dayOverDayChanges: "Täglich"
|
dayOverDayChanges: "Täglich"
|
||||||
accessibility: "Barrierefreiheit"
|
appearance: "Aussehen"
|
||||||
clinetSettings: "Client-Einstellungen"
|
clientSettings: "Client-Einstellungen"
|
||||||
accountSettings: "Benutzerkonto-Einstellungen"
|
accountSettings: "Benutzerkonto-Einstellungen"
|
||||||
promotion: "Hervorgehoben"
|
promotion: "Hervorgehoben"
|
||||||
promote: "Hervorheben"
|
promote: "Hervorheben"
|
||||||
@ -466,6 +477,7 @@ objectStorageUseSSL: "SSL verwenden"
|
|||||||
objectStorageUseSSLDesc: "Deaktiviere dies falls du für die API-Verbindungen kein HTTPS verwenden wirst"
|
objectStorageUseSSLDesc: "Deaktiviere dies falls du für die API-Verbindungen kein HTTPS verwenden wirst"
|
||||||
objectStorageUseProxy: "Über Proxy verbinden"
|
objectStorageUseProxy: "Über Proxy verbinden"
|
||||||
objectStorageUseProxyDesc: "Deaktiviere dies falls du keinen Proxy für den Objektspeicher verwenden wirst"
|
objectStorageUseProxyDesc: "Deaktiviere dies falls du keinen Proxy für den Objektspeicher verwenden wirst"
|
||||||
|
objectStorageSetPublicRead: "Bei Upload auf \"public-read\" stellen"
|
||||||
serverLogs: "Serverprotokolle"
|
serverLogs: "Serverprotokolle"
|
||||||
deleteAll: "Alle löschen"
|
deleteAll: "Alle löschen"
|
||||||
showFixedPostForm: "Bereich zum Schreiben neuer Notizen am Anfang der Chronik anzeigen"
|
showFixedPostForm: "Bereich zum Schreiben neuer Notizen am Anfang der Chronik anzeigen"
|
||||||
@ -473,6 +485,8 @@ newNoteRecived: "Es gibt neue Notizen"
|
|||||||
sounds: "Töne"
|
sounds: "Töne"
|
||||||
listen: "Anhören"
|
listen: "Anhören"
|
||||||
none: "Keine"
|
none: "Keine"
|
||||||
|
showInPage: "In Seite anzeigen"
|
||||||
|
popout: "Pop-Up"
|
||||||
volume: "Lautstärke"
|
volume: "Lautstärke"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Wähle ein Emoji"
|
chooseEmoji: "Wähle ein Emoji"
|
||||||
@ -515,7 +529,6 @@ enableInfiniteScroll: "Automatisch mehr Notizen laden"
|
|||||||
visibility: "Sichtbarkeit"
|
visibility: "Sichtbarkeit"
|
||||||
poll: "Umfrage"
|
poll: "Umfrage"
|
||||||
useCw: "Inhalt verstecken"
|
useCw: "Inhalt verstecken"
|
||||||
fixedWidgetsPosition: "Widgetposition fixieren"
|
|
||||||
enablePlayer: "Video-Player öffnen"
|
enablePlayer: "Video-Player öffnen"
|
||||||
disablePlayer: "Video-Player schließen"
|
disablePlayer: "Video-Player schließen"
|
||||||
expandTweet: "Tweet ausklappen"
|
expandTweet: "Tweet ausklappen"
|
||||||
@ -528,6 +541,98 @@ plugins: "Plugins"
|
|||||||
pluginInstallWarn: "Installiere nur vertrauenswürdige Plugins."
|
pluginInstallWarn: "Installiere nur vertrauenswürdige Plugins."
|
||||||
deck: "Deck"
|
deck: "Deck"
|
||||||
undeck: "Deck verlassen"
|
undeck: "Deck verlassen"
|
||||||
|
useBlurEffectForModal: "Weichzeichnungseffekt für Modals verwenden"
|
||||||
|
generateAccessToken: "Zugriffstoken generieren"
|
||||||
|
permission: "Berechtigungen"
|
||||||
|
enableAll: "Alle aktivieren"
|
||||||
|
disableAll: "Alle deaktivieren"
|
||||||
|
tokenRequested: "Benutzerkontozugriff gewähren"
|
||||||
|
pluginTokenRequestedDescription: "Dieses Plugin wird die hier konfigurierten Berechtigungen verwenden können."
|
||||||
|
notificationType: "Benachrichtigungstyp"
|
||||||
|
edit: "Bearbeiten"
|
||||||
|
useStarForReactionFallback: "Verwende ★ falls das Reaktions-Emoji unbekannt ist"
|
||||||
|
emailConfig: "Email-Server Konfiguration"
|
||||||
|
enableEmail: "Email-Versand aktivieren"
|
||||||
|
emailConfigInfo: "Zur Email-Bestätigung bei Registrierung und zum Zurücksetzen des Passworts verwendet"
|
||||||
|
email: "Email-Adresse"
|
||||||
|
smtpConfig: "SMTP-Server Konfiguration"
|
||||||
|
smtpHost: "Host"
|
||||||
|
smtpPort: "Port"
|
||||||
|
smtpUser: "Benutzername"
|
||||||
|
smtpPass: "Passwort"
|
||||||
|
emptyToDisableSmtpAuth: "Benutzername und Passwort leer lassen um SMTP-Verifizierung zu deaktivieren"
|
||||||
|
smtpSecure: "Für SMTP-Verbindungen implizit SSL/TLS verwenden"
|
||||||
|
smtpSecureInfo: "Schalte dies aus, falls du STARTTLS verwendest"
|
||||||
|
testEmail: "Email-Versand testen"
|
||||||
|
wordMute: "Wort-Stummschaltung"
|
||||||
|
userSaysSomething: "{name} hat etwas gesagt."
|
||||||
|
makeActive: "Aktivieren"
|
||||||
|
display: "Anzeige"
|
||||||
|
copy: "Kopieren"
|
||||||
|
metrics: "Metriken"
|
||||||
|
overview: "Übersicht"
|
||||||
|
logs: "Logs"
|
||||||
|
delayed: "Verzögert"
|
||||||
|
database: "Datenbank"
|
||||||
|
channel: "Kanäle"
|
||||||
|
create: "Erstellen"
|
||||||
|
notificationSetting: "Benachrichtigungseinstellungen"
|
||||||
|
notificationSettingDesc: "Wähle die Art der anzuzeigenden Benachrichtigung"
|
||||||
|
useGlobalSetting: "Globale Einstellung verwenden"
|
||||||
|
useGlobalSettingDesc: "Wenn dies eingeschaltet ist, werden die Benachrichtigungseinstellungen deines Benutzerkontos verwendet. Wenn dies ausgeschaltet ist, können individuelle Einstellungen vorgenommen werden."
|
||||||
|
other: "Andere"
|
||||||
|
regenerateLoginToken: "Login-Token regenerieren"
|
||||||
|
regenerateLoginTokenDescription: "Den bei Logins intern verwendeten Token regenerieren. Normalerweise wird dies nicht benötigt. Bei Regeneration werden alle Geräte ausgeloggt."
|
||||||
|
setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren."
|
||||||
|
fileIdOrUrl: "Datei-ID oder URL"
|
||||||
|
chatOpenBehavior: "Verhalten des Chatfensters bei Öffnung"
|
||||||
|
sample: "Beispiel"
|
||||||
|
abuseReports: "Melden"
|
||||||
|
reportAbuse: "Melden"
|
||||||
|
reportAbuseOf: "{name} melden"
|
||||||
|
fillAbuseReportDescription: "Bitte gib Details für diese Meldung an. Falls es sich um eine spezielle Notiz handelt, bitte gib dessen URL an."
|
||||||
|
abuseReported: "Die Meldung wurde versendet. Vielen Dank."
|
||||||
|
send: "Senden"
|
||||||
|
abuseMarkAsResolved: "Meldung als gelöst markieren"
|
||||||
|
openInNewTab: "In neuem Tab öffnen"
|
||||||
|
openInSideView: "In Seitenansicht öffnen"
|
||||||
|
defaultNavigationBehaviour: "Standardnavigationsverhalten"
|
||||||
|
editTheseSettingsMayBreakAccount: "Bei Bearbeitung dieser Einstellungen besteht die Gefahr, dein Benutzerkonto zu beschädigen."
|
||||||
|
instanceTicker: "Instanz-Informationen der Notiz"
|
||||||
|
random: "Zufällig"
|
||||||
|
_reversi:
|
||||||
|
total: "Gesamt"
|
||||||
|
_instanceTicker:
|
||||||
|
none: "Nie anzeigen"
|
||||||
|
remote: "Für Benutzer fremder Instanzen anzeigen"
|
||||||
|
always: "Immer anzeigen"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "Automatisch aktualisieren"
|
||||||
|
dialog: "Warnungsfenster zeigen"
|
||||||
|
quiet: "Unaufdringlich warnen"
|
||||||
|
_channel:
|
||||||
|
create: "Kanal erstellen"
|
||||||
|
edit: "Kanal bearbeiten"
|
||||||
|
setBanner: "Kanalbanner festlegen"
|
||||||
|
removeBanner: "Kanalbanner entfernen"
|
||||||
|
featured: "Trends"
|
||||||
|
owned: "Besitzt"
|
||||||
|
following: "Gefolgt"
|
||||||
|
usersCount: "{n} Teilnehmer"
|
||||||
|
notesCount: "{n} Notizen"
|
||||||
|
_sidebar:
|
||||||
|
full: "Voll"
|
||||||
|
icon: "Symbol"
|
||||||
|
hide: "Ausblenden"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "Wort stummschalten"
|
||||||
|
muteWordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen."
|
||||||
|
muteWordsDescription2: "Umgib Schlüsselworter mit Schrägstrichen, um Reguläre Ausdrücke zu verwenden."
|
||||||
|
softDescription: "Notizen, die die eingestellten Konditionen erfüllen, in der Chronik ausblenden"
|
||||||
|
hardDescription: "Verhindern, dass Notizen, die die eingestellten Konditionen erfüllen, der Chronik hinzugefügt werden. Zudem werden diese Notizen auch nicht der Chronik hinzugefügt, falls die Konditionen geändert werden."
|
||||||
|
soft: "Leicht"
|
||||||
|
hard: "Schwer"
|
||||||
|
mutedNotes: "Stummgeschaltete Notizen"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Themen erforschen"
|
explore: "Themen erforschen"
|
||||||
install: "Thema installieren"
|
install: "Thema installieren"
|
||||||
@ -548,7 +653,7 @@ _theme:
|
|||||||
func: "Funktionen"
|
func: "Funktionen"
|
||||||
funcKind: "Funktionstyp"
|
funcKind: "Funktionstyp"
|
||||||
argument: "Parameter"
|
argument: "Parameter"
|
||||||
basedProp: "Name der referenzierten Eigenschaft"
|
basedProp: "Referenzierte Eigenschaft"
|
||||||
alpha: "Transparenz"
|
alpha: "Transparenz"
|
||||||
darken: "Verdunkeln"
|
darken: "Verdunkeln"
|
||||||
lighten: "Erhellen"
|
lighten: "Erhellen"
|
||||||
@ -606,6 +711,7 @@ _sfx:
|
|||||||
chat: "Chat"
|
chat: "Chat"
|
||||||
chatBg: "Nachrichten (Hintergrund)"
|
chatBg: "Nachrichten (Hintergrund)"
|
||||||
antenna: "Antennen"
|
antenna: "Antennen"
|
||||||
|
channel: "Kanalbenachrichtigung"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Unbekannt"
|
unknown: "Unbekannt"
|
||||||
future: "Zukunft"
|
future: "Zukunft"
|
||||||
@ -671,9 +777,9 @@ _permissions:
|
|||||||
"write:mutes": "Stummschaltungen bearbeiten"
|
"write:mutes": "Stummschaltungen bearbeiten"
|
||||||
"write:notes": "Notizen schreiben oder löschen"
|
"write:notes": "Notizen schreiben oder löschen"
|
||||||
"read:notifications": "Benachrichtigungen lesen"
|
"read:notifications": "Benachrichtigungen lesen"
|
||||||
"write:notifications": "Mit Benachrichtigungen arbeiten"
|
"write:notifications": "Benachrichtigungen bearbeiten"
|
||||||
"read:reactions": "Reaktionen lesen"
|
"read:reactions": "Reaktionen lesen"
|
||||||
"write:reactions": "Reaktionen hinzufügen und bearbeiten"
|
"write:reactions": "Reaktionen hinzufügen und ändern"
|
||||||
"write:votes": "In Umfragen abstimmen"
|
"write:votes": "In Umfragen abstimmen"
|
||||||
"read:pages": "Deine Seiten lesen"
|
"read:pages": "Deine Seiten lesen"
|
||||||
"write:pages": "Deine Seiten bearbeiten oder löschen"
|
"write:pages": "Deine Seiten bearbeiten oder löschen"
|
||||||
@ -681,6 +787,8 @@ _permissions:
|
|||||||
"write:page-likes": "Liste der Seiten, die mir gefallen, bearbeiten"
|
"write:page-likes": "Liste der Seiten, die mir gefallen, bearbeiten"
|
||||||
"read:user-groups": "Benutzergruppen lesen"
|
"read:user-groups": "Benutzergruppen lesen"
|
||||||
"write:user-groups": "Benutzergruppen bearbeiten oder löschen"
|
"write:user-groups": "Benutzergruppen bearbeiten oder löschen"
|
||||||
|
"read:channels": "Kanäle lesen"
|
||||||
|
"write:channels": "Kanäle bearbeiten"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "Möchtest du \"{name}\" authorisieren, auf dieses Benuzerkonto zugreifen zu können?"
|
shareAccess: "Möchtest du \"{name}\" authorisieren, auf dieses Benuzerkonto zugreifen zu können?"
|
||||||
shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?"
|
shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?"
|
||||||
@ -713,6 +821,8 @@ _widgets:
|
|||||||
activity: "Aktivität"
|
activity: "Aktivität"
|
||||||
photos: "Fotos"
|
photos: "Fotos"
|
||||||
digitalClock: "Digitaluhr"
|
digitalClock: "Digitaluhr"
|
||||||
|
federation: "Föderation"
|
||||||
|
postForm: "Neue Notiz anfertigen"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Ausblenden"
|
hide: "Ausblenden"
|
||||||
show: "Mehr anzeigen"
|
show: "Mehr anzeigen"
|
||||||
@ -754,6 +864,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Dieser Notiz antworten..."
|
replyPlaceholder: "Dieser Notiz antworten..."
|
||||||
quotePlaceholder: "Diese Notiz zitieren..."
|
quotePlaceholder: "Diese Notiz zitieren..."
|
||||||
|
channelPlaceholder: "In einen Kanal senden"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "Was machst du momentan?"
|
a: "Was machst du momentan?"
|
||||||
b: "Was ist um dich herum los?"
|
b: "Was ist um dich herum los?"
|
||||||
@ -1166,10 +1277,29 @@ _notification:
|
|||||||
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
|
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
|
||||||
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
|
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
|
||||||
youWereInvitedToGroup: "Du wurdest in eine Gruppe eingeladen"
|
youWereInvitedToGroup: "Du wurdest in eine Gruppe eingeladen"
|
||||||
|
_types:
|
||||||
|
all: "Alle"
|
||||||
|
follow: "Neue Follower"
|
||||||
|
mention: "Erwähnungen"
|
||||||
|
reply: "Antworten"
|
||||||
|
renote: "Renotes"
|
||||||
|
quote: "Zitationen"
|
||||||
|
reaction: "Reaktionen"
|
||||||
|
pollVote: "Antworten auf Umfragen"
|
||||||
|
receiveFollowRequest: "Follow-Anfrage erhalten"
|
||||||
|
followRequestAccepted: "Follow-Anfrage akzeptiert"
|
||||||
|
groupInvited: "Gruppeneinladung erhalten"
|
||||||
|
app: "Benachrichtigungen von Apps"
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "Hauptspalte immer zeigen"
|
alwaysShowMainColumn: "Hauptspalte immer zeigen"
|
||||||
columnAlign: "Spalten ausrichten"
|
columnAlign: "Spalten ausrichten"
|
||||||
addColumn: "Spalte hinzufügen"
|
addColumn: "Spalte hinzufügen"
|
||||||
|
swapLeft: "Nach links verschieben"
|
||||||
|
swapRight: "Nach rechts verschieben"
|
||||||
|
swapUp: "Nach oben verschieben"
|
||||||
|
swapDown: "Nach unten verschieben"
|
||||||
|
stackLeft: "Nach links stapeln"
|
||||||
|
popRight: "Nach rechts vom Stapel nehmen"
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "Widgets"
|
widgets: "Widgets"
|
||||||
notifications: "Benachrichtigungen"
|
notifications: "Benachrichtigungen"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "No notes"
|
|||||||
noNotifications: "No notifications"
|
noNotifications: "No notifications"
|
||||||
instance: "Instance"
|
instance: "Instance"
|
||||||
settings: "Settings"
|
settings: "Settings"
|
||||||
|
basicSettings: "Basic Settings"
|
||||||
|
otherSettings: "Other Settings"
|
||||||
|
openInWindow: "Open in window"
|
||||||
profile: "Profile"
|
profile: "Profile"
|
||||||
timeline: "Timeline"
|
timeline: "Timeline"
|
||||||
noAccountDescription: "This user has not written their bio yet."
|
noAccountDescription: "This user has not written their bio yet."
|
||||||
@ -29,7 +32,7 @@ users: "Users"
|
|||||||
addUser: "Add a user"
|
addUser: "Add a user"
|
||||||
favorite: "Favorite"
|
favorite: "Favorite"
|
||||||
favorites: "Favorites"
|
favorites: "Favorites"
|
||||||
unfavorite: "Undo favorite"
|
unfavorite: "Unfavorite"
|
||||||
pin: "Pin to profile"
|
pin: "Pin to profile"
|
||||||
unpin: "Unpin from profile"
|
unpin: "Unpin from profile"
|
||||||
copyContent: "Copy contents"
|
copyContent: "Copy contents"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "Are you sure you want to delete this note and edit it? Yo
|
|||||||
addToList: "Add to list"
|
addToList: "Add to list"
|
||||||
sendMessage: "Send a message"
|
sendMessage: "Send a message"
|
||||||
copyUsername: "Copy username"
|
copyUsername: "Copy username"
|
||||||
|
searchUser: "User search"
|
||||||
reply: "Reply"
|
reply: "Reply"
|
||||||
loadMore: "Load more"
|
loadMore: "Load more"
|
||||||
youGotNewFollower: "Followed you"
|
youGotNewFollower: "Followed you"
|
||||||
@ -66,8 +70,11 @@ followers: "Followers"
|
|||||||
followsYou: "Follows you"
|
followsYou: "Follows you"
|
||||||
createList: "Create list"
|
createList: "Create list"
|
||||||
manageLists: "Manage lists"
|
manageLists: "Manage lists"
|
||||||
error: "Something happened :("
|
error: "Error"
|
||||||
|
somethingHappened: "An error occurred"
|
||||||
retry: "Retry"
|
retry: "Retry"
|
||||||
|
pageLoadError: "Failed to load page"
|
||||||
|
pageLoadErrorDescription: "This is normally caused by network errors or the browser's cache. Try clearung the cache and then try again after waiting a little while."
|
||||||
enterListName: "List name"
|
enterListName: "List name"
|
||||||
privacy: "Privacy"
|
privacy: "Privacy"
|
||||||
makeFollowManuallyApprove: "Follow requests require approval"
|
makeFollowManuallyApprove: "Follow requests require approval"
|
||||||
@ -104,6 +111,10 @@ unblockConfirm: "Are you sure that you want to unblock this account?"
|
|||||||
suspendConfirm: "Are you sure that you want to suspend this account?"
|
suspendConfirm: "Are you sure that you want to suspend this account?"
|
||||||
unsuspendConfirm: "Are you sure you that want to unsuspend this account?"
|
unsuspendConfirm: "Are you sure you that want to unsuspend this account?"
|
||||||
selectList: "Select a list"
|
selectList: "Select a list"
|
||||||
|
selectAntenna: "Select an Antenna"
|
||||||
|
selectWidget: "Select a widget"
|
||||||
|
editWidgets: "Edit widgets"
|
||||||
|
editWidgetsExit: "Done"
|
||||||
customEmojis: "Custom Emoji"
|
customEmojis: "Custom Emoji"
|
||||||
emoji: "Emoji"
|
emoji: "Emoji"
|
||||||
emojiName: "Emoji name"
|
emojiName: "Emoji name"
|
||||||
@ -175,7 +186,6 @@ processing: "Processing"
|
|||||||
preview: "Preview"
|
preview: "Preview"
|
||||||
default: "Default"
|
default: "Default"
|
||||||
noCustomEmojis: "There are no emojis"
|
noCustomEmojis: "There are no emojis"
|
||||||
customEmojisOfRemote: "Emojis from other instances"
|
|
||||||
noJobs: "There are no jobs"
|
noJobs: "There are no jobs"
|
||||||
federating: "Federating"
|
federating: "Federating"
|
||||||
blocked: "Blocked"
|
blocked: "Blocked"
|
||||||
@ -262,6 +272,7 @@ rename: "Rename"
|
|||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
nsfw: "NSFW"
|
nsfw: "NSFW"
|
||||||
|
whenServerDisconnected: "When losing connection to the server"
|
||||||
disconnectedFromServer: "Connection to the server was interrupted."
|
disconnectedFromServer: "Connection to the server was interrupted."
|
||||||
reload: "Refresh"
|
reload: "Refresh"
|
||||||
doNothing: "Ignore"
|
doNothing: "Ignore"
|
||||||
@ -362,7 +373,6 @@ unregister: "Unregister"
|
|||||||
passwordLessLogin: "Set up password-less login"
|
passwordLessLogin: "Set up password-less login"
|
||||||
resetPassword: "Reset password"
|
resetPassword: "Reset password"
|
||||||
newPasswordIs: "The new password is \"{password}\""
|
newPasswordIs: "The new password is \"{password}\""
|
||||||
autoReloadWhenDisconnected: "Auto refresh when disconnected from server"
|
|
||||||
autoNoteWatch: "Watch note automatically"
|
autoNoteWatch: "Watch note automatically"
|
||||||
autoNoteWatchDescription: "Get notified about the notes which you reactioned or replied."
|
autoNoteWatchDescription: "Get notified about the notes which you reactioned or replied."
|
||||||
reduceUiAnimation: "Reduce UI animation"
|
reduceUiAnimation: "Reduce UI animation"
|
||||||
@ -402,6 +412,7 @@ noMessagesYet: "No messages yet"
|
|||||||
newMessageExists: "You've got a new message"
|
newMessageExists: "You've got a new message"
|
||||||
onlyOneFileCanBeAttached: "You can only attach one file to a message"
|
onlyOneFileCanBeAttached: "You can only attach one file to a message"
|
||||||
signinRequired: "Please sign in"
|
signinRequired: "Please sign in"
|
||||||
|
invitations: "Invite"
|
||||||
invitationCode: "Invitation code"
|
invitationCode: "Invitation code"
|
||||||
checking: "Checking"
|
checking: "Checking"
|
||||||
available: "Available"
|
available: "Available"
|
||||||
@ -442,8 +453,8 @@ remote: "Remote"
|
|||||||
total: "Total"
|
total: "Total"
|
||||||
weekOverWeekChanges: "Weekly"
|
weekOverWeekChanges: "Weekly"
|
||||||
dayOverDayChanges: "Daily"
|
dayOverDayChanges: "Daily"
|
||||||
accessibility: "Accessibility"
|
appearance: "Appearance"
|
||||||
clinetSettings: "Client Settings"
|
clientSettings: "Client settings"
|
||||||
accountSettings: "Account Settings"
|
accountSettings: "Account Settings"
|
||||||
promotion: "Promoted"
|
promotion: "Promoted"
|
||||||
promote: "Promote"
|
promote: "Promote"
|
||||||
@ -466,6 +477,7 @@ objectStorageUseSSL: "Use SSL"
|
|||||||
objectStorageUseSSLDesc: "Turn off this if you are not going to use HTTPS for API connection"
|
objectStorageUseSSLDesc: "Turn off this if you are not going to use HTTPS for API connection"
|
||||||
objectStorageUseProxy: "Connect over Proxy"
|
objectStorageUseProxy: "Connect over Proxy"
|
||||||
objectStorageUseProxyDesc: "Turn off this if you are not going to use Proxy for ObjectStorage connection"
|
objectStorageUseProxyDesc: "Turn off this if you are not going to use Proxy for ObjectStorage connection"
|
||||||
|
objectStorageSetPublicRead: "Set \"public-read\" on upload"
|
||||||
serverLogs: "Server logs"
|
serverLogs: "Server logs"
|
||||||
deleteAll: "Delete all"
|
deleteAll: "Delete all"
|
||||||
showFixedPostForm: "Display the posting form at the top of the timeline"
|
showFixedPostForm: "Display the posting form at the top of the timeline"
|
||||||
@ -473,6 +485,8 @@ newNoteRecived: "You've got a new note"
|
|||||||
sounds: "Sounds"
|
sounds: "Sounds"
|
||||||
listen: "Listen"
|
listen: "Listen"
|
||||||
none: "None"
|
none: "None"
|
||||||
|
showInPage: "Show in page"
|
||||||
|
popout: "Pop-out"
|
||||||
volume: "Volume"
|
volume: "Volume"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Choose an emoji"
|
chooseEmoji: "Choose an emoji"
|
||||||
@ -515,7 +529,6 @@ enableInfiniteScroll: "Enable infinite scrolling"
|
|||||||
visibility: "Visiblility"
|
visibility: "Visiblility"
|
||||||
poll: "Poll"
|
poll: "Poll"
|
||||||
useCw: "Hide content"
|
useCw: "Hide content"
|
||||||
fixedWidgetsPosition: "Make widget position fixed"
|
|
||||||
enablePlayer: "Open video player"
|
enablePlayer: "Open video player"
|
||||||
disablePlayer: "Close video player"
|
disablePlayer: "Close video player"
|
||||||
expandTweet: "Expand tweet"
|
expandTweet: "Expand tweet"
|
||||||
@ -528,6 +541,98 @@ plugins: "Plugins"
|
|||||||
pluginInstallWarn: "Please do not install untrustworthy plugins."
|
pluginInstallWarn: "Please do not install untrustworthy plugins."
|
||||||
deck: "Deck"
|
deck: "Deck"
|
||||||
undeck: "Leave Deck"
|
undeck: "Leave Deck"
|
||||||
|
useBlurEffectForModal: "Use blur effect for modals"
|
||||||
|
generateAccessToken: "Generate access token"
|
||||||
|
permission: "Permissions"
|
||||||
|
enableAll: "Enable all"
|
||||||
|
disableAll: "Disable all"
|
||||||
|
tokenRequested: "Grant access to account"
|
||||||
|
pluginTokenRequestedDescription: "This plugin will be able to use the permissions set here."
|
||||||
|
notificationType: "Notification type"
|
||||||
|
edit: "Edit"
|
||||||
|
useStarForReactionFallback: "Use ★ as fallback if the reaction emoji is unknown"
|
||||||
|
emailConfig: "Email server configuration"
|
||||||
|
enableEmail: "Enable email distribution"
|
||||||
|
emailConfigInfo: "Used to confirm your email during sign-up and if you forget your password"
|
||||||
|
email: "Email Address"
|
||||||
|
smtpConfig: "SMTP Server configuration"
|
||||||
|
smtpHost: "Host"
|
||||||
|
smtpPort: "Port"
|
||||||
|
smtpUser: "Username"
|
||||||
|
smtpPass: "Password"
|
||||||
|
emptyToDisableSmtpAuth: "Leave username and password empty to disable SMTP verification"
|
||||||
|
smtpSecure: "Use implicit SSL/TLS for SMTP connections"
|
||||||
|
smtpSecureInfo: "Turn this off when using STARTTLS"
|
||||||
|
testEmail: "Test email delivery"
|
||||||
|
wordMute: "Word mute"
|
||||||
|
userSaysSomething: "{name} said something"
|
||||||
|
makeActive: "Activate"
|
||||||
|
display: "Display"
|
||||||
|
copy: "Copy"
|
||||||
|
metrics: "Metrics"
|
||||||
|
overview: "Overview"
|
||||||
|
logs: "Logs"
|
||||||
|
delayed: "Delayed"
|
||||||
|
database: "Database"
|
||||||
|
channel: "Channels"
|
||||||
|
create: "Create"
|
||||||
|
notificationSetting: "Notification settings"
|
||||||
|
notificationSettingDesc: "Select the type of notification to display"
|
||||||
|
useGlobalSetting: "Use global setting"
|
||||||
|
useGlobalSettingDesc: "If turned on, your account's notification settings will be used. If turned off, individual configurations can be made."
|
||||||
|
other: "Other"
|
||||||
|
regenerateLoginToken: "Regenerate login token"
|
||||||
|
regenerateLoginTokenDescription: "Regenerate the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out."
|
||||||
|
setMultipleBySeparatingWithSpace: "You can set multiple by separating them with spaces."
|
||||||
|
fileIdOrUrl: "File-ID or URL"
|
||||||
|
chatOpenBehavior: "Behavior of the chat window when opened"
|
||||||
|
sample: "Sample"
|
||||||
|
abuseReports: "Reports"
|
||||||
|
reportAbuse: "Report"
|
||||||
|
reportAbuseOf: "Report {name}"
|
||||||
|
fillAbuseReportDescription: "Please fill in the report details. If it is about a specific note, please include its URL."
|
||||||
|
abuseReported: "Your report has been sent. Thank you very much."
|
||||||
|
send: "Send"
|
||||||
|
abuseMarkAsResolved: "Mark report as resolved"
|
||||||
|
openInNewTab: "Open in new tab"
|
||||||
|
openInSideView: "Open in side view"
|
||||||
|
defaultNavigationBehaviour: "Default navigation behavior"
|
||||||
|
editTheseSettingsMayBreakAccount: "Editing these settings may damage your account."
|
||||||
|
instanceTicker: "Instance information of the Note"
|
||||||
|
random: "Random"
|
||||||
|
_reversi:
|
||||||
|
total: "Total"
|
||||||
|
_instanceTicker:
|
||||||
|
none: "Never show"
|
||||||
|
remote: "Show for remote users"
|
||||||
|
always: "Always show"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "Automatically reload"
|
||||||
|
dialog: "Show warning dialog"
|
||||||
|
quiet: "Show unobtrusive warning"
|
||||||
|
_channel:
|
||||||
|
create: "Create channel"
|
||||||
|
edit: "Edit channel"
|
||||||
|
setBanner: "Set banner"
|
||||||
|
removeBanner: "Remove banner"
|
||||||
|
featured: "Trending"
|
||||||
|
owned: "Owned"
|
||||||
|
following: "Followed"
|
||||||
|
usersCount: "{n} Participants"
|
||||||
|
notesCount: "{n} Notes"
|
||||||
|
_sidebar:
|
||||||
|
full: "Full"
|
||||||
|
icon: "Avatar"
|
||||||
|
hide: "Hide"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "Word to mute"
|
||||||
|
muteWordsDescription: "Separate with spaces for AND condition. Separate with line breaks for OR."
|
||||||
|
muteWordsDescription2: "Surround keywords by slashes to use regular expressions."
|
||||||
|
softDescription: "Hide notes fulfilling the set conditions from the timeline."
|
||||||
|
hardDescription: "Prevent notes fulfilling the set conditions from being added to the timeline. In addition, these notes will not be added to the timeline even if the conditions are changed."
|
||||||
|
soft: "Soft"
|
||||||
|
hard: "Hard"
|
||||||
|
mutedNotes: "Muted notes"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Explore Themes"
|
explore: "Explore Themes"
|
||||||
install: "Install theme"
|
install: "Install theme"
|
||||||
@ -548,7 +653,7 @@ _theme:
|
|||||||
func: "Functions"
|
func: "Functions"
|
||||||
funcKind: "Function type"
|
funcKind: "Function type"
|
||||||
argument: "Argument"
|
argument: "Argument"
|
||||||
basedProp: "Name of the referenced property"
|
basedProp: "Referenced property"
|
||||||
alpha: "Opacity"
|
alpha: "Opacity"
|
||||||
darken: "Darken"
|
darken: "Darken"
|
||||||
lighten: "Lighten"
|
lighten: "Lighten"
|
||||||
@ -606,6 +711,7 @@ _sfx:
|
|||||||
chat: "Messaging"
|
chat: "Messaging"
|
||||||
chatBg: "Messaging (Background)"
|
chatBg: "Messaging (Background)"
|
||||||
antenna: "Antenna Reception"
|
antenna: "Antenna Reception"
|
||||||
|
channel: "Channel notifications"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Unknown"
|
unknown: "Unknown"
|
||||||
future: "Future"
|
future: "Future"
|
||||||
@ -681,6 +787,8 @@ _permissions:
|
|||||||
"write:page-likes": "Edit likes on pages"
|
"write:page-likes": "Edit likes on pages"
|
||||||
"read:user-groups": "View user groups"
|
"read:user-groups": "View user groups"
|
||||||
"write:user-groups": "Edit or delete user groups"
|
"write:user-groups": "Edit or delete user groups"
|
||||||
|
"read:channels": "Read channels"
|
||||||
|
"write:channels": "Modify channels"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
||||||
shareAccessAsk: "Are you sure you want to authorize this application to access your account?"
|
shareAccessAsk: "Are you sure you want to authorize this application to access your account?"
|
||||||
@ -713,6 +821,8 @@ _widgets:
|
|||||||
activity: "Activity"
|
activity: "Activity"
|
||||||
photos: "Photos"
|
photos: "Photos"
|
||||||
digitalClock: "Digital clock"
|
digitalClock: "Digital clock"
|
||||||
|
federation: "Federation"
|
||||||
|
postForm: "Compose a note"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Hide"
|
hide: "Hide"
|
||||||
show: "Load more"
|
show: "Load more"
|
||||||
@ -754,6 +864,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Reply to this note..."
|
replyPlaceholder: "Reply to this note..."
|
||||||
quotePlaceholder: "Quote this note..."
|
quotePlaceholder: "Quote this note..."
|
||||||
|
channelPlaceholder: "Post to channel"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "What are you up to?"
|
a: "What are you up to?"
|
||||||
b: "What's happening around you?"
|
b: "What's happening around you?"
|
||||||
@ -1166,10 +1277,29 @@ _notification:
|
|||||||
youReceivedFollowRequest: "You've received a follow request"
|
youReceivedFollowRequest: "You've received a follow request"
|
||||||
yourFollowRequestAccepted: "Your follow request was accepted"
|
yourFollowRequestAccepted: "Your follow request was accepted"
|
||||||
youWereInvitedToGroup: "Invited to group"
|
youWereInvitedToGroup: "Invited to group"
|
||||||
|
_types:
|
||||||
|
all: "All"
|
||||||
|
follow: "Follows"
|
||||||
|
mention: "Mentions"
|
||||||
|
reply: "Replies"
|
||||||
|
renote: "Renotes"
|
||||||
|
quote: "Quotes"
|
||||||
|
reaction: "Reactions"
|
||||||
|
pollVote: "Votes on polls"
|
||||||
|
receiveFollowRequest: "Follow request received"
|
||||||
|
followRequestAccepted: "Follow request accepted"
|
||||||
|
groupInvited: "Invited to groups"
|
||||||
|
app: "Notifications from apps"
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "Always show main column"
|
alwaysShowMainColumn: "Always show main column"
|
||||||
columnAlign: "Align columns"
|
columnAlign: "Align columns"
|
||||||
addColumn: "Add column"
|
addColumn: "Add column"
|
||||||
|
swapLeft: "Swap to left"
|
||||||
|
swapRight: "Swap to right"
|
||||||
|
swapUp: "Swap with above"
|
||||||
|
swapDown: "Swap with below"
|
||||||
|
stackLeft: "Stack on the left"
|
||||||
|
popRight: "Pop to the right"
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "Widgets"
|
widgets: "Widgets"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "No hay notas"
|
|||||||
noNotifications: "No hay notificaciones"
|
noNotifications: "No hay notificaciones"
|
||||||
instance: "Instancia"
|
instance: "Instancia"
|
||||||
settings: "Configuración"
|
settings: "Configuración"
|
||||||
|
basicSettings: "Configuración Básica"
|
||||||
|
otherSettings: "Configuración avanzada"
|
||||||
|
openInWindow: "Abrir en una ventana"
|
||||||
profile: "Perfil"
|
profile: "Perfil"
|
||||||
timeline: "Linea de tiempo"
|
timeline: "Linea de tiempo"
|
||||||
noAccountDescription: "Este usuario no tiene una descripción"
|
noAccountDescription: "Este usuario no tiene una descripción"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "¿Quieres borrar y editar este nota? Las reacciones, reno
|
|||||||
addToList: "Agregar a lista"
|
addToList: "Agregar a lista"
|
||||||
sendMessage: "Énviar mensaje"
|
sendMessage: "Énviar mensaje"
|
||||||
copyUsername: "Copiar nombre de usuario"
|
copyUsername: "Copiar nombre de usuario"
|
||||||
|
searchUser: "Búsqueda de usuarios"
|
||||||
reply: "Responder"
|
reply: "Responder"
|
||||||
loadMore: "Ver más"
|
loadMore: "Ver más"
|
||||||
youGotNewFollower: "te ha seguido"
|
youGotNewFollower: "te ha seguido"
|
||||||
@ -66,8 +70,11 @@ followers: "Seguidores"
|
|||||||
followsYou: "Te sigue"
|
followsYou: "Te sigue"
|
||||||
createList: "Crear lista"
|
createList: "Crear lista"
|
||||||
manageLists: "Administrar listas"
|
manageLists: "Administrar listas"
|
||||||
error: "Ocurrió un problema"
|
error: "Error"
|
||||||
|
somethingHappened: "Ocurrió un error"
|
||||||
retry: "Reintentar"
|
retry: "Reintentar"
|
||||||
|
pageLoadError: "Error al leer la página"
|
||||||
|
pageLoadErrorDescription: "Normalmente es debido a la red o al caché del navegador. Por favor limpie el caché o intente más tarde."
|
||||||
enterListName: "Ingrese nombre de lista"
|
enterListName: "Ingrese nombre de lista"
|
||||||
privacy: "Privacidad"
|
privacy: "Privacidad"
|
||||||
makeFollowManuallyApprove: "Aprobar manualmente las solicitudes de seguimiento"
|
makeFollowManuallyApprove: "Aprobar manualmente las solicitudes de seguimiento"
|
||||||
@ -104,6 +111,10 @@ unblockConfirm: "¿Quiere dejar de bloquear esta cuenta?"
|
|||||||
suspendConfirm: "¿Quiere suspender esta cuenta?"
|
suspendConfirm: "¿Quiere suspender esta cuenta?"
|
||||||
unsuspendConfirm: "¿Quiere dejar de suspender esta cuenta?"
|
unsuspendConfirm: "¿Quiere dejar de suspender esta cuenta?"
|
||||||
selectList: "Seleccione una lista"
|
selectList: "Seleccione una lista"
|
||||||
|
selectAntenna: "Seleccionar antena"
|
||||||
|
selectWidget: "Seleccionar widget"
|
||||||
|
editWidgets: "Editar widgets"
|
||||||
|
editWidgetsExit: "Terminar edición"
|
||||||
customEmojis: "Emojis personalizados"
|
customEmojis: "Emojis personalizados"
|
||||||
emoji: "Emoji"
|
emoji: "Emoji"
|
||||||
emojiName: "Nombre del emoji"
|
emojiName: "Nombre del emoji"
|
||||||
@ -175,7 +186,6 @@ processing: "Procesando"
|
|||||||
preview: "Vista previa"
|
preview: "Vista previa"
|
||||||
default: "Predeterminado"
|
default: "Predeterminado"
|
||||||
noCustomEmojis: "No hay emojis personalizados"
|
noCustomEmojis: "No hay emojis personalizados"
|
||||||
customEmojisOfRemote: "Emojis remotos"
|
|
||||||
noJobs: "No hay trabajos"
|
noJobs: "No hay trabajos"
|
||||||
federating: "Federando"
|
federating: "Federando"
|
||||||
blocked: "Bloqueando"
|
blocked: "Bloqueando"
|
||||||
@ -262,6 +272,7 @@ rename: "Renombrar"
|
|||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
nsfw: "Marcado como sensible"
|
nsfw: "Marcado como sensible"
|
||||||
|
whenServerDisconnected: "Cuando se pierda la conexión con el servidor"
|
||||||
disconnectedFromServer: "Desconectado del servidor"
|
disconnectedFromServer: "Desconectado del servidor"
|
||||||
reload: "Recargar"
|
reload: "Recargar"
|
||||||
doNothing: "No hacer nada"
|
doNothing: "No hacer nada"
|
||||||
@ -362,7 +373,6 @@ unregister: "Cancelar registro"
|
|||||||
passwordLessLogin: "Iniciar sesión sin contraseña"
|
passwordLessLogin: "Iniciar sesión sin contraseña"
|
||||||
resetPassword: "Resetear contraseña"
|
resetPassword: "Resetear contraseña"
|
||||||
newPasswordIs: "La nueva contraseña es \"{password}\""
|
newPasswordIs: "La nueva contraseña es \"{password}\""
|
||||||
autoReloadWhenDisconnected: "Recargar automáticamente cuando el servidor está desconectado"
|
|
||||||
autoNoteWatch: "Ver nota automáticamente"
|
autoNoteWatch: "Ver nota automáticamente"
|
||||||
autoNoteWatchDescription: "Recibe notificaciones sobre las notas de otros usuarios que a los que respondiste y reaccionaste"
|
autoNoteWatchDescription: "Recibe notificaciones sobre las notas de otros usuarios que a los que respondiste y reaccionaste"
|
||||||
reduceUiAnimation: "Reducir la animación de la UI"
|
reduceUiAnimation: "Reducir la animación de la UI"
|
||||||
@ -402,6 +412,7 @@ noMessagesYet: "Aún no hay chat"
|
|||||||
newMessageExists: "Tienes un mensaje nuevo"
|
newMessageExists: "Tienes un mensaje nuevo"
|
||||||
onlyOneFileCanBeAttached: "Solo se puede añadir un archivo al mensaje"
|
onlyOneFileCanBeAttached: "Solo se puede añadir un archivo al mensaje"
|
||||||
signinRequired: "Iniciar sesión"
|
signinRequired: "Iniciar sesión"
|
||||||
|
invitations: "Invitar"
|
||||||
invitationCode: "Código de invitación"
|
invitationCode: "Código de invitación"
|
||||||
checking: "Comprobando"
|
checking: "Comprobando"
|
||||||
available: "Disponible"
|
available: "Disponible"
|
||||||
@ -442,8 +453,8 @@ remote: "Remoto"
|
|||||||
total: "Total"
|
total: "Total"
|
||||||
weekOverWeekChanges: "Dif semanal"
|
weekOverWeekChanges: "Dif semanal"
|
||||||
dayOverDayChanges: "Dif diaria"
|
dayOverDayChanges: "Dif diaria"
|
||||||
accessibility: "Accesibilidad"
|
appearance: "Apariencia"
|
||||||
clinetSettings: "Ajustes del cliente"
|
clientSettings: "Configuración del cliente"
|
||||||
accountSettings: "Ajustes de cuenta"
|
accountSettings: "Ajustes de cuenta"
|
||||||
promotion: "Promovido"
|
promotion: "Promovido"
|
||||||
promote: "Promover"
|
promote: "Promover"
|
||||||
@ -466,6 +477,7 @@ objectStorageUseSSL: "Usar SSL"
|
|||||||
objectStorageUseSSLDesc: "Desactive esto si no va a usar HTTPS para la conexión API"
|
objectStorageUseSSLDesc: "Desactive esto si no va a usar HTTPS para la conexión API"
|
||||||
objectStorageUseProxy: "Conectarse a través de Proxy"
|
objectStorageUseProxy: "Conectarse a través de Proxy"
|
||||||
objectStorageUseProxyDesc: "Desactive esto si no va a usar Proxy para la conexión de Almacenamiento de objetos"
|
objectStorageUseProxyDesc: "Desactive esto si no va a usar Proxy para la conexión de Almacenamiento de objetos"
|
||||||
|
objectStorageSetPublicRead: "Seleccionar \"public-read\" al subir "
|
||||||
serverLogs: "Registros del servidor"
|
serverLogs: "Registros del servidor"
|
||||||
deleteAll: "Eliminar todos"
|
deleteAll: "Eliminar todos"
|
||||||
showFixedPostForm: "Mostrar el formulario de las entradas encima de la línea de tiempo"
|
showFixedPostForm: "Mostrar el formulario de las entradas encima de la línea de tiempo"
|
||||||
@ -473,6 +485,8 @@ newNoteRecived: "Tienes una nota nuevo"
|
|||||||
sounds: "Sonidos"
|
sounds: "Sonidos"
|
||||||
listen: "Escuchar"
|
listen: "Escuchar"
|
||||||
none: "Ninguna"
|
none: "Ninguna"
|
||||||
|
showInPage: "Mostrar en la página"
|
||||||
|
popout: "Popout"
|
||||||
volume: "Volumen"
|
volume: "Volumen"
|
||||||
details: "Detalles"
|
details: "Detalles"
|
||||||
chooseEmoji: "Elije un emoji"
|
chooseEmoji: "Elije un emoji"
|
||||||
@ -515,7 +529,6 @@ enableInfiniteScroll: "Activar scroll infinito"
|
|||||||
visibility: "Visibilidad"
|
visibility: "Visibilidad"
|
||||||
poll: "Encuesta"
|
poll: "Encuesta"
|
||||||
useCw: "Esconder contenidos"
|
useCw: "Esconder contenidos"
|
||||||
fixedWidgetsPosition: "Fijar la posición de los widgets"
|
|
||||||
enablePlayer: "Abrir reproductor"
|
enablePlayer: "Abrir reproductor"
|
||||||
disablePlayer: "Cerrar reproductor"
|
disablePlayer: "Cerrar reproductor"
|
||||||
expandTweet: "Expandir tweet"
|
expandTweet: "Expandir tweet"
|
||||||
@ -526,6 +539,95 @@ leaveConfirm: "Hay modificaciones sin guardar. ¿Desea descartarlas?"
|
|||||||
manage: "Administrar"
|
manage: "Administrar"
|
||||||
plugins: "Plugins"
|
plugins: "Plugins"
|
||||||
pluginInstallWarn: "Por favor no instale plugins que no son de confianza"
|
pluginInstallWarn: "Por favor no instale plugins que no son de confianza"
|
||||||
|
deck: "Deck"
|
||||||
|
undeck: "Quitar deck"
|
||||||
|
useBlurEffectForModal: "Usar efecto borroso en modales"
|
||||||
|
generateAccessToken: "Generar token de acceso"
|
||||||
|
permission: "Permisos"
|
||||||
|
enableAll: "Activar todo"
|
||||||
|
disableAll: "Desactivar todo"
|
||||||
|
tokenRequested: "Permiso de acceso a la cuenta"
|
||||||
|
pluginTokenRequestedDescription: "Este plugin podrá usar los permisos descritos aquí"
|
||||||
|
notificationType: "Tipo de notificación"
|
||||||
|
edit: "Editar"
|
||||||
|
useStarForReactionFallback: "En caso de que los emojis de reacciones no sean claros, usar en su lugar una estrella"
|
||||||
|
emailConfig: "Configuración del servidor de correos"
|
||||||
|
enableEmail: "Activar el envío de correos electrónicos"
|
||||||
|
emailConfigInfo: "Usar en caso de validación de correo electrónico y pedido de contraseña"
|
||||||
|
email: "Correo electrónico"
|
||||||
|
smtpConfig: "Configuración del servidor SMTP"
|
||||||
|
smtpHost: "Host"
|
||||||
|
smtpPort: "Puerto"
|
||||||
|
smtpUser: "Nombre de usuario"
|
||||||
|
smtpPass: "Contraseña"
|
||||||
|
emptyToDisableSmtpAuth: "Deje el nombre del usuario y la contraseña en blanco para deshabilitar la autenticación SMTP"
|
||||||
|
smtpSecure: "Usar SSL/TLS implícito en la conexión SMTP"
|
||||||
|
smtpSecureInfo: "Apagar cuando se use STARTTLS"
|
||||||
|
testEmail: "Prueba de envío"
|
||||||
|
wordMute: "Silenciar palabras"
|
||||||
|
userSaysSomething: "{name} dijo algo"
|
||||||
|
makeActive: "Activar"
|
||||||
|
display: "Apariencia"
|
||||||
|
copy: "Copiar"
|
||||||
|
metrics: "Métricas"
|
||||||
|
overview: "Resumen"
|
||||||
|
logs: "Registros"
|
||||||
|
delayed: "atrasado"
|
||||||
|
database: "Base de datos"
|
||||||
|
channel: "Canal"
|
||||||
|
create: "Crear"
|
||||||
|
notificationSetting: "Ajustes de Notificaciones"
|
||||||
|
notificationSettingDesc: "Por favor elija el tipo de notificación a mostrar"
|
||||||
|
useGlobalSetting: "Usar ajustes globales"
|
||||||
|
useGlobalSettingDesc: "Al activarse, se usará la configuración de notificaciones de la cuenta, al desactivarse se pueden hacer configuraciones particulares."
|
||||||
|
other: "Otro"
|
||||||
|
regenerateLoginToken: "Regenerar token de login"
|
||||||
|
regenerateLoginTokenDescription: "Regenerar el token usado internamente durante el login. No siempre es necesario hacerlo. Al hacerlo de nuevo, se deslogueará en todos los dispositivos."
|
||||||
|
setMultipleBySeparatingWithSpace: "Puedes añadir mas de uno, separado por espacios."
|
||||||
|
fileIdOrUrl: "Id del archivo o URL"
|
||||||
|
chatOpenBehavior: "Comportamiento al abrir el chat"
|
||||||
|
sample: "Muestra"
|
||||||
|
abuseReports: "Reportes"
|
||||||
|
reportAbuse: "Reportar"
|
||||||
|
reportAbuseOf: "Reportar a {name}"
|
||||||
|
fillAbuseReportDescription: "Ingrese los detalles del reporte. Si hay una nota en particular, ingrese la URL de esta."
|
||||||
|
abuseReported: "Se ha enviado el reporte. Muchas gracias."
|
||||||
|
send: "Enviar"
|
||||||
|
abuseMarkAsResolved: "Marcar reporte como resuelto"
|
||||||
|
openInNewTab: "Abrir en una Nueva Pestaña"
|
||||||
|
openInSideView: "Abrir en una vista al costado"
|
||||||
|
defaultNavigationBehaviour: "Navegación por defecto"
|
||||||
|
editTheseSettingsMayBreakAccount: "Editar estas configuraciones puede dañar su cuenta."
|
||||||
|
random: "Aleatorio"
|
||||||
|
_reversi:
|
||||||
|
total: "Total"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "Recargar automáticamente"
|
||||||
|
dialog: "Mostrar diálogo de advertencia"
|
||||||
|
quiet: "Advertencia discreta"
|
||||||
|
_channel:
|
||||||
|
create: "Crear canal"
|
||||||
|
edit: "Editar canal"
|
||||||
|
setBanner: "Elegir banner"
|
||||||
|
removeBanner: "Borrar banner"
|
||||||
|
featured: "Tendencias"
|
||||||
|
owned: "Dueño"
|
||||||
|
following: "Siguiendo"
|
||||||
|
usersCount: "{n} participantes"
|
||||||
|
notesCount: "{n} notas"
|
||||||
|
_sidebar:
|
||||||
|
full: "Completo"
|
||||||
|
icon: "Avatar"
|
||||||
|
hide: "Ocultar"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "Palabras que silenciar"
|
||||||
|
muteWordsDescription: "Separar con espacios indica una declaracion And, separar con lineas nuevas indica una declaracion Or。"
|
||||||
|
muteWordsDescription2: "Encerrar las palabras clave entre numerales para usar expresiones regulares"
|
||||||
|
softDescription: "Ocultar en la linea de tiempo las notas que cumplen las condiciones"
|
||||||
|
hardDescription: "Evitar que se agreguen a la linea de tiempo las notas que cumplen las condiciones. Las notas no agregadas seguirán quitadas aunque cambien las condiciones."
|
||||||
|
soft: "Suave"
|
||||||
|
hard: "Duro"
|
||||||
|
mutedNotes: "Notas silenciadas"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Explorar temas"
|
explore: "Explorar temas"
|
||||||
install: "Instalar tema"
|
install: "Instalar tema"
|
||||||
@ -604,6 +706,7 @@ _sfx:
|
|||||||
chat: "Chat"
|
chat: "Chat"
|
||||||
chatBg: "Chat (Fondo)"
|
chatBg: "Chat (Fondo)"
|
||||||
antenna: "Antena receptora"
|
antenna: "Antena receptora"
|
||||||
|
channel: "Notificaciones del canal"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Desconocido"
|
unknown: "Desconocido"
|
||||||
future: "Futuro"
|
future: "Futuro"
|
||||||
@ -679,6 +782,8 @@ _permissions:
|
|||||||
"write:page-likes": "Administrar páginas que te gustan"
|
"write:page-likes": "Administrar páginas que te gustan"
|
||||||
"read:user-groups": "Ver grupos de usuarios"
|
"read:user-groups": "Ver grupos de usuarios"
|
||||||
"write:user-groups": "Administrar grupos de usuarios"
|
"write:user-groups": "Administrar grupos de usuarios"
|
||||||
|
"read:channels": "Ver canal"
|
||||||
|
"write:channels": "Modificar canal"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
|
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
|
||||||
shareAccessAsk: "¿Está seguro de que desea autorizar esta aplicación para acceder a su cuenta?"
|
shareAccessAsk: "¿Está seguro de que desea autorizar esta aplicación para acceder a su cuenta?"
|
||||||
@ -711,6 +816,8 @@ _widgets:
|
|||||||
activity: "Actividad"
|
activity: "Actividad"
|
||||||
photos: "Fotos"
|
photos: "Fotos"
|
||||||
digitalClock: "Reloj digital"
|
digitalClock: "Reloj digital"
|
||||||
|
federation: "Federación"
|
||||||
|
postForm: "Formulario"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Ocultar"
|
hide: "Ocultar"
|
||||||
show: "Ver más"
|
show: "Ver más"
|
||||||
@ -752,6 +859,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Responder a esta nota"
|
replyPlaceholder: "Responder a esta nota"
|
||||||
quotePlaceholder: "Citar esta nota"
|
quotePlaceholder: "Citar esta nota"
|
||||||
|
channelPlaceholder: "Postear en el canal"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "¿Qué haces?"
|
a: "¿Qué haces?"
|
||||||
b: "¿Te pasó algo?"
|
b: "¿Te pasó algo?"
|
||||||
@ -1164,9 +1272,29 @@ _notification:
|
|||||||
youReceivedFollowRequest: "Has mandado una solicitud de seguimiento"
|
youReceivedFollowRequest: "Has mandado una solicitud de seguimiento"
|
||||||
yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada"
|
yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada"
|
||||||
youWereInvitedToGroup: "Invitado al grupo"
|
youWereInvitedToGroup: "Invitado al grupo"
|
||||||
|
_types:
|
||||||
|
all: "Todo"
|
||||||
|
follow: "Siguiendo"
|
||||||
|
mention: "Menciones"
|
||||||
|
reply: "Respuestas"
|
||||||
|
renote: "Renotar"
|
||||||
|
quote: "Citar"
|
||||||
|
reaction: "Reacción"
|
||||||
|
pollVote: "Votado en la encuesta"
|
||||||
|
receiveFollowRequest: "Recibió una solicitud de seguimiento"
|
||||||
|
followRequestAccepted: "El seguimiento fue aceptado"
|
||||||
|
groupInvited: "Invitado al grupo"
|
||||||
|
app: "Notificaciones desde aplicaciones"
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "Siempre mostrar la columna principal"
|
alwaysShowMainColumn: "Siempre mostrar la columna principal"
|
||||||
columnAlign: "Alinear columnas"
|
columnAlign: "Alinear columnas"
|
||||||
|
addColumn: "Agregar columna"
|
||||||
|
swapLeft: "Mover a la izquierda"
|
||||||
|
swapRight: "Mover a la derecha"
|
||||||
|
swapUp: "Mover arriba"
|
||||||
|
swapDown: "Mover abajo"
|
||||||
|
stackLeft: "Apilar a la izquierda"
|
||||||
|
popRight: "Sacar a la derecha"
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "Widgets"
|
widgets: "Widgets"
|
||||||
notifications: "Notificaciones"
|
notifications: "Notificaciones"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "Aucune note"
|
|||||||
noNotifications: "Aucune notification"
|
noNotifications: "Aucune notification"
|
||||||
instance: "Instance"
|
instance: "Instance"
|
||||||
settings: "Paramètres"
|
settings: "Paramètres"
|
||||||
|
basicSettings: "Paramètres basiques"
|
||||||
|
otherSettings: "Autres paramètres"
|
||||||
|
openInWindow: "Ouvrir dans une nouvelle fenêtre"
|
||||||
profile: "Profil"
|
profile: "Profil"
|
||||||
timeline: "Fil"
|
timeline: "Fil"
|
||||||
noAccountDescription: "L’utilisateur·rice n’a pas encore renseigné de biographie de présentation sur son profil."
|
noAccountDescription: "L’utilisateur·rice n’a pas encore renseigné de biographie de présentation sur son profil."
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note et la
|
|||||||
addToList: "Ajouter à une liste"
|
addToList: "Ajouter à une liste"
|
||||||
sendMessage: "Envoyer un message"
|
sendMessage: "Envoyer un message"
|
||||||
copyUsername: "Copier le nom d’utilisateur·rice"
|
copyUsername: "Copier le nom d’utilisateur·rice"
|
||||||
|
searchUser: "Chercher un·e utilisateur·rice"
|
||||||
reply: "Répondre"
|
reply: "Répondre"
|
||||||
loadMore: "Afficher plus …"
|
loadMore: "Afficher plus …"
|
||||||
youGotNewFollower: "Vous suit"
|
youGotNewFollower: "Vous suit"
|
||||||
@ -66,8 +70,10 @@ followers: "Abonné·e·s"
|
|||||||
followsYou: "Vous suit"
|
followsYou: "Vous suit"
|
||||||
createList: "Créer une liste"
|
createList: "Créer une liste"
|
||||||
manageLists: "Gérer les listes"
|
manageLists: "Gérer les listes"
|
||||||
error: "Une erreur est survenue"
|
error: "Erreur"
|
||||||
|
somethingHappened: "Une erreur est survenue"
|
||||||
retry: "Réessayer"
|
retry: "Réessayer"
|
||||||
|
pageLoadError: "Le chargement de la page a échoué"
|
||||||
enterListName: "Nom de la liste"
|
enterListName: "Nom de la liste"
|
||||||
privacy: "Confidentialité"
|
privacy: "Confidentialité"
|
||||||
makeFollowManuallyApprove: "Accepter manuellement les demandes d’abonnement"
|
makeFollowManuallyApprove: "Accepter manuellement les demandes d’abonnement"
|
||||||
@ -104,6 +110,10 @@ unblockConfirm: "Êtes-vous sûr·e de vouloir débloquer ce compte ?"
|
|||||||
suspendConfirm: "Êtes-vous sûr·e de vouloir suspendre ce compte ?"
|
suspendConfirm: "Êtes-vous sûr·e de vouloir suspendre ce compte ?"
|
||||||
unsuspendConfirm: "Êtes-vous sûr·e de vouloir annuler la suspension de ce compte ?"
|
unsuspendConfirm: "Êtes-vous sûr·e de vouloir annuler la suspension de ce compte ?"
|
||||||
selectList: "Sélectionner une liste"
|
selectList: "Sélectionner une liste"
|
||||||
|
selectAntenna: "Sélectionner une antenne"
|
||||||
|
selectWidget: "Sélectionner un widget"
|
||||||
|
editWidgets: "Modifier les widgets"
|
||||||
|
editWidgetsExit: "Fait"
|
||||||
customEmojis: "Émojis personnalisés"
|
customEmojis: "Émojis personnalisés"
|
||||||
emoji: "Émoji"
|
emoji: "Émoji"
|
||||||
emojiName: "Nom de l’émoji"
|
emojiName: "Nom de l’émoji"
|
||||||
@ -175,7 +185,6 @@ processing: "Traitement en cours"
|
|||||||
preview: "Prévisualisation"
|
preview: "Prévisualisation"
|
||||||
default: "Par défaut"
|
default: "Par défaut"
|
||||||
noCustomEmojis: "Il n'y a pas d’émoji"
|
noCustomEmojis: "Il n'y a pas d’émoji"
|
||||||
customEmojisOfRemote: "Émojis provenant des autres instances"
|
|
||||||
noJobs: "Il n’y a aucune tâche planifiée"
|
noJobs: "Il n’y a aucune tâche planifiée"
|
||||||
federating: "En cours de fédération"
|
federating: "En cours de fédération"
|
||||||
blocked: "Bloqué·e"
|
blocked: "Bloqué·e"
|
||||||
@ -262,6 +271,7 @@ rename: "Renommer"
|
|||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
banner: "Bannière"
|
banner: "Bannière"
|
||||||
nsfw: "Contenu sensible"
|
nsfw: "Contenu sensible"
|
||||||
|
whenServerDisconnected: "Lorsque la connexion au serveur est perdue"
|
||||||
disconnectedFromServer: "Déconnecté·e du serveur"
|
disconnectedFromServer: "Déconnecté·e du serveur"
|
||||||
reload: "Rafraîchir"
|
reload: "Rafraîchir"
|
||||||
doNothing: "Ignorer"
|
doNothing: "Ignorer"
|
||||||
@ -362,7 +372,6 @@ unregister: "Se désinscrire"
|
|||||||
passwordLessLogin: "Connectez-vous sans mot de passe"
|
passwordLessLogin: "Connectez-vous sans mot de passe"
|
||||||
resetPassword: "Réinitialiser mot de passe"
|
resetPassword: "Réinitialiser mot de passe"
|
||||||
newPasswordIs: "Votre nouveau mot de passe est \"{password}\""
|
newPasswordIs: "Votre nouveau mot de passe est \"{password}\""
|
||||||
autoReloadWhenDisconnected: "Rechargement automatique lorsque le serveur se déconnecte"
|
|
||||||
autoNoteWatch: "Surveiller les notes automatiquement"
|
autoNoteWatch: "Surveiller les notes automatiquement"
|
||||||
autoNoteWatchDescription: "Soyez informé des notes auxquelles vous avez réagi ou répondu."
|
autoNoteWatchDescription: "Soyez informé des notes auxquelles vous avez réagi ou répondu."
|
||||||
reduceUiAnimation: "Réduire les animations dans l’interface"
|
reduceUiAnimation: "Réduire les animations dans l’interface"
|
||||||
@ -402,6 +411,7 @@ noMessagesYet: "Pas encore discuté"
|
|||||||
newMessageExists: "Vous avez un nouveau message"
|
newMessageExists: "Vous avez un nouveau message"
|
||||||
onlyOneFileCanBeAttached: "Vous ne pouvez joindre qu’un seul fichier au message"
|
onlyOneFileCanBeAttached: "Vous ne pouvez joindre qu’un seul fichier au message"
|
||||||
signinRequired: "Veuillez vous connecter"
|
signinRequired: "Veuillez vous connecter"
|
||||||
|
invitations: "Inviter"
|
||||||
invitationCode: "Code d’invitation"
|
invitationCode: "Code d’invitation"
|
||||||
checking: "Vérification"
|
checking: "Vérification"
|
||||||
available: "Disponible"
|
available: "Disponible"
|
||||||
@ -442,8 +452,8 @@ remote: "Distant"
|
|||||||
total: "Total"
|
total: "Total"
|
||||||
weekOverWeekChanges: "Diff hebdo"
|
weekOverWeekChanges: "Diff hebdo"
|
||||||
dayOverDayChanges: "Diff quotidien"
|
dayOverDayChanges: "Diff quotidien"
|
||||||
accessibility: "Accessibilité"
|
appearance: "Aspect"
|
||||||
clinetSettings: "Paramètres du client"
|
clientSettings: "Paramètres du client"
|
||||||
accountSettings: "Paramètres du compte"
|
accountSettings: "Paramètres du compte"
|
||||||
promotion: "Promu"
|
promotion: "Promu"
|
||||||
promote: "Promouvoir"
|
promote: "Promouvoir"
|
||||||
@ -473,6 +483,7 @@ newNoteRecived: "Vous avez une nouvelle note"
|
|||||||
sounds: "Sons"
|
sounds: "Sons"
|
||||||
listen: "Écouter"
|
listen: "Écouter"
|
||||||
none: "Rien"
|
none: "Rien"
|
||||||
|
popout: "Fenêtre contextuelle"
|
||||||
volume: "Volume"
|
volume: "Volume"
|
||||||
details: "Détails"
|
details: "Détails"
|
||||||
chooseEmoji: "Choisissez un émoji"
|
chooseEmoji: "Choisissez un émoji"
|
||||||
@ -515,15 +526,81 @@ enableInfiniteScroll: "Activer le défilement infini"
|
|||||||
visibility: "Visibilité"
|
visibility: "Visibilité"
|
||||||
poll: "Sondage"
|
poll: "Sondage"
|
||||||
useCw: "Masquer le contenu"
|
useCw: "Masquer le contenu"
|
||||||
fixedWidgetsPosition: "Rendre la position du widget fixe"
|
|
||||||
enablePlayer: "Activer le lecteur vidéo"
|
enablePlayer: "Activer le lecteur vidéo"
|
||||||
disablePlayer: "Désactiver le lecteur vidéo"
|
disablePlayer: "Désactiver le lecteur vidéo"
|
||||||
expandTweet: "Étendre le tweet"
|
expandTweet: "Étendre le tweet"
|
||||||
themeEditor: "Éditeur de thèmes"
|
themeEditor: "Éditeur de thèmes"
|
||||||
description: "Description"
|
description: "Description"
|
||||||
author: "Auteur·rice"
|
author: "Auteur·rice"
|
||||||
|
leaveConfirm: "Vous avez des modifications non-sauvegardées. Voulez-vous les ignorer ?"
|
||||||
manage: "Gestion"
|
manage: "Gestion"
|
||||||
plugins: "Extensions"
|
plugins: "Extensions"
|
||||||
|
pluginInstallWarn: "N’installez que des extensions provenant de sources de confiance."
|
||||||
|
deck: "Deck"
|
||||||
|
undeck: "Quitter le deck"
|
||||||
|
useBlurEffectForModal: "Utiliser un effet de flou pour les modals"
|
||||||
|
generateAccessToken: "Générer un jeton d'accès"
|
||||||
|
permission: "Autorisations "
|
||||||
|
enableAll: "Tout activer"
|
||||||
|
disableAll: "Tout désactiver"
|
||||||
|
tokenRequested: "Autoriser l'accès au compte"
|
||||||
|
pluginTokenRequestedDescription: "Ce plugin pourra utiliser les autorisations définies ici."
|
||||||
|
notificationType: "Type de notifications"
|
||||||
|
edit: "Editer"
|
||||||
|
useStarForReactionFallback: "Utiliser ★ comme alternative si l’émoji de réaction est inconnu"
|
||||||
|
emailConfig: "Configuration du serveur email"
|
||||||
|
enableEmail: "Activer la distribution de courriel"
|
||||||
|
emailConfigInfo: "Utilisé pour confirmer votre adresse de courriel et la réinitialisation de votre mot de passe en cas d’oubli."
|
||||||
|
email: "Adresse de courrier électronique"
|
||||||
|
smtpConfig: "Paramètres du serveur SMTP"
|
||||||
|
smtpHost: "Hôte"
|
||||||
|
smtpPort: "Port"
|
||||||
|
smtpUser: "Nom d’utilisateur·rice"
|
||||||
|
smtpPass: "Mot de passe"
|
||||||
|
emptyToDisableSmtpAuth: "Laisser le nom d’utilisateur et le mot de passe vides pour désactiver la vérification SMTP"
|
||||||
|
smtpSecure: "Utiliser SSL/TLS implicitement dans les connexions SMTP"
|
||||||
|
smtpSecureInfo: "Désactiver cette option lorsque STARTTLS est utilisé"
|
||||||
|
testEmail: "Tester la distribution de courriel"
|
||||||
|
wordMute: "Filtre de mots"
|
||||||
|
userSaysSomething: "{name} a dit quelque chose"
|
||||||
|
makeActive: "Activer"
|
||||||
|
display: "Affichage"
|
||||||
|
copy: "Copier"
|
||||||
|
metrics: "Métriques"
|
||||||
|
overview: "Aperçu"
|
||||||
|
logs: "Journaux"
|
||||||
|
delayed: "en retard"
|
||||||
|
database: "Base de données"
|
||||||
|
channel: "Canaux"
|
||||||
|
create: "Créer"
|
||||||
|
notificationSetting: "Paramètres des notifications "
|
||||||
|
notificationSettingDesc: "Sélectionnez le type de notification à afficher"
|
||||||
|
useGlobalSetting: "Utiliser paramètre général"
|
||||||
|
other: "Autre"
|
||||||
|
regenerateLoginToken: "Régénérer le jeton de connexion"
|
||||||
|
setMultipleBySeparatingWithSpace: "Vous pouvez définir plus d’un, séparés par des espaces."
|
||||||
|
fileIdOrUrl: "ID du fichier ou URL"
|
||||||
|
chatOpenBehavior: "Comportement de la fenêtre de discussion lors de son ouverture"
|
||||||
|
random: "Aléatoire"
|
||||||
|
_reversi:
|
||||||
|
total: "Total"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "Rechargement automatique"
|
||||||
|
_channel:
|
||||||
|
create: "Créer un canal"
|
||||||
|
edit: "Éditer le canal"
|
||||||
|
removeBanner: "Supprimer la bannière"
|
||||||
|
featured: "Tendances"
|
||||||
|
usersCount: "{n} Participants"
|
||||||
|
notesCount: "{n} Notes"
|
||||||
|
_sidebar:
|
||||||
|
full: "Complet"
|
||||||
|
icon: "Avatar"
|
||||||
|
hide: "Masquer"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "Mot à mettre en sourdine"
|
||||||
|
muteWordsDescription: "Séparer avec des espaces pour la condition AND. Séparer avec un saut de ligne pour une condition OR."
|
||||||
|
mutedNotes: "Notes mises en sourdine"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Explorer les thèmes"
|
explore: "Explorer les thèmes"
|
||||||
install: "Installer un thème"
|
install: "Installer un thème"
|
||||||
@ -534,12 +611,16 @@ _theme:
|
|||||||
invalid: "Le format du thème n'est pas valide"
|
invalid: "Le format du thème n'est pas valide"
|
||||||
make: "Créer un thème"
|
make: "Créer un thème"
|
||||||
base: "Base"
|
base: "Base"
|
||||||
|
addConstant: "Ajouter une constante"
|
||||||
|
constant: "Constante"
|
||||||
defaultValue: "Valeur par défaut"
|
defaultValue: "Valeur par défaut"
|
||||||
color: "Couleur"
|
color: "Couleur"
|
||||||
|
key: "Clé "
|
||||||
func: "Fonction"
|
func: "Fonction"
|
||||||
argument: "Argument"
|
argument: "Argument"
|
||||||
alpha: "Transparence"
|
alpha: "Transparence"
|
||||||
darken: "Assombrir"
|
darken: "Assombrir"
|
||||||
|
importInfo: "Vous pouvez importer un thème vers l’éditeur de thèmes en saisissant son code ici."
|
||||||
keys:
|
keys:
|
||||||
bg: "Arrière-plan"
|
bg: "Arrière-plan"
|
||||||
fg: "Texte"
|
fg: "Texte"
|
||||||
@ -549,10 +630,16 @@ _theme:
|
|||||||
shadow: "Ombre"
|
shadow: "Ombre"
|
||||||
header: "Entête"
|
header: "Entête"
|
||||||
navBg: "Fond de la barre latérale"
|
navBg: "Fond de la barre latérale"
|
||||||
|
navFg: "Texte de la barre latérale"
|
||||||
|
link: "Lien"
|
||||||
hashtag: "Hashtags"
|
hashtag: "Hashtags"
|
||||||
mention: "Mentionner"
|
mention: "Mentionner"
|
||||||
|
mentionMe: "Mentions (Moi)"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
divider: "Séparateur"
|
divider: "Séparateur"
|
||||||
|
infoWarnFg: "Texte d’avertissement"
|
||||||
|
cwBg: "Arrière-plan du CW"
|
||||||
|
badge: "Badge"
|
||||||
messageBg: "Arrière plan de la discussion"
|
messageBg: "Arrière plan de la discussion"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Nouvelle note"
|
note: "Nouvelle note"
|
||||||
@ -636,6 +723,8 @@ _permissions:
|
|||||||
"write:page-likes": "Mettre à jour les favoris sur les Pages"
|
"write:page-likes": "Mettre à jour les favoris sur les Pages"
|
||||||
"read:user-groups": "Voir les groupes d'utilisateur·rice·s"
|
"read:user-groups": "Voir les groupes d'utilisateur·rice·s"
|
||||||
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
|
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
|
||||||
|
"read:channels": "Lire les canaux"
|
||||||
|
"write:channels": "Modifier les canaux"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "Autoriser \"{name}\" à accéder à votre compte ?"
|
shareAccess: "Autoriser \"{name}\" à accéder à votre compte ?"
|
||||||
shareAccessAsk: "Voulez-vous vraiment autoriser cette application à accéder à votre compte?"
|
shareAccessAsk: "Voulez-vous vraiment autoriser cette application à accéder à votre compte?"
|
||||||
@ -667,6 +756,9 @@ _widgets:
|
|||||||
rss: "Lecteur de flux RSS"
|
rss: "Lecteur de flux RSS"
|
||||||
activity: "Activité"
|
activity: "Activité"
|
||||||
photos: "Photos"
|
photos: "Photos"
|
||||||
|
digitalClock: "Horloge numérique"
|
||||||
|
federation: "Fédération"
|
||||||
|
postForm: "Formulaire à publier"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Masquer"
|
hide: "Masquer"
|
||||||
show: "Afficher plus …"
|
show: "Afficher plus …"
|
||||||
@ -708,6 +800,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Répondre à cette note ..."
|
replyPlaceholder: "Répondre à cette note ..."
|
||||||
quotePlaceholder: "Citez cette note ..."
|
quotePlaceholder: "Citez cette note ..."
|
||||||
|
channelPlaceholder: "Publier vers le canal"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "Quoi de neuf ?"
|
a: "Quoi de neuf ?"
|
||||||
b: "Quoi de neuf ?"
|
b: "Quoi de neuf ?"
|
||||||
@ -1120,9 +1213,23 @@ _notification:
|
|||||||
youReceivedFollowRequest: "Vous avez reçu une demande d’abonnement"
|
youReceivedFollowRequest: "Vous avez reçu une demande d’abonnement"
|
||||||
yourFollowRequestAccepted: "Votre demande d’abonnement a été accepté"
|
yourFollowRequestAccepted: "Votre demande d’abonnement a été accepté"
|
||||||
youWereInvitedToGroup: "Invité au groupe"
|
youWereInvitedToGroup: "Invité au groupe"
|
||||||
|
_types:
|
||||||
|
all: "Toutes"
|
||||||
|
follow: "Abonnements"
|
||||||
|
mention: "Mentionner"
|
||||||
|
reply: "Réponses"
|
||||||
|
renote: "Renote"
|
||||||
|
quote: "Citer"
|
||||||
|
reaction: "Réactions"
|
||||||
|
groupInvited: "Invité aux groupes"
|
||||||
|
app: "Notifications provenant des apps"
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "Toujours afficher la colonne principale"
|
alwaysShowMainColumn: "Toujours afficher la colonne principale"
|
||||||
columnAlign: "Aligner les colonnes"
|
columnAlign: "Aligner les colonnes"
|
||||||
|
addColumn: "Ajouter une colonne"
|
||||||
|
swapLeft: "Déplacer à gauche"
|
||||||
|
swapRight: "Déplacer à droite"
|
||||||
|
stackLeft: "Empiler à gauche"
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "Widgets"
|
widgets: "Widgets"
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "ノートはありません"
|
|||||||
noNotifications: "通知はありません"
|
noNotifications: "通知はありません"
|
||||||
instance: "インスタンス"
|
instance: "インスタンス"
|
||||||
settings: "設定"
|
settings: "設定"
|
||||||
|
basicSettings: "基本設定"
|
||||||
|
otherSettings: "その他の設定"
|
||||||
|
openInWindow: "ウィンドウで開く"
|
||||||
profile: "プロフィール"
|
profile: "プロフィール"
|
||||||
timeline: "タイムライン"
|
timeline: "タイムライン"
|
||||||
noAccountDescription: "自己紹介はありません"
|
noAccountDescription: "自己紹介はありません"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "このノートを削除してもう一度編集します
|
|||||||
addToList: "リストに追加"
|
addToList: "リストに追加"
|
||||||
sendMessage: "メッセージを送信"
|
sendMessage: "メッセージを送信"
|
||||||
copyUsername: "ユーザー名をコピー"
|
copyUsername: "ユーザー名をコピー"
|
||||||
|
searchUser: "ユーザーを検索"
|
||||||
reply: "返信"
|
reply: "返信"
|
||||||
loadMore: "もっと見る"
|
loadMore: "もっと見る"
|
||||||
youGotNewFollower: "フォローされました"
|
youGotNewFollower: "フォローされました"
|
||||||
@ -66,8 +70,11 @@ followers: "フォロワー"
|
|||||||
followsYou: "フォローされています"
|
followsYou: "フォローされています"
|
||||||
createList: "リスト作成"
|
createList: "リスト作成"
|
||||||
manageLists: "リストの管理"
|
manageLists: "リストの管理"
|
||||||
error: "問題が発生しました"
|
error: "エラー"
|
||||||
|
somethingHappened: "問題が発生しました"
|
||||||
retry: "再試行"
|
retry: "再試行"
|
||||||
|
pageLoadError: "ページの読み込みに失敗しました。"
|
||||||
|
pageLoadErrorDescription: "これは通常、ネットワークまたはブラウザキャッシュが原因です。キャッシュをクリアするか、しばらく待ってから再度試してください。"
|
||||||
enterListName: "リスト名を入力"
|
enterListName: "リスト名を入力"
|
||||||
privacy: "プライバシー"
|
privacy: "プライバシー"
|
||||||
makeFollowManuallyApprove: "フォローを承認制にする"
|
makeFollowManuallyApprove: "フォローを承認制にする"
|
||||||
@ -104,6 +111,10 @@ unblockConfirm: "ブロック解除しますか?"
|
|||||||
suspendConfirm: "凍結しますか?"
|
suspendConfirm: "凍結しますか?"
|
||||||
unsuspendConfirm: "解凍しますか?"
|
unsuspendConfirm: "解凍しますか?"
|
||||||
selectList: "リストを選択"
|
selectList: "リストを選択"
|
||||||
|
selectAntenna: "アンテナを選択"
|
||||||
|
selectWidget: "ウィジェットを選択"
|
||||||
|
editWidgets: "ウィジェットを編集"
|
||||||
|
editWidgetsExit: "編集を終了"
|
||||||
customEmojis: "カスタム絵文字"
|
customEmojis: "カスタム絵文字"
|
||||||
emoji: "絵文字"
|
emoji: "絵文字"
|
||||||
emojiName: "絵文字名"
|
emojiName: "絵文字名"
|
||||||
@ -175,7 +186,6 @@ processing: "処理中"
|
|||||||
preview: "プレビュー"
|
preview: "プレビュー"
|
||||||
default: "デフォルト"
|
default: "デフォルト"
|
||||||
noCustomEmojis: "絵文字はありません"
|
noCustomEmojis: "絵文字はありません"
|
||||||
customEmojisOfRemote: "リモートの絵文字"
|
|
||||||
noJobs: "ジョブはありません"
|
noJobs: "ジョブはありません"
|
||||||
federating: "連合中"
|
federating: "連合中"
|
||||||
blocked: "ブロック中"
|
blocked: "ブロック中"
|
||||||
@ -262,6 +272,7 @@ rename: "名前を変更"
|
|||||||
avatar: "アイコン"
|
avatar: "アイコン"
|
||||||
banner: "バナー"
|
banner: "バナー"
|
||||||
nsfw: "閲覧注意"
|
nsfw: "閲覧注意"
|
||||||
|
whenServerDisconnected: "サーバーとの接続が失われたとき"
|
||||||
disconnectedFromServer: "サーバーから切断されました"
|
disconnectedFromServer: "サーバーから切断されました"
|
||||||
reload: "リロード"
|
reload: "リロード"
|
||||||
doNothing: "なにもしない"
|
doNothing: "なにもしない"
|
||||||
@ -362,7 +373,6 @@ unregister: "登録を解除"
|
|||||||
passwordLessLogin: "パスワード無しログイン"
|
passwordLessLogin: "パスワード無しログイン"
|
||||||
resetPassword: "パスワードをリセット"
|
resetPassword: "パスワードをリセット"
|
||||||
newPasswordIs: "新しいパスワードは「{password}」です"
|
newPasswordIs: "新しいパスワードは「{password}」です"
|
||||||
autoReloadWhenDisconnected: "サーバー切断時に自動リロード"
|
|
||||||
autoNoteWatch: "ノートの自動ウォッチ"
|
autoNoteWatch: "ノートの自動ウォッチ"
|
||||||
autoNoteWatchDescription: "あなたがリアクションしたり返信したりした他のユーザーのノートに関する通知を受け取るようにします。"
|
autoNoteWatchDescription: "あなたがリアクションしたり返信したりした他のユーザーのノートに関する通知を受け取るようにします。"
|
||||||
reduceUiAnimation: "UIのアニメーションを減らす"
|
reduceUiAnimation: "UIのアニメーションを減らす"
|
||||||
@ -402,6 +412,7 @@ noMessagesYet: "まだチャットはありません"
|
|||||||
newMessageExists: "新しいメッセージがあります"
|
newMessageExists: "新しいメッセージがあります"
|
||||||
onlyOneFileCanBeAttached: "メッセージに添付できるファイルはひとつです"
|
onlyOneFileCanBeAttached: "メッセージに添付できるファイルはひとつです"
|
||||||
signinRequired: "ログインしてください"
|
signinRequired: "ログインしてください"
|
||||||
|
invitations: "招待"
|
||||||
invitationCode: "招待コード"
|
invitationCode: "招待コード"
|
||||||
checking: "確認しています"
|
checking: "確認しています"
|
||||||
available: "利用できます"
|
available: "利用できます"
|
||||||
@ -442,8 +453,8 @@ remote: "リモート"
|
|||||||
total: "合計"
|
total: "合計"
|
||||||
weekOverWeekChanges: "前週比"
|
weekOverWeekChanges: "前週比"
|
||||||
dayOverDayChanges: "前日比"
|
dayOverDayChanges: "前日比"
|
||||||
accessibility: "アクセシビリティ"
|
appearance: "アピアランス"
|
||||||
clinetSettings: "クライアント設定"
|
clientSettings: "クライアント設定"
|
||||||
accountSettings: "アカウント設定"
|
accountSettings: "アカウント設定"
|
||||||
promotion: "プロモーション"
|
promotion: "プロモーション"
|
||||||
promote: "プロモート"
|
promote: "プロモート"
|
||||||
@ -466,6 +477,7 @@ objectStorageUseSSL: "SSLを使用する"
|
|||||||
objectStorageUseSSLDesc: "API接続にhttpsを使用しない場合はオフにしてください"
|
objectStorageUseSSLDesc: "API接続にhttpsを使用しない場合はオフにしてください"
|
||||||
objectStorageUseProxy: "Proxyを利用する"
|
objectStorageUseProxy: "Proxyを利用する"
|
||||||
objectStorageUseProxyDesc: "API接続にproxyを利用しない場合はオフにしてください"
|
objectStorageUseProxyDesc: "API接続にproxyを利用しない場合はオフにしてください"
|
||||||
|
objectStorageSetPublicRead: "アップロード時に'public-read'を設定する"
|
||||||
serverLogs: "サーバーログ"
|
serverLogs: "サーバーログ"
|
||||||
deleteAll: "全て削除"
|
deleteAll: "全て削除"
|
||||||
showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
|
showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
|
||||||
@ -473,6 +485,8 @@ newNoteRecived: "新しいノートがあります"
|
|||||||
sounds: "サウンド"
|
sounds: "サウンド"
|
||||||
listen: "聴く"
|
listen: "聴く"
|
||||||
none: "なし"
|
none: "なし"
|
||||||
|
showInPage: "ページで表示"
|
||||||
|
popout: "ポップアウト"
|
||||||
volume: "音量"
|
volume: "音量"
|
||||||
details: "詳細"
|
details: "詳細"
|
||||||
chooseEmoji: "絵文字を選択"
|
chooseEmoji: "絵文字を選択"
|
||||||
@ -515,7 +529,6 @@ enableInfiniteScroll: "自動でもっと見る"
|
|||||||
visibility: "公開範囲"
|
visibility: "公開範囲"
|
||||||
poll: "アンケート"
|
poll: "アンケート"
|
||||||
useCw: "内容を隠す"
|
useCw: "内容を隠す"
|
||||||
fixedWidgetsPosition: "ウィジェットの位置を固定する"
|
|
||||||
enablePlayer: "プレイヤーを開く"
|
enablePlayer: "プレイヤーを開く"
|
||||||
disablePlayer: "プレイヤーを閉じる"
|
disablePlayer: "プレイヤーを閉じる"
|
||||||
expandTweet: "ツイートを展開する"
|
expandTweet: "ツイートを展開する"
|
||||||
@ -529,6 +542,135 @@ pluginInstallWarn: "信頼できないプラグインはインストールしな
|
|||||||
deck: "デッキ"
|
deck: "デッキ"
|
||||||
undeck: "デッキ解除"
|
undeck: "デッキ解除"
|
||||||
useBlurEffectForModal: "モーダルにぼかし効果を使用"
|
useBlurEffectForModal: "モーダルにぼかし効果を使用"
|
||||||
|
generateAccessToken: "アクセストークンの発行"
|
||||||
|
permission: "権限"
|
||||||
|
enableAll: "全て有効にする"
|
||||||
|
disableAll: "全て無効にする"
|
||||||
|
tokenRequested: "アカウントへのアクセス許可"
|
||||||
|
pluginTokenRequestedDescription: "このプラグインはここで設定した権限を行使できるようになります。"
|
||||||
|
notificationType: "通知の種類"
|
||||||
|
edit: "編集"
|
||||||
|
useStarForReactionFallback: "リアクション絵文字が不明な場合、代わりに★を使う"
|
||||||
|
emailConfig: "メールサーバー設定"
|
||||||
|
enableEmail: "メール配信機能を有効化する"
|
||||||
|
emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います"
|
||||||
|
email: "メールアドレス"
|
||||||
|
smtpConfig: "SMTP サーバーの設定"
|
||||||
|
smtpHost: "ホスト"
|
||||||
|
smtpPort: "ポート"
|
||||||
|
smtpUser: "ユーザー名"
|
||||||
|
smtpPass: "パスワード"
|
||||||
|
emptyToDisableSmtpAuth: "ユーザー名とパスワードを空欄にすることで、SMTP認証を無効化出来ます"
|
||||||
|
smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
|
||||||
|
smtpSecureInfo: "STARTTLS使用時はオフにします。"
|
||||||
|
testEmail: "配信テスト"
|
||||||
|
wordMute: "ワードミュート"
|
||||||
|
userSaysSomething: "{name}が何かを言いました"
|
||||||
|
makeActive: "アクティブにする"
|
||||||
|
display: "表示"
|
||||||
|
copy: "コピー"
|
||||||
|
metrics: "メトリクス"
|
||||||
|
overview: "概要"
|
||||||
|
logs: "ログ"
|
||||||
|
delayed: "遅延"
|
||||||
|
database: "データベース"
|
||||||
|
channel: "チャンネル"
|
||||||
|
create: "作成"
|
||||||
|
notificationSetting: "通知設定"
|
||||||
|
notificationSettingDesc: "表示する通知の種別を選択してください。"
|
||||||
|
useGlobalSetting: "グローバル設定を使う"
|
||||||
|
useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使用されます。オフにすると、個別に設定できるようになります。"
|
||||||
|
other: "その他"
|
||||||
|
regenerateLoginToken: "ログイントークンを再生成"
|
||||||
|
regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。"
|
||||||
|
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
|
||||||
|
fileIdOrUrl: "ファイルIDまたはURL"
|
||||||
|
chatOpenBehavior: "チャットを開くときの動作"
|
||||||
|
sample: "サンプル"
|
||||||
|
abuseReports: "通報"
|
||||||
|
reportAbuse: "通報"
|
||||||
|
reportAbuseOf: "{name}を通報する"
|
||||||
|
fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。"
|
||||||
|
abuseReported: "内容が送信されました。ご報告ありがとうございました。"
|
||||||
|
send: "送信"
|
||||||
|
abuseMarkAsResolved: "対応済みにする"
|
||||||
|
openInNewTab: "新しいタブで開く"
|
||||||
|
openInSideView: "サイドビューで開く"
|
||||||
|
defaultNavigationBehaviour: "デフォルトのナビゲーション"
|
||||||
|
editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
|
||||||
|
instanceTicker: "ノートのインスタンス情報"
|
||||||
|
waitingFor: "{x}を待っています"
|
||||||
|
random: "ランダム"
|
||||||
|
|
||||||
|
_reversi:
|
||||||
|
reversi: "リバーシ"
|
||||||
|
gameSettings: "対局の設定"
|
||||||
|
chooseBoard: "ボードを選択"
|
||||||
|
blackOrWhite: "先行/後攻"
|
||||||
|
blackIs: "{name}が黒(先行)"
|
||||||
|
rules: "ルール"
|
||||||
|
botSettings: "Botのオプション"
|
||||||
|
thisGameIsStartedSoon: "対局は数秒後に開始されます"
|
||||||
|
waitingForOther: "相手の準備が完了するのを待っています"
|
||||||
|
waitingForMe: "あなたの準備が完了するのを待っています"
|
||||||
|
waitingBoth: "準備してください"
|
||||||
|
ready: "準備完了"
|
||||||
|
cancelReady: "準備を再開"
|
||||||
|
opponentTurn: "相手のターンです"
|
||||||
|
myTurn: "あなたのターンです"
|
||||||
|
turnOf: "{name}のターンです"
|
||||||
|
pastTurnOf: "{name}のターン"
|
||||||
|
surrender: "投了"
|
||||||
|
surrendered: "投了により"
|
||||||
|
drawn: "引き分け"
|
||||||
|
won: "{name}の勝ち"
|
||||||
|
black: "黒"
|
||||||
|
white: "白"
|
||||||
|
total: "合計"
|
||||||
|
turnCount: "{count}ターン目"
|
||||||
|
myGames: "自分の対局"
|
||||||
|
allGames: "みんなの対局"
|
||||||
|
ended: "終了"
|
||||||
|
playing: "対局中"
|
||||||
|
isLlotheo: "石の少ない方が勝ち(ロセオ)"
|
||||||
|
loopedMap: "ループマップ"
|
||||||
|
canPutEverywhere: "どこでも置けるモード"
|
||||||
|
|
||||||
|
_instanceTicker:
|
||||||
|
none: "表示しない"
|
||||||
|
remote: "リモートユーザーに表示"
|
||||||
|
always: "常に表示"
|
||||||
|
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "自動でリロード"
|
||||||
|
dialog: "ダイアログで警告"
|
||||||
|
quiet: "控えめに警告"
|
||||||
|
|
||||||
|
_channel:
|
||||||
|
create: "チャンネルを作成"
|
||||||
|
edit: "チャンネルを編集"
|
||||||
|
setBanner: "バナーを設定"
|
||||||
|
removeBanner: "バナーを削除"
|
||||||
|
featured: "トレンド"
|
||||||
|
owned: "管理中"
|
||||||
|
following: "フォロー中"
|
||||||
|
usersCount: "{n}人が参加中"
|
||||||
|
notesCount: "{n}投稿があります"
|
||||||
|
|
||||||
|
_sidebar:
|
||||||
|
full: "フル"
|
||||||
|
icon: "アイコン"
|
||||||
|
hide: "隠す"
|
||||||
|
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "ミュートするワード"
|
||||||
|
muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。"
|
||||||
|
muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。"
|
||||||
|
softDescription: "指定した条件のノートをタイムラインから隠します。"
|
||||||
|
hardDescription: "指定した条件のノートをタイムラインに追加しないようにします。追加されなかったノートは、条件を変更しても除外されたままになります。"
|
||||||
|
soft: "ソフト"
|
||||||
|
hard: "ハード"
|
||||||
|
mutedNotes: "ミュートされたノート"
|
||||||
|
|
||||||
_theme:
|
_theme:
|
||||||
explore: "テーマを探す"
|
explore: "テーマを探す"
|
||||||
@ -610,6 +752,7 @@ _sfx:
|
|||||||
chat: "チャット"
|
chat: "チャット"
|
||||||
chatBg: "チャット(バックグラウンド)"
|
chatBg: "チャット(バックグラウンド)"
|
||||||
antenna: "アンテナ受信"
|
antenna: "アンテナ受信"
|
||||||
|
channel: "チャンネル通知"
|
||||||
|
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "謎"
|
unknown: "謎"
|
||||||
@ -690,6 +833,8 @@ _permissions:
|
|||||||
"write:page-likes": "ページのいいねを操作する"
|
"write:page-likes": "ページのいいねを操作する"
|
||||||
"read:user-groups": "ユーザーグループを見る"
|
"read:user-groups": "ユーザーグループを見る"
|
||||||
"write:user-groups": "ユーザーグループを操作する"
|
"write:user-groups": "ユーザーグループを操作する"
|
||||||
|
"read:channels": "チャンネルを見る"
|
||||||
|
"write:channels": "チャンネルを操作する"
|
||||||
|
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
||||||
@ -726,6 +871,8 @@ _widgets:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
photos: "フォト"
|
photos: "フォト"
|
||||||
digitalClock: "デジタル時計"
|
digitalClock: "デジタル時計"
|
||||||
|
federation: "連合"
|
||||||
|
postForm: "投稿フォーム"
|
||||||
|
|
||||||
_cw:
|
_cw:
|
||||||
hide: "隠す"
|
hide: "隠す"
|
||||||
@ -771,6 +918,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "このノートに返信..."
|
replyPlaceholder: "このノートに返信..."
|
||||||
quotePlaceholder: "このノートを引用..."
|
quotePlaceholder: "このノートを引用..."
|
||||||
|
channelPlaceholder: "チャンネルに投稿..."
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "いまどうしてる?"
|
a: "いまどうしてる?"
|
||||||
b: "何かありましたか?"
|
b: "何かありましたか?"
|
||||||
@ -1204,10 +1352,30 @@ _notification:
|
|||||||
yourFollowRequestAccepted: "フォローリクエストが承認されました"
|
yourFollowRequestAccepted: "フォローリクエストが承認されました"
|
||||||
youWereInvitedToGroup: "グループに招待されました"
|
youWereInvitedToGroup: "グループに招待されました"
|
||||||
|
|
||||||
|
_types:
|
||||||
|
all: "すべて"
|
||||||
|
follow: "フォロー"
|
||||||
|
mention: "メンション"
|
||||||
|
reply: "リプライ"
|
||||||
|
renote: "Renote"
|
||||||
|
quote: "引用"
|
||||||
|
reaction: "リアクション"
|
||||||
|
pollVote: "アンケートに投票された"
|
||||||
|
receiveFollowRequest: "フォロー申請を受け取った"
|
||||||
|
followRequestAccepted: "フォローが受理された"
|
||||||
|
groupInvited: "グループに招待された"
|
||||||
|
app: "連携アプリからの通知"
|
||||||
|
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "常にメインカラムを表示"
|
alwaysShowMainColumn: "常にメインカラムを表示"
|
||||||
columnAlign: "カラムの寄せ"
|
columnAlign: "カラムの寄せ"
|
||||||
addColumn: "カラムを追加"
|
addColumn: "カラムを追加"
|
||||||
|
swapLeft: "左に移動"
|
||||||
|
swapRight: "右に移動"
|
||||||
|
swapUp: "上に移動"
|
||||||
|
swapDown: "下に移動"
|
||||||
|
stackLeft: "左に重ねる"
|
||||||
|
popRight: "右に出す"
|
||||||
|
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "ウィジェット"
|
widgets: "ウィジェット"
|
||||||
|
@ -65,7 +65,6 @@ followers: "フォロワー"
|
|||||||
followsYou: "フォローされとるで"
|
followsYou: "フォローされとるで"
|
||||||
createList: "リスト作る"
|
createList: "リスト作る"
|
||||||
manageLists: "リストの管理"
|
manageLists: "リストの管理"
|
||||||
error: "問題が発生してん"
|
|
||||||
retry: "もっぺんやってみる"
|
retry: "もっぺんやってみる"
|
||||||
enterListName: "リスト名を入れてや"
|
enterListName: "リスト名を入れてや"
|
||||||
privacy: "プライバシーってなんや?オカンの年齢か?"
|
privacy: "プライバシーってなんや?オカンの年齢か?"
|
||||||
@ -173,7 +172,6 @@ processing: "処理しとる"
|
|||||||
preview: "プレビュー"
|
preview: "プレビュー"
|
||||||
default: "デフォルト"
|
default: "デフォルト"
|
||||||
noCustomEmojis: "絵文字はあらへん"
|
noCustomEmojis: "絵文字はあらへん"
|
||||||
customEmojisOfRemote: "リモートの絵文字"
|
|
||||||
noJobs: "ジョブはあらへん"
|
noJobs: "ジョブはあらへん"
|
||||||
federating: "連合しとる"
|
federating: "連合しとる"
|
||||||
blocked: "ブロックしとる"
|
blocked: "ブロックしとる"
|
||||||
@ -295,6 +293,7 @@ proxyRemoteFilesDescription: "この設定を入れると、保存しとらん
|
|||||||
driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量"
|
driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量"
|
||||||
driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量"
|
driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量"
|
||||||
inMb: "メガバイト単位"
|
inMb: "メガバイト単位"
|
||||||
|
recaptcha: "reCAPTCHA"
|
||||||
avoidMultiCaptchaConfirm: "ぎょうさんのCaptchaをつこてしまうと、仲良うせんことがあるんや。他のCaptchaをなおしとこか?別にキャンセルしてもろうたらCaptchaは消されへんで済むけど知らんで。"
|
avoidMultiCaptchaConfirm: "ぎょうさんのCaptchaをつこてしまうと、仲良うせんことがあるんや。他のCaptchaをなおしとこか?別にキャンセルしてもろうたらCaptchaは消されへんで済むけど知らんで。"
|
||||||
antennas: "アンテナ"
|
antennas: "アンテナ"
|
||||||
manageAntennas: "アンテナいじる"
|
manageAntennas: "アンテナいじる"
|
||||||
@ -347,11 +346,16 @@ unregister: "登録やめる"
|
|||||||
passwordLessLogin: "パスワード無くてもログインできるようにする"
|
passwordLessLogin: "パスワード無くてもログインできるようにする"
|
||||||
resetPassword: "パスワードをリセット"
|
resetPassword: "パスワードをリセット"
|
||||||
newPasswordIs: "今度のパスワードは「{password}」や"
|
newPasswordIs: "今度のパスワードは「{password}」や"
|
||||||
autoReloadWhenDisconnected: "サーバーが調子悪いときには自動でリロードしたる"
|
|
||||||
notFoundDescription: "指定されたURLに該当するページはあらへんやった。"
|
notFoundDescription: "指定されたURLに該当するページはあらへんやった。"
|
||||||
close: "さいなら"
|
close: "さいなら"
|
||||||
joinedGroups: "参加しとるグループ"
|
joinedGroups: "参加しとるグループ"
|
||||||
invites: "来てや"
|
invites: "来てや"
|
||||||
|
invitations: "来てや"
|
||||||
|
smtpHost: "ホスト"
|
||||||
|
smtpUser: "ユーザー名"
|
||||||
|
smtpPass: "パスワード"
|
||||||
|
_sidebar:
|
||||||
|
icon: "アイコン"
|
||||||
_theme:
|
_theme:
|
||||||
keys:
|
keys:
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
@ -386,6 +390,7 @@ _widgets:
|
|||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
timeline: "タイムライン"
|
timeline: "タイムライン"
|
||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
|
federation: "連合"
|
||||||
_cw:
|
_cw:
|
||||||
show: "もっとあるやろ!"
|
show: "もっとあるやろ!"
|
||||||
_poll:
|
_poll:
|
||||||
@ -434,6 +439,11 @@ _pages:
|
|||||||
array: "リスト"
|
array: "リスト"
|
||||||
_notification:
|
_notification:
|
||||||
youWereFollowed: "フォローされたで"
|
youWereFollowed: "フォローされたで"
|
||||||
|
_types:
|
||||||
|
follow: "フォロー"
|
||||||
|
renote: "Renote"
|
||||||
|
quote: "引用"
|
||||||
|
reaction: "リアクション"
|
||||||
_deck:
|
_deck:
|
||||||
_columns:
|
_columns:
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
|
@ -33,6 +33,8 @@ youHaveNoLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
|
|||||||
remove: "Kkes"
|
remove: "Kkes"
|
||||||
userList: "Tibdarin"
|
userList: "Tibdarin"
|
||||||
uiLanguage: "Tutlayt n wegrudem"
|
uiLanguage: "Tutlayt n wegrudem"
|
||||||
|
smtpUser: "Isem n umseqdac"
|
||||||
|
smtpPass: "Awal uffir"
|
||||||
_theme:
|
_theme:
|
||||||
keys:
|
keys:
|
||||||
mention: "Bder"
|
mention: "Bder"
|
||||||
@ -80,6 +82,9 @@ _pages:
|
|||||||
array: "Tibdarin"
|
array: "Tibdarin"
|
||||||
_notification:
|
_notification:
|
||||||
youWereFollowed: "Yeṭṭafaṛ-ik·em-id"
|
youWereFollowed: "Yeṭṭafaṛ-ik·em-id"
|
||||||
|
_types:
|
||||||
|
follow: "Ig ṭṭafaṛ"
|
||||||
|
mention: "Bder"
|
||||||
_deck:
|
_deck:
|
||||||
_columns:
|
_columns:
|
||||||
notifications: "Ilɣuyen"
|
notifications: "Ilɣuyen"
|
||||||
|
@ -54,6 +54,8 @@ driveFileDeleteConfirm: "\"{name}\" ಕಡತವನ್ನು ಅಳಿಸಲು
|
|||||||
unfollowConfirm: "{name}ಅನ್ನು ಹಿಂಬಾಲಿಸದಿರುವುದೇ?"
|
unfollowConfirm: "{name}ಅನ್ನು ಹಿಂಬಾಲಿಸದಿರುವುದೇ?"
|
||||||
instances: "ನಿದರ್ಶನ"
|
instances: "ನಿದರ್ಶನ"
|
||||||
remove: "ಅಳಿಸು"
|
remove: "ಅಳಿಸು"
|
||||||
|
smtpUser: "ಬಳಕೆಹೆಸರು"
|
||||||
|
smtpPass: "ಗುಪ್ತಪದ"
|
||||||
_sfx:
|
_sfx:
|
||||||
notification: "ಅಧಿಸೂಚನೆಗಳು"
|
notification: "ಅಧಿಸೂಚನೆಗಳು"
|
||||||
_widgets:
|
_widgets:
|
||||||
|
@ -66,7 +66,6 @@ followers: "팔로워"
|
|||||||
followsYou: "당신을 팔로우합니다"
|
followsYou: "당신을 팔로우합니다"
|
||||||
createList: "리스트 만들기"
|
createList: "리스트 만들기"
|
||||||
manageLists: "리스트 관리"
|
manageLists: "리스트 관리"
|
||||||
error: "오류가 발생했습니다"
|
|
||||||
retry: "다시 시도"
|
retry: "다시 시도"
|
||||||
enterListName: "리스트 이름을 입력"
|
enterListName: "리스트 이름을 입력"
|
||||||
privacy: "프라이버시"
|
privacy: "프라이버시"
|
||||||
@ -104,6 +103,8 @@ unblockConfirm: "이 계정의 차단을 해제하시겠습니까?"
|
|||||||
suspendConfirm: "이 계정을 정지하시겠습니까?"
|
suspendConfirm: "이 계정을 정지하시겠습니까?"
|
||||||
unsuspendConfirm: "이 계정의 정지를 해제하시겠습니까?"
|
unsuspendConfirm: "이 계정의 정지를 해제하시겠습니까?"
|
||||||
selectList: "리스트 선택"
|
selectList: "리스트 선택"
|
||||||
|
selectAntenna: "안테나 선택"
|
||||||
|
selectWidget: "위젯 선택"
|
||||||
customEmojis: "커스텀 이모지"
|
customEmojis: "커스텀 이모지"
|
||||||
emoji: "이모지"
|
emoji: "이모지"
|
||||||
emojiName: "이모지 이름"
|
emojiName: "이모지 이름"
|
||||||
@ -175,7 +176,6 @@ processing: "처리중"
|
|||||||
preview: "미리보기"
|
preview: "미리보기"
|
||||||
default: "기본값"
|
default: "기본값"
|
||||||
noCustomEmojis: "이모지가 없습니다"
|
noCustomEmojis: "이모지가 없습니다"
|
||||||
customEmojisOfRemote: "다른 인스턴스들의 이모지"
|
|
||||||
noJobs: "작업이 없습니다"
|
noJobs: "작업이 없습니다"
|
||||||
federating: "연합 중"
|
federating: "연합 중"
|
||||||
blocked: "차단됨"
|
blocked: "차단됨"
|
||||||
@ -362,7 +362,6 @@ unregister: "등록 해제"
|
|||||||
passwordLessLogin: "비밀번호 없이 로그인"
|
passwordLessLogin: "비밀번호 없이 로그인"
|
||||||
resetPassword: "비밀번호 재설정"
|
resetPassword: "비밀번호 재설정"
|
||||||
newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다"
|
newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다"
|
||||||
autoReloadWhenDisconnected: "서버와의 연결이 끊기면 자동 새로고침"
|
|
||||||
autoNoteWatch: "노트를 자동으로 지켜보기"
|
autoNoteWatch: "노트를 자동으로 지켜보기"
|
||||||
autoNoteWatchDescription: "리액션하거나 답글을 남긴 다른 유저의 노트에 대한 알림을 받습니다."
|
autoNoteWatchDescription: "리액션하거나 답글을 남긴 다른 유저의 노트에 대한 알림을 받습니다."
|
||||||
reduceUiAnimation: "UI의 애니메이션을 줄이기"
|
reduceUiAnimation: "UI의 애니메이션을 줄이기"
|
||||||
@ -402,6 +401,7 @@ noMessagesYet: "아직 대화가 없습니다"
|
|||||||
newMessageExists: "새 메시지가 있습니다"
|
newMessageExists: "새 메시지가 있습니다"
|
||||||
onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다"
|
onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다"
|
||||||
signinRequired: "로그인 해주세요"
|
signinRequired: "로그인 해주세요"
|
||||||
|
invitations: "초대"
|
||||||
invitationCode: "초대 코드"
|
invitationCode: "초대 코드"
|
||||||
checking: "확인하는 중입니다"
|
checking: "확인하는 중입니다"
|
||||||
available: "사용 가능합니다"
|
available: "사용 가능합니다"
|
||||||
@ -432,7 +432,7 @@ tags: "태그"
|
|||||||
docSource: "이 문서의 소스"
|
docSource: "이 문서의 소스"
|
||||||
createAccount: "계정 만들기"
|
createAccount: "계정 만들기"
|
||||||
existingAcount: "기존 계정"
|
existingAcount: "기존 계정"
|
||||||
regenerate: "다시 생성"
|
regenerate: "재생성"
|
||||||
fontSize: "글자 크기"
|
fontSize: "글자 크기"
|
||||||
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
|
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
|
||||||
openImageInNewTab: "새 탭에서 이미지 열기"
|
openImageInNewTab: "새 탭에서 이미지 열기"
|
||||||
@ -442,8 +442,6 @@ remote: "리모트"
|
|||||||
total: "합계"
|
total: "합계"
|
||||||
weekOverWeekChanges: "지난주보다"
|
weekOverWeekChanges: "지난주보다"
|
||||||
dayOverDayChanges: "어제보다"
|
dayOverDayChanges: "어제보다"
|
||||||
accessibility: "접근성"
|
|
||||||
clinetSettings: "클라이언트 설정"
|
|
||||||
accountSettings: "계정 설정"
|
accountSettings: "계정 설정"
|
||||||
promotion: "프로모션"
|
promotion: "프로모션"
|
||||||
promote: "프로모션하기"
|
promote: "프로모션하기"
|
||||||
@ -515,7 +513,6 @@ enableInfiniteScroll: "자동으로 좀 더 보기"
|
|||||||
visibility: "공개 범위"
|
visibility: "공개 범위"
|
||||||
poll: "투표"
|
poll: "투표"
|
||||||
useCw: "내용 숨기기"
|
useCw: "내용 숨기기"
|
||||||
fixedWidgetsPosition: "위젯의 위치 고정"
|
|
||||||
enablePlayer: "플레이어 열기"
|
enablePlayer: "플레이어 열기"
|
||||||
disablePlayer: "플레이어 닫기"
|
disablePlayer: "플레이어 닫기"
|
||||||
expandTweet: "트윗 확장하기"
|
expandTweet: "트윗 확장하기"
|
||||||
@ -528,6 +525,47 @@ plugins: "플러그인"
|
|||||||
pluginInstallWarn: "신뢰할 수 없는 플러그인은 설치하지 마십시오."
|
pluginInstallWarn: "신뢰할 수 없는 플러그인은 설치하지 마십시오."
|
||||||
deck: "덱"
|
deck: "덱"
|
||||||
undeck: "덱 해제"
|
undeck: "덱 해제"
|
||||||
|
generateAccessToken: "액세스 토큰 생성"
|
||||||
|
permission: "권한"
|
||||||
|
enableAll: "전체 선택"
|
||||||
|
disableAll: "전체 해제"
|
||||||
|
tokenRequested: "계정 접근 허용"
|
||||||
|
edit: "편집"
|
||||||
|
useStarForReactionFallback: "알 수 없는 리액션 이모지 대신 ★ 사용"
|
||||||
|
emailConfig: "메일 서버 설정"
|
||||||
|
emailConfigInfo: "가입 시 메일 주소 확인이나 비밀번호 초기화 시에 사용합니다."
|
||||||
|
email: "메일 주소"
|
||||||
|
smtpConfig: "SMTP 서버 설정"
|
||||||
|
smtpHost: "호스트"
|
||||||
|
smtpPort: "포트"
|
||||||
|
smtpUser: "유저명"
|
||||||
|
smtpPass: "비밀번호"
|
||||||
|
emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다."
|
||||||
|
smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용"
|
||||||
|
smtpSecureInfo: "STARTTLS 사용 시에는 해제합니다."
|
||||||
|
wordMute: "단어 뮤트"
|
||||||
|
makeActive: "활성화"
|
||||||
|
copy: "복사"
|
||||||
|
logs: "로그"
|
||||||
|
database: "데이터베이스"
|
||||||
|
channel: "채널"
|
||||||
|
random: "랜덤"
|
||||||
|
_reversi:
|
||||||
|
total: "합계"
|
||||||
|
_channel:
|
||||||
|
create: "채널 생성"
|
||||||
|
setBanner: "배너 설정"
|
||||||
|
removeBanner: "배너 삭제"
|
||||||
|
featured: "트렌드"
|
||||||
|
following: "팔로잉"
|
||||||
|
usersCount: "{n}명 참여 중"
|
||||||
|
notesCount: "{n}노트"
|
||||||
|
_sidebar:
|
||||||
|
icon: "아바타"
|
||||||
|
hide: "숨기기"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "뮤트할 단어"
|
||||||
|
mutedNotes: "뮤트된 노트"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "테마 찾아보기"
|
explore: "테마 찾아보기"
|
||||||
install: "테마 설치"
|
install: "테마 설치"
|
||||||
@ -548,7 +586,10 @@ _theme:
|
|||||||
func: "함수"
|
func: "함수"
|
||||||
funcKind: "함수 종류"
|
funcKind: "함수 종류"
|
||||||
argument: "매개변수"
|
argument: "매개변수"
|
||||||
|
importInfo: "여기에 테마 코드를 붙여 넣어 에디터로 불러올 수 있습니다."
|
||||||
keys:
|
keys:
|
||||||
|
link: "링크"
|
||||||
|
hashtag: "해시태그"
|
||||||
mention: "멘션"
|
mention: "멘션"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
divider: "구분선"
|
divider: "구분선"
|
||||||
@ -665,6 +706,9 @@ _widgets:
|
|||||||
rss: "RSS 리더"
|
rss: "RSS 리더"
|
||||||
activity: "활동"
|
activity: "활동"
|
||||||
photos: "사진"
|
photos: "사진"
|
||||||
|
digitalClock: "디지털 시계"
|
||||||
|
federation: "연합"
|
||||||
|
postForm: "글 입력란"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "숨기기"
|
hide: "숨기기"
|
||||||
show: "더 보기"
|
show: "더 보기"
|
||||||
@ -1116,8 +1160,24 @@ _notification:
|
|||||||
youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다"
|
youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다"
|
||||||
yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다"
|
yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다"
|
||||||
youWereInvitedToGroup: "그룹에 초대되었습니다"
|
youWereInvitedToGroup: "그룹에 초대되었습니다"
|
||||||
|
_types:
|
||||||
|
follow: "팔로잉"
|
||||||
|
mention: "멘션"
|
||||||
|
renote: "Renote"
|
||||||
|
quote: "인용"
|
||||||
|
reaction: "리액션"
|
||||||
_deck:
|
_deck:
|
||||||
|
alwaysShowMainColumn: "메인 칼럼 항상 표시"
|
||||||
|
columnAlign: "칼럼 정렬"
|
||||||
|
addColumn: "칼럼 추가"
|
||||||
|
swapLeft: "왼쪽으로 이동"
|
||||||
|
swapRight: "오른쪽으로 이동"
|
||||||
|
swapUp: "위로 이동"
|
||||||
|
swapDown: "아래로 이동"
|
||||||
|
stackLeft: "왼쪽에 쌓기"
|
||||||
|
popRight: "오른쪽으로 빼기"
|
||||||
_columns:
|
_columns:
|
||||||
|
widgets: "위젯"
|
||||||
notifications: "알림"
|
notifications: "알림"
|
||||||
tl: "타임라인"
|
tl: "타임라인"
|
||||||
antenna: "안테나"
|
antenna: "안테나"
|
||||||
|
@ -1,2 +1,21 @@
|
|||||||
---
|
---
|
||||||
_lang_: "język polski"
|
_lang_: "język polski"
|
||||||
|
search: "Szukaj"
|
||||||
|
notifications: "Powiadomienia"
|
||||||
|
username: "Nazwa użytkownika"
|
||||||
|
password: "Hasło"
|
||||||
|
ok: "OK"
|
||||||
|
gotIt: "Rozumiem!"
|
||||||
|
cancel: "Anuluj"
|
||||||
|
enterUsername: "Wprowadź nazwę użytkownika"
|
||||||
|
smtpUser: "Nazwa użytkownika"
|
||||||
|
smtpPass: "Hasło"
|
||||||
|
_sfx:
|
||||||
|
notification: "Powiadomienia"
|
||||||
|
_widgets:
|
||||||
|
notifications: "Powiadomienia"
|
||||||
|
_profile:
|
||||||
|
username: "Nazwa użytkownika"
|
||||||
|
_deck:
|
||||||
|
_columns:
|
||||||
|
notifications: "Powiadomienia"
|
||||||
|
1283
locales/ru-RU.yml
1283
locales/ru-RU.yml
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,9 @@ noNotes: "没有帖文"
|
|||||||
noNotifications: "无通知"
|
noNotifications: "无通知"
|
||||||
instance: "实例"
|
instance: "实例"
|
||||||
settings: "设置"
|
settings: "设置"
|
||||||
|
basicSettings: "基本设置"
|
||||||
|
otherSettings: "其他设置"
|
||||||
|
openInWindow: "在新窗口中打开"
|
||||||
profile: "个人资料"
|
profile: "个人资料"
|
||||||
timeline: "时间线"
|
timeline: "时间线"
|
||||||
noAccountDescription: "这个人很懒,没有写自我介绍"
|
noAccountDescription: "这个人很懒,没有写自我介绍"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "要删除此帖并再次编辑吗?对此帖的所有回
|
|||||||
addToList: "添加至列表"
|
addToList: "添加至列表"
|
||||||
sendMessage: "发送"
|
sendMessage: "发送"
|
||||||
copyUsername: "复制用户名"
|
copyUsername: "复制用户名"
|
||||||
|
searchUser: "搜索用户"
|
||||||
reply: "回复"
|
reply: "回复"
|
||||||
loadMore: "查看更多"
|
loadMore: "查看更多"
|
||||||
youGotNewFollower: "你有新的关注者"
|
youGotNewFollower: "你有新的关注者"
|
||||||
@ -66,8 +70,11 @@ followers: "关注者"
|
|||||||
followsYou: "关注了你"
|
followsYou: "关注了你"
|
||||||
createList: "创建列表"
|
createList: "创建列表"
|
||||||
manageLists: "管理列表"
|
manageLists: "管理列表"
|
||||||
error: "有点小问题"
|
error: "错误"
|
||||||
|
somethingHappened: "出现了问题"
|
||||||
retry: "重试"
|
retry: "重试"
|
||||||
|
pageLoadError: "页面加载失败。"
|
||||||
|
pageLoadErrorDescription: "这通常是由于网络或浏览器缓存的原因。请清除缓存或等待片刻后重试。"
|
||||||
enterListName: "输入列表名称"
|
enterListName: "输入列表名称"
|
||||||
privacy: "隐私"
|
privacy: "隐私"
|
||||||
makeFollowManuallyApprove: "关注者请求需要批准"
|
makeFollowManuallyApprove: "关注者请求需要批准"
|
||||||
@ -86,8 +93,8 @@ you: "您"
|
|||||||
clickToShow: "点击以显示"
|
clickToShow: "点击以显示"
|
||||||
sensitive: "阅读注意"
|
sensitive: "阅读注意"
|
||||||
add: "添加"
|
add: "添加"
|
||||||
reaction: "反应"
|
reaction: "回应"
|
||||||
reactionSettingDescription: "选择您想要固定在反应选择器中的反应。"
|
reactionSettingDescription: "选择您想要置顶的回应。"
|
||||||
rememberNoteVisibility: "记录公开范围"
|
rememberNoteVisibility: "记录公开范围"
|
||||||
attachCancel: "删除附件"
|
attachCancel: "删除附件"
|
||||||
markAsSensitive: "阅读注意"
|
markAsSensitive: "阅读注意"
|
||||||
@ -104,6 +111,10 @@ unblockConfirm: "确定要解除屏蔽吗?"
|
|||||||
suspendConfirm: "要冻结吗?"
|
suspendConfirm: "要冻结吗?"
|
||||||
unsuspendConfirm: "要解除冻结吗?"
|
unsuspendConfirm: "要解除冻结吗?"
|
||||||
selectList: "选择列表"
|
selectList: "选择列表"
|
||||||
|
selectAntenna: "天线选择"
|
||||||
|
selectWidget: "选择小工具"
|
||||||
|
editWidgets: "编辑小工具"
|
||||||
|
editWidgetsExit: "完成编辑"
|
||||||
customEmojis: "自定义Emoji"
|
customEmojis: "自定义Emoji"
|
||||||
emoji: "表情符号"
|
emoji: "表情符号"
|
||||||
emojiName: "Emoji 名称"
|
emojiName: "Emoji 名称"
|
||||||
@ -175,7 +186,6 @@ processing: "处理中"
|
|||||||
preview: "预览"
|
preview: "预览"
|
||||||
default: "默认"
|
default: "默认"
|
||||||
noCustomEmojis: "无自定义Emoji"
|
noCustomEmojis: "无自定义Emoji"
|
||||||
customEmojisOfRemote: "远程Emoji"
|
|
||||||
noJobs: "没有任务"
|
noJobs: "没有任务"
|
||||||
federating: "联合中"
|
federating: "联合中"
|
||||||
blocked: "已拦截"
|
blocked: "已拦截"
|
||||||
@ -262,6 +272,7 @@ rename: "重命名"
|
|||||||
avatar: "头像"
|
avatar: "头像"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
nsfw: "阅读注意"
|
nsfw: "阅读注意"
|
||||||
|
whenServerDisconnected: "与服务器连接中断时"
|
||||||
disconnectedFromServer: "已从服务器断开连接"
|
disconnectedFromServer: "已从服务器断开连接"
|
||||||
reload: "重新加载"
|
reload: "重新加载"
|
||||||
doNothing: "什么都不做"
|
doNothing: "什么都不做"
|
||||||
@ -283,7 +294,7 @@ dayX: "{day}日"
|
|||||||
monthX: "{month}月"
|
monthX: "{month}月"
|
||||||
yearX: "{year}年"
|
yearX: "{year}年"
|
||||||
pages: "页面"
|
pages: "页面"
|
||||||
integration: "连携"
|
integration: "关联"
|
||||||
connectSerice: "已连接"
|
connectSerice: "已连接"
|
||||||
disconnectSerice: "断开连接"
|
disconnectSerice: "断开连接"
|
||||||
enableLocalTimeline: "启用本地时间线功能"
|
enableLocalTimeline: "启用本地时间线功能"
|
||||||
@ -356,15 +367,14 @@ moderator: "版主"
|
|||||||
nUsersMentioned: "{n} 被提到"
|
nUsersMentioned: "{n} 被提到"
|
||||||
securityKey: "安全密钥"
|
securityKey: "安全密钥"
|
||||||
securityKeyName: "密钥名称"
|
securityKeyName: "密钥名称"
|
||||||
registerSecurityKey: "注册安全密钥"
|
registerSecurityKey: "注册硬件安全密钥"
|
||||||
lastUsed: "最后使用:"
|
lastUsed: "最后使用:"
|
||||||
unregister: "删除账户"
|
unregister: "删除账户"
|
||||||
passwordLessLogin: "无密码登录"
|
passwordLessLogin: "无密码登录"
|
||||||
resetPassword: "重置密码"
|
resetPassword: "重置密码"
|
||||||
newPasswordIs: "新的密码是「{password}」"
|
newPasswordIs: "新的密码是「{password}」"
|
||||||
autoReloadWhenDisconnected: "断开连接时自动重新加载"
|
|
||||||
autoNoteWatch: "自动关注帖子"
|
autoNoteWatch: "自动关注帖子"
|
||||||
autoNoteWatchDescription: "让您能够收到关于「反应」和回复其他用户的帖子的通知。"
|
autoNoteWatchDescription: "让您能够收到关于「回应」和回复其他用户的帖子的通知。"
|
||||||
reduceUiAnimation: "减少UI动画"
|
reduceUiAnimation: "减少UI动画"
|
||||||
share: "分享"
|
share: "分享"
|
||||||
notFound: "未找到"
|
notFound: "未找到"
|
||||||
@ -402,6 +412,7 @@ noMessagesYet: "现在没有新的聊天"
|
|||||||
newMessageExists: "新信息"
|
newMessageExists: "新信息"
|
||||||
onlyOneFileCanBeAttached: "只能添加一个附件"
|
onlyOneFileCanBeAttached: "只能添加一个附件"
|
||||||
signinRequired: "请先登录"
|
signinRequired: "请先登录"
|
||||||
|
invitations: "邀请"
|
||||||
invitationCode: "邀请码"
|
invitationCode: "邀请码"
|
||||||
checking: "正在确认"
|
checking: "正在确认"
|
||||||
available: "可用"
|
available: "可用"
|
||||||
@ -442,8 +453,8 @@ remote: "远程"
|
|||||||
total: "总计"
|
total: "总计"
|
||||||
weekOverWeekChanges: "与前一周相比"
|
weekOverWeekChanges: "与前一周相比"
|
||||||
dayOverDayChanges: "与前一日相比"
|
dayOverDayChanges: "与前一日相比"
|
||||||
accessibility: "辅助功能"
|
appearance: "外观"
|
||||||
clinetSettings: "客户端设置"
|
clientSettings: "客户端设置"
|
||||||
accountSettings: "账户设置"
|
accountSettings: "账户设置"
|
||||||
promotion: "推广"
|
promotion: "推广"
|
||||||
promote: "推广"
|
promote: "推广"
|
||||||
@ -453,19 +464,20 @@ showFeaturedNotesInTimeline: "在时间线上显示热门推荐"
|
|||||||
objectStorage: "对象存储"
|
objectStorage: "对象存储"
|
||||||
useObjectStorage: "使用对象存储"
|
useObjectStorage: "使用对象存储"
|
||||||
objectStorageBaseUrl: "基本网址"
|
objectStorageBaseUrl: "基本网址"
|
||||||
objectStorageBaseUrlDesc: "供参考的URL。如果使用CDN或Proxy,则其URL为S3:\"https://<bucket>.s3.amazonaws.com\"、GCS等:\"https://storage-googleapis.proxy.ustclug.org/<bucket>\"。"
|
objectStorageBaseUrlDesc: "URL前缀,用于构造URL到对象(媒体)的引用,如果您使用的是CDN或反向代理,请指定其URL,否则请根据您使用的服务指定可公开访问的地址。例如“https://<bucket>.s3.amazonaws.com”用于AWS S3,“https://storage.googleapis.com/<bucket>”用于GCS"
|
||||||
objectStorageBucket: "存储桶"
|
objectStorageBucket: "存储桶"
|
||||||
objectStorageBucketDesc: "请指定使用的对象存储服务的存储桶名称。"
|
objectStorageBucketDesc: "请指定使用的对象存储服务的存储桶名称。"
|
||||||
objectStoragePrefix: "前缀"
|
objectStoragePrefix: "前缀"
|
||||||
objectStoragePrefixDesc: "文件将存储在此前缀的目录下。"
|
objectStoragePrefixDesc: "文件将存储在此前缀的目录下。"
|
||||||
objectStorageEndpoint: "端点"
|
objectStorageEndpoint: "端点"
|
||||||
objectStorageEndpointDesc: "S3默认情况下为空,否则请为每个服务指定端点。 指定为“<host>”或“<host>:<port>”。"
|
objectStorageEndpointDesc: "如果你希望使用AWS S3请留空。否则请根据你使用的服务来进行设置,指定端点形式为“<host>”或“<host>:<port>”。"
|
||||||
objectStorageRegion: "可用区"
|
objectStorageRegion: "可用区"
|
||||||
objectStorageRegionDesc: "指定一个可用区,例如“xx-east-1”。 如果您的对象存储服务没有可用区概念,请将其留空或填写“us-east-1”。"
|
objectStorageRegionDesc: "指定一个可用区,例如“xx-east-1”。 如果您的对象存储服务没有可用区概念,请将其留空或填写“us-east-1”。"
|
||||||
objectStorageUseSSL: "使用SSL"
|
objectStorageUseSSL: "使用SSL"
|
||||||
objectStorageUseSSLDesc: "如果不使用https进行API连接,请关闭。"
|
objectStorageUseSSLDesc: "如果不使用https进行API连接,请关闭。"
|
||||||
objectStorageUseProxy: "使用代理"
|
objectStorageUseProxy: "使用代理"
|
||||||
objectStorageUseProxyDesc: "如果您不使用代理进行API连接,请将其关闭。"
|
objectStorageUseProxyDesc: "如果您不使用代理进行API连接,请将其关闭。"
|
||||||
|
objectStorageSetPublicRead: "上传时设置为public-read"
|
||||||
serverLogs: "服务器日志"
|
serverLogs: "服务器日志"
|
||||||
deleteAll: "删除全部"
|
deleteAll: "删除全部"
|
||||||
showFixedPostForm: "在时间线顶部显示帖子表单"
|
showFixedPostForm: "在时间线顶部显示帖子表单"
|
||||||
@ -473,6 +485,8 @@ newNoteRecived: "有新的帖子"
|
|||||||
sounds: "声音"
|
sounds: "声音"
|
||||||
listen: "听"
|
listen: "听"
|
||||||
none: "空"
|
none: "空"
|
||||||
|
showInPage: "在页面中显示"
|
||||||
|
popout: "弹窗"
|
||||||
volume: "音量"
|
volume: "音量"
|
||||||
details: "详情"
|
details: "详情"
|
||||||
chooseEmoji: "选择表情符号"
|
chooseEmoji: "选择表情符号"
|
||||||
@ -488,8 +502,8 @@ state: "状态"
|
|||||||
sort: "排序"
|
sort: "排序"
|
||||||
ascendingOrder: "升序"
|
ascendingOrder: "升序"
|
||||||
descendingOrder: "降序"
|
descendingOrder: "降序"
|
||||||
scratchpad: "暂存器"
|
scratchpad: "便签本"
|
||||||
scratchpadDescription: "暂存器为AiScript提供了实验环境。您可以编写代码以与Misskey交互,运行它并查看结果。"
|
scratchpadDescription: "便签本为AiScript提供了实验环境。您可以编写代码以与Misskey交互,运行它并查看结果。"
|
||||||
output: "输出"
|
output: "输出"
|
||||||
script: "脚本"
|
script: "脚本"
|
||||||
disablePagesScript: "禁用页面脚本"
|
disablePagesScript: "禁用页面脚本"
|
||||||
@ -515,7 +529,6 @@ enableInfiniteScroll: "启用自动滚动页面模式"
|
|||||||
visibility: "可见性"
|
visibility: "可见性"
|
||||||
poll: "调查问卷"
|
poll: "调查问卷"
|
||||||
useCw: "隐藏内容"
|
useCw: "隐藏内容"
|
||||||
fixedWidgetsPosition: "固定小工具的位置"
|
|
||||||
enablePlayer: "打开播放器"
|
enablePlayer: "打开播放器"
|
||||||
disablePlayer: "关闭播放器"
|
disablePlayer: "关闭播放器"
|
||||||
expandTweet: "展开推文"
|
expandTweet: "展开推文"
|
||||||
@ -528,6 +541,93 @@ plugins: "插件"
|
|||||||
pluginInstallWarn: "请不要安装不明来源的插件"
|
pluginInstallWarn: "请不要安装不明来源的插件"
|
||||||
deck: "Deck"
|
deck: "Deck"
|
||||||
undeck: "取消Deck"
|
undeck: "取消Deck"
|
||||||
|
useBlurEffectForModal: "模态框使用模糊效果"
|
||||||
|
generateAccessToken: "生成访问令牌"
|
||||||
|
permission: "权限"
|
||||||
|
enableAll: "启用全部"
|
||||||
|
disableAll: "禁用全部"
|
||||||
|
tokenRequested: "允许访问账户"
|
||||||
|
pluginTokenRequestedDescription: "此插件将能够拥有此处设置的权限"
|
||||||
|
notificationType: "通知类型"
|
||||||
|
edit: "编辑"
|
||||||
|
useStarForReactionFallback: "如果回应的颜文字未知,则使用★作为代替"
|
||||||
|
emailConfig: "邮件服务器设置"
|
||||||
|
enableEmail: "启用发送邮件功能"
|
||||||
|
emailConfigInfo: "用于确认电子邮件和密码重置"
|
||||||
|
email: "邮件地址"
|
||||||
|
smtpConfig: "SMTP服务器设置"
|
||||||
|
smtpHost: "主机名"
|
||||||
|
smtpPort: "端口"
|
||||||
|
smtpUser: "用户名"
|
||||||
|
smtpPass: "密码"
|
||||||
|
emptyToDisableSmtpAuth: "用户名和密码留空可以禁用SMTP验证"
|
||||||
|
smtpSecure: "在 SMTP 连接中使用隐式 SSL / TLS"
|
||||||
|
smtpSecureInfo: "使用STARTTLS时关闭。"
|
||||||
|
testEmail: "邮件发送测试"
|
||||||
|
wordMute: "文字屏蔽"
|
||||||
|
userSaysSomething: "{name}说了什么"
|
||||||
|
makeActive: "激活"
|
||||||
|
display: "显示"
|
||||||
|
copy: "复制"
|
||||||
|
metrics: "指标"
|
||||||
|
overview: "概述"
|
||||||
|
logs: "日志"
|
||||||
|
delayed: "延迟"
|
||||||
|
database: "数据库"
|
||||||
|
channel: "频道"
|
||||||
|
create: "创建"
|
||||||
|
notificationSetting: "通知设置"
|
||||||
|
notificationSettingDesc: "选择要显示的通知类型。"
|
||||||
|
useGlobalSetting: "使用全局设置"
|
||||||
|
useGlobalSettingDesc: "启用时,将使用帐户通知设置。关闭时,则可以单独设置。"
|
||||||
|
other: "其他"
|
||||||
|
regenerateLoginToken: "重新生成登录令牌"
|
||||||
|
regenerateLoginTokenDescription: "重新生成用于登录的内部令牌。通常您不需要这样做。重新生成后,您将在所有设备上登出。"
|
||||||
|
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。"
|
||||||
|
fileIdOrUrl: "文件ID或者URL"
|
||||||
|
chatOpenBehavior: "聊天窗口打开时的行为"
|
||||||
|
sample: "示例"
|
||||||
|
abuseReports: "举报"
|
||||||
|
reportAbuse: "举报"
|
||||||
|
reportAbuseOf: "举报{name}"
|
||||||
|
fillAbuseReportDescription: "请填写举报的详细原因。如果有对方发的帖子,请同时填写URL地址。"
|
||||||
|
abuseReported: "内容已发送。感谢您的报告。"
|
||||||
|
send: "发送"
|
||||||
|
abuseMarkAsResolved: "处理完毕"
|
||||||
|
openInNewTab: "在新标签页中打开"
|
||||||
|
openInSideView: "在侧边栏中打开"
|
||||||
|
defaultNavigationBehaviour: "默认导航"
|
||||||
|
editTheseSettingsMayBreakAccount: "编辑这些设置可以会损坏您的账号"
|
||||||
|
random: "随机"
|
||||||
|
_reversi:
|
||||||
|
total: "总计"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "自动重载"
|
||||||
|
dialog: "对话框警告"
|
||||||
|
quiet: "安静警告"
|
||||||
|
_channel:
|
||||||
|
create: "创建频道"
|
||||||
|
edit: "编辑频道"
|
||||||
|
setBanner: "设置横幅"
|
||||||
|
removeBanner: "删除横幅"
|
||||||
|
featured: "热点"
|
||||||
|
owned: "管理中"
|
||||||
|
following: "正在关注"
|
||||||
|
usersCount: "有{n}人参与"
|
||||||
|
notesCount: "有{n}个帖子"
|
||||||
|
_sidebar:
|
||||||
|
full: "全部"
|
||||||
|
icon: "图标"
|
||||||
|
hide: "隐藏"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "禁用词"
|
||||||
|
muteWordsDescription: "使用空格分隔表示AND逻辑,使用换行符分隔表示OR逻辑。"
|
||||||
|
muteWordsDescription2: "将关键字用斜线括起来表示正则表达式。"
|
||||||
|
softDescription: "隐藏时间轴中指定条件的帖文。"
|
||||||
|
hardDescription: "防止将具有指定条件的帖文添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
|
||||||
|
soft: "软屏蔽"
|
||||||
|
hard: "硬屏蔽"
|
||||||
|
mutedNotes: "被屏蔽的帖文"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "寻找主题"
|
explore: "寻找主题"
|
||||||
install: "安装主题"
|
install: "安装主题"
|
||||||
@ -536,7 +636,7 @@ _theme:
|
|||||||
installed: "{name} 已安装"
|
installed: "{name} 已安装"
|
||||||
alreadyInstalled: "此主题已经安装"
|
alreadyInstalled: "此主题已经安装"
|
||||||
invalid: "主题格式错误"
|
invalid: "主题格式错误"
|
||||||
make: "主题制作"
|
make: "制作主题"
|
||||||
base: "基于"
|
base: "基于"
|
||||||
addConstant: "添加常量"
|
addConstant: "添加常量"
|
||||||
constant: "常量"
|
constant: "常量"
|
||||||
@ -574,7 +674,7 @@ _theme:
|
|||||||
mention: "提及"
|
mention: "提及"
|
||||||
mentionMe: "提及"
|
mentionMe: "提及"
|
||||||
renote: "转发"
|
renote: "转发"
|
||||||
modalBg: "模块背景"
|
modalBg: "模态框背景"
|
||||||
divider: "分割线"
|
divider: "分割线"
|
||||||
scrollbarHandle: "滚动条"
|
scrollbarHandle: "滚动条"
|
||||||
scrollbarHandleHover: "滚动条(悬停)"
|
scrollbarHandleHover: "滚动条(悬停)"
|
||||||
@ -587,7 +687,7 @@ _theme:
|
|||||||
cwFg: "CW 按钮文本"
|
cwFg: "CW 按钮文本"
|
||||||
cwHoverBg: "CW 按钮背景(悬停)"
|
cwHoverBg: "CW 按钮背景(悬停)"
|
||||||
toastBg: "吐司提示背景"
|
toastBg: "吐司提示背景"
|
||||||
toastFg: "土司提示文本"
|
toastFg: "吐司提示文本"
|
||||||
buttonBg: "按钮背景"
|
buttonBg: "按钮背景"
|
||||||
buttonHoverBg: "按钮背景(悬停)"
|
buttonHoverBg: "按钮背景(悬停)"
|
||||||
inputBorder: "输入框边框"
|
inputBorder: "输入框边框"
|
||||||
@ -596,6 +696,8 @@ _theme:
|
|||||||
wallpaperOverlay: "壁纸叠加层"
|
wallpaperOverlay: "壁纸叠加层"
|
||||||
badge: "徽章"
|
badge: "徽章"
|
||||||
messageBg: "聊天背景"
|
messageBg: "聊天背景"
|
||||||
|
accentDarken: "强调色(暗)"
|
||||||
|
accentLighten: "强调色(亮)"
|
||||||
fgHighlighted: "高亮显示文本"
|
fgHighlighted: "高亮显示文本"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "帖子"
|
note: "帖子"
|
||||||
@ -604,6 +706,7 @@ _sfx:
|
|||||||
chat: "聊天"
|
chat: "聊天"
|
||||||
chatBg: "聊天背景"
|
chatBg: "聊天背景"
|
||||||
antenna: "天线接收"
|
antenna: "天线接收"
|
||||||
|
channel: "频道通知"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "未知"
|
unknown: "未知"
|
||||||
future: "未来"
|
future: "未来"
|
||||||
@ -638,9 +741,9 @@ _tutorial:
|
|||||||
step5_3: "要关注其他用户,请单击他的头像,然后在他的个人资料上按下“关注”按钮。"
|
step5_3: "要关注其他用户,请单击他的头像,然后在他的个人资料上按下“关注”按钮。"
|
||||||
step5_4: "如果用户的名称旁边有锁定图标,则该用户需要手动批准您的关注请求。"
|
step5_4: "如果用户的名称旁边有锁定图标,则该用户需要手动批准您的关注请求。"
|
||||||
step6_1: "现在,您将可以在时间线上看到其他用户的帖子。"
|
step6_1: "现在,您将可以在时间线上看到其他用户的帖子。"
|
||||||
step6_2: "您还可以在其他人的帖子上进行「反应」,以快速做出简单回复。"
|
step6_2: "您还可以在其他人的帖子上进行「回应」,以快速做出简单回复。"
|
||||||
step6_3: "在他人的贴子上按下「+」图标,即可选择想要的表情来进行「反应」。"
|
step6_3: "在他人的贴子上按下「+」图标,即可选择想要的表情来进行「回应」。"
|
||||||
step7_1: "对Misskey基本操作的简单介绍,到此结束了。 辛苦了!"
|
step7_1: "对Misskey基本操作的简单介绍,就到此结束了。 辛苦了!"
|
||||||
step7_2: "如果你想了解更多有关Misskey的信息,请参见{help}。"
|
step7_2: "如果你想了解更多有关Misskey的信息,请参见{help}。"
|
||||||
step7_3: "接下来,享受Misskey带来的乐趣吧🚀"
|
step7_3: "接下来,享受Misskey带来的乐趣吧🚀"
|
||||||
_2fa:
|
_2fa:
|
||||||
@ -651,7 +754,7 @@ _2fa:
|
|||||||
step2: "然后,扫描屏幕上显示的二维码。"
|
step2: "然后,扫描屏幕上显示的二维码。"
|
||||||
step3: "输入您的应用提供的动态口令以完成设置。"
|
step3: "输入您的应用提供的动态口令以完成设置。"
|
||||||
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
||||||
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、指纹或设备上的PIN来保护您的登录过程。"
|
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、设备上的指纹或PIN来保护您的登录过程。"
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:account": "查看账户信息"
|
"read:account": "查看账户信息"
|
||||||
"write:account": "更改帐户信息"
|
"write:account": "更改帐户信息"
|
||||||
@ -679,6 +782,8 @@ _permissions:
|
|||||||
"write:page-likes": "操作喜欢的页面"
|
"write:page-likes": "操作喜欢的页面"
|
||||||
"read:user-groups": "查看用户组"
|
"read:user-groups": "查看用户组"
|
||||||
"write:user-groups": "操作用户组"
|
"write:user-groups": "操作用户组"
|
||||||
|
"read:channels": "查看频道"
|
||||||
|
"write:channels": "管理频道"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
||||||
shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?"
|
shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?"
|
||||||
@ -711,6 +816,8 @@ _widgets:
|
|||||||
activity: "活动"
|
activity: "活动"
|
||||||
photos: "照片"
|
photos: "照片"
|
||||||
digitalClock: "数字时钟"
|
digitalClock: "数字时钟"
|
||||||
|
federation: "联邦宇宙"
|
||||||
|
postForm: "投稿窗口"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "隐藏"
|
hide: "隐藏"
|
||||||
show: "查看更多"
|
show: "查看更多"
|
||||||
@ -752,6 +859,7 @@ _visibility:
|
|||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "回复这个帖子..."
|
replyPlaceholder: "回复这个帖子..."
|
||||||
quotePlaceholder: "引用这个帖子..."
|
quotePlaceholder: "引用这个帖子..."
|
||||||
|
channelPlaceholder: "发布到频道…"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "现在如何?"
|
a: "现在如何?"
|
||||||
b: "发生了什么?"
|
b: "发生了什么?"
|
||||||
@ -1164,11 +1272,31 @@ _notification:
|
|||||||
youReceivedFollowRequest: "您有新的关注请求"
|
youReceivedFollowRequest: "您有新的关注请求"
|
||||||
yourFollowRequestAccepted: "您的关注请求已通过"
|
yourFollowRequestAccepted: "您的关注请求已通过"
|
||||||
youWereInvitedToGroup: "您有新的群组邀请"
|
youWereInvitedToGroup: "您有新的群组邀请"
|
||||||
|
_types:
|
||||||
|
all: "全部"
|
||||||
|
follow: "关注中"
|
||||||
|
mention: "提及"
|
||||||
|
reply: "回复"
|
||||||
|
renote: "转发"
|
||||||
|
quote: "引用"
|
||||||
|
reaction: "回应"
|
||||||
|
pollVote: "问卷调查已投票"
|
||||||
|
receiveFollowRequest: "收到关注请求"
|
||||||
|
followRequestAccepted: "关注请求已接受"
|
||||||
|
groupInvited: "加入群组邀请"
|
||||||
|
app: "关联应用的通知"
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "总是显示主列"
|
alwaysShowMainColumn: "总是显示主列"
|
||||||
columnAlign: "列对齐"
|
columnAlign: "列对齐"
|
||||||
|
addColumn: "添加列"
|
||||||
|
swapLeft: "向左移动"
|
||||||
|
swapRight: "向右移动"
|
||||||
|
swapUp: "向上移动"
|
||||||
|
swapDown: "向下移动"
|
||||||
|
stackLeft: "向左折叠"
|
||||||
|
popRight: "向右弹出"
|
||||||
_columns:
|
_columns:
|
||||||
widgets: "小部件"
|
widgets: "小工具"
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
tl: "时间线"
|
tl: "时间线"
|
||||||
antenna: "天线"
|
antenna: "天线"
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
---
|
---
|
||||||
_lang_: "中文(繁體)"
|
_lang_: "繁體中文"
|
||||||
introMisskey: "歡迎! Misskey是一個開源的去中心化的社群網站。\n通過「貼文」來分享現在發生的事情吧! 📡\n「反應」功能,可以讓你快速的對大家的「帖子」來表達感情👍\n一起來探索新的世界吧! 🚀"
|
introMisskey: "歡迎! Misskey是一個開源的去中心化的社群網站。\n通過「貼文」來分享現在發生的事情吧! 📡\n「反應」功能,可以讓你快速的對大家的「帖子」來表達感情👍\n一起來探索新的世界吧! 🚀"
|
||||||
monthAndDay: "{month}月 {day}日"
|
monthAndDay: "{month}月 {day}日"
|
||||||
search: "搜尋"
|
search: "搜尋"
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
username: "用戶名"
|
username: "使用者名稱"
|
||||||
password: "密碼"
|
password: "密碼"
|
||||||
fetchingAsApObject: "從Fediverse尋找中..."
|
fetchingAsApObject: "從 Fediverse 查詢中..."
|
||||||
ok: "OK"
|
ok: "OK"
|
||||||
gotIt: "知道了"
|
gotIt: "知道了"
|
||||||
cancel: "取消"
|
cancel: "取消"
|
||||||
enterUsername: "輸入用戶名"
|
enterUsername: "輸入使用者名稱"
|
||||||
renotedBy: "由{user}轉發"
|
renotedBy: "{user} 轉發了"
|
||||||
noNotes: "貼文不可用。"
|
noNotes: "貼文不可用。"
|
||||||
noNotifications: "沒有通知"
|
noNotifications: "沒有通知"
|
||||||
instance: "實例"
|
instance: "實例"
|
||||||
settings: "設定"
|
settings: "設定"
|
||||||
|
basicSettings: "基本設定"
|
||||||
|
otherSettings: "其他設定"
|
||||||
|
openInWindow: "在新視窗開啟"
|
||||||
profile: "個人檔案"
|
profile: "個人檔案"
|
||||||
timeline: "時間軸"
|
timeline: "時間軸"
|
||||||
noAccountDescription: "此用戶還沒有自我介紹"
|
noAccountDescription: "此用戶還沒有自我介紹"
|
||||||
@ -24,11 +27,11 @@ loggingIn: "登入中"
|
|||||||
logout: "登出"
|
logout: "登出"
|
||||||
signup: "註冊"
|
signup: "註冊"
|
||||||
uploading: "上傳中"
|
uploading: "上傳中"
|
||||||
save: "保存"
|
save: "儲存"
|
||||||
users: "用戶"
|
users: "使用者"
|
||||||
addUser: "新增用戶"
|
addUser: "新增使用者"
|
||||||
favorite: "收藏"
|
favorite: "收藏"
|
||||||
favorites: "收藏"
|
favorites: "已加星號"
|
||||||
unfavorite: "取消收藏"
|
unfavorite: "取消收藏"
|
||||||
pin: "置頂"
|
pin: "置頂"
|
||||||
unpin: "取消置頂"
|
unpin: "取消置頂"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有反應,
|
|||||||
addToList: "添加至清單"
|
addToList: "添加至清單"
|
||||||
sendMessage: "發送訊息"
|
sendMessage: "發送訊息"
|
||||||
copyUsername: "複製用戶名"
|
copyUsername: "複製用戶名"
|
||||||
|
searchUser: "搜尋用戶"
|
||||||
reply: "回覆"
|
reply: "回覆"
|
||||||
loadMore: "瀏覽更多"
|
loadMore: "瀏覽更多"
|
||||||
youGotNewFollower: "您有新的追隨者"
|
youGotNewFollower: "您有新的追隨者"
|
||||||
@ -47,6 +51,7 @@ receiveFollowRequest: "收到追隨請求"
|
|||||||
followRequestAccepted: "追隨請求已接受"
|
followRequestAccepted: "追隨請求已接受"
|
||||||
mention: "提及"
|
mention: "提及"
|
||||||
mentions: "提及"
|
mentions: "提及"
|
||||||
|
directNotes: "私信"
|
||||||
importAndExport: "匯入 / 匯出"
|
importAndExport: "匯入 / 匯出"
|
||||||
import: "匯入"
|
import: "匯入"
|
||||||
export: "匯出"
|
export: "匯出"
|
||||||
@ -65,8 +70,10 @@ followers: "追隨者"
|
|||||||
followsYou: "追隨你的人"
|
followsYou: "追隨你的人"
|
||||||
createList: "建立清單"
|
createList: "建立清單"
|
||||||
manageLists: "管理清單"
|
manageLists: "管理清單"
|
||||||
error: "發生錯誤"
|
error: "錯誤"
|
||||||
|
somethingHappened: "發生錯誤"
|
||||||
retry: "重試"
|
retry: "重試"
|
||||||
|
pageLoadError: "載入頁面失敗"
|
||||||
enterListName: "輸入清單名稱"
|
enterListName: "輸入清單名稱"
|
||||||
privacy: "隱私"
|
privacy: "隱私"
|
||||||
makeFollowManuallyApprove: "手動審核追隨請求"
|
makeFollowManuallyApprove: "手動審核追隨請求"
|
||||||
@ -82,7 +89,7 @@ unrenote: "取消轉發貼文"
|
|||||||
quote: "引用"
|
quote: "引用"
|
||||||
pinnedNote: "已置頂的貼文"
|
pinnedNote: "已置頂的貼文"
|
||||||
you: "您"
|
you: "您"
|
||||||
clickToShow: "點擊查看"
|
clickToShow: "按一下以顯示"
|
||||||
sensitive: "敏感內容"
|
sensitive: "敏感內容"
|
||||||
add: "新增"
|
add: "新增"
|
||||||
reaction: "反應"
|
reaction: "反應"
|
||||||
@ -92,8 +99,8 @@ attachCancel: "移除附件"
|
|||||||
markAsSensitive: "標記為敏感內容"
|
markAsSensitive: "標記為敏感內容"
|
||||||
unmarkAsSensitive: "取消標記為敏感內容"
|
unmarkAsSensitive: "取消標記為敏感內容"
|
||||||
enterFileName: "請輸入檔案名稱"
|
enterFileName: "請輸入檔案名稱"
|
||||||
mute: "禁言"
|
mute: "消音"
|
||||||
unmute: "解除禁言"
|
unmute: "解除消音"
|
||||||
block: "封鎖"
|
block: "封鎖"
|
||||||
unblock: "解除封鎖"
|
unblock: "解除封鎖"
|
||||||
suspend: "凍結"
|
suspend: "凍結"
|
||||||
@ -103,47 +110,65 @@ unblockConfirm: "確定解除封鎖此用戶?"
|
|||||||
suspendConfirm: "確定凍結此帳號?"
|
suspendConfirm: "確定凍結此帳號?"
|
||||||
unsuspendConfirm: "確定解凍此帳號?"
|
unsuspendConfirm: "確定解凍此帳號?"
|
||||||
selectList: "選擇清單"
|
selectList: "選擇清單"
|
||||||
|
selectAntenna: "選擇天線"
|
||||||
|
selectWidget: "選擇小工具"
|
||||||
|
editWidgets: "編輯小工具"
|
||||||
|
editWidgetsExit: "停止編輯"
|
||||||
customEmojis: "自訂表情符號"
|
customEmojis: "自訂表情符號"
|
||||||
emoji: "表情符號"
|
emoji: "表情符號"
|
||||||
emojiName: "表情符號名稱"
|
emojiName: "表情符號名稱"
|
||||||
emojiUrl: "表情符號URL"
|
emojiUrl: "表情符號URL"
|
||||||
addEmoji: "新增表情符號"
|
addEmoji: "新增表情符號"
|
||||||
settingGuide: "推介設定"
|
settingGuide: "推薦設定"
|
||||||
flagAsBot: "此帳戶是Bot"
|
cacheRemoteFiles: "緩存非遠程檔案"
|
||||||
flagAsCat: "此帳戶是Cat"
|
cacheRemoteFilesDescription: "禁用此設定會停止遠端檔案的緩存,從而節省儲存空間。但資料會因直接連線從而產生額外連接數據。"
|
||||||
|
flagAsBot: "此使用者是機器人"
|
||||||
|
flagAsCat: "此使用者是貓"
|
||||||
autoAcceptFollowed: "自動許可追隨"
|
autoAcceptFollowed: "自動許可追隨"
|
||||||
addAcount: "新增帳戶"
|
addAcount: "新增帳號"
|
||||||
loginFailed: "登入失敗"
|
loginFailed: "登入失敗"
|
||||||
|
showOnRemote: "轉到所在實例顯示"
|
||||||
general: "一般"
|
general: "一般"
|
||||||
wallpaper: "壁紙"
|
wallpaper: "桌布"
|
||||||
setWallpaper: "設定桌布"
|
setWallpaper: "設定桌布"
|
||||||
removeWallpaper: "移除壁紙"
|
removeWallpaper: "移除桌布"
|
||||||
searchWith: "搜尋: {q}"
|
searchWith: "搜尋: {q}"
|
||||||
youHaveNoLists: "你沒有任何清單"
|
youHaveNoLists: "沒有任何清單"
|
||||||
followConfirm: "你真的要追隨{name}嗎?"
|
followConfirm: "你真的要關注{name}嗎?"
|
||||||
|
proxyAccount: "代理帳號"
|
||||||
|
proxyAccountDescription: "代理帳號是在某些情況下充當其他服務器用戶的帳號。例如,當用戶將一個來自其他服務器的帳號放在列表中時,由於沒有其他用戶關注該帳號,該指令不會傳送到該服務器上,因此會由代理帳戶關注。"
|
||||||
host: "主機"
|
host: "主機"
|
||||||
selectUser: "選擇用戶"
|
selectUser: "選取使用者"
|
||||||
recipient: "收件人"
|
recipient: "發送至"
|
||||||
annotation: "註解"
|
annotation: "註解"
|
||||||
federation: "整合"
|
federation: "聯邦宇宙"
|
||||||
instances: "實例"
|
instances: "實例"
|
||||||
|
registeredAt: "初次觀測"
|
||||||
|
latestRequestSentAt: "上次發送的請求"
|
||||||
|
latestRequestReceivedAt: "上次收到的請求"
|
||||||
latestStatus: "最後狀態"
|
latestStatus: "最後狀態"
|
||||||
storageUsage: "已使用容量"
|
storageUsage: "已使用容量"
|
||||||
charts: "圖表"
|
charts: "圖表"
|
||||||
perHour: "每小時"
|
perHour: "每小時"
|
||||||
perDay: "每日"
|
perDay: "每日"
|
||||||
|
blockThisInstance: "封鎖此實例"
|
||||||
operations: "操作"
|
operations: "操作"
|
||||||
software: "軟體"
|
software: "軟體"
|
||||||
version: "版本"
|
version: "版本"
|
||||||
|
metadata: "元資料(Metadata)"
|
||||||
withNFiles: "{n}個檔案"
|
withNFiles: "{n}個檔案"
|
||||||
monitor: "監視器"
|
monitor: "監視器"
|
||||||
|
jobQueue: "佇列"
|
||||||
cpuAndMemory: "CPU及記憶體用量"
|
cpuAndMemory: "CPU及記憶體用量"
|
||||||
network: "網路"
|
network: "網路"
|
||||||
|
disk: "硬碟"
|
||||||
instanceInfo: "實例資訊"
|
instanceInfo: "實例資訊"
|
||||||
statistics: "統計"
|
statistics: "統計"
|
||||||
clearQueue: "清除佇列"
|
clearQueue: "清除佇列"
|
||||||
clearQueueConfirmTitle: "確定要清除佇列嗎?"
|
clearQueueConfirmTitle: "確定要清除佇列嗎?"
|
||||||
|
clearQueueConfirmText: "未發佈的帖子將不會發佈。您通常不需要確認。"
|
||||||
clearCachedFiles: "清除快取資料"
|
clearCachedFiles: "清除快取資料"
|
||||||
|
clearCachedFilesConfirm: "確定要清除緩存資料嗎?"
|
||||||
blockedInstances: "已封鎖的實例"
|
blockedInstances: "已封鎖的實例"
|
||||||
blockedInstancesDescription: "請逐行輸入需要封鎖的實例。已封鎖的實例將無法與本實例進行通訊。"
|
blockedInstancesDescription: "請逐行輸入需要封鎖的實例。已封鎖的實例將無法與本實例進行通訊。"
|
||||||
muteAndBlock: "禁言 / 封鎖"
|
muteAndBlock: "禁言 / 封鎖"
|
||||||
@ -153,14 +178,14 @@ noUsers: "無用戶"
|
|||||||
editProfile: "編輯個人檔案"
|
editProfile: "編輯個人檔案"
|
||||||
noteDeleteConfirm: "確定刪除此貼文嗎?"
|
noteDeleteConfirm: "確定刪除此貼文嗎?"
|
||||||
pinLimitExceeded: "不能再置頂更多的貼文了"
|
pinLimitExceeded: "不能再置頂更多的貼文了"
|
||||||
intro: "Misskey安裝作業完成!請創立管理員用戶"
|
intro: "Misskey 部署完成!請開設管理員帳號!"
|
||||||
done: "完成"
|
done: "完成"
|
||||||
processing: "處理中"
|
processing: "處理中"
|
||||||
preview: "預覽"
|
preview: "預覽"
|
||||||
default: "預設"
|
default: "預設"
|
||||||
noCustomEmojis: "沒有表情符號"
|
noCustomEmojis: "沒有表情符號"
|
||||||
customEmojisOfRemote: "來自其他實例的表情符號"
|
noJobs: "沒有任務"
|
||||||
federating: "整合檢索中"
|
federating: "整合搜索中"
|
||||||
blocked: "已封鎖"
|
blocked: "已封鎖"
|
||||||
suspended: "已凍結"
|
suspended: "已凍結"
|
||||||
all: "全部"
|
all: "全部"
|
||||||
@ -175,12 +200,13 @@ security: "安全性"
|
|||||||
retypedNotMatch: "不相符的輸入內容"
|
retypedNotMatch: "不相符的輸入內容"
|
||||||
currentPassword: "現在的密碼"
|
currentPassword: "現在的密碼"
|
||||||
newPassword: "新的密碼"
|
newPassword: "新的密碼"
|
||||||
newPasswordRetype: "新的密碼(再輸入一次)"
|
newPasswordRetype: "新的密碼(再輸入一次)"
|
||||||
attachFile: "添加附件"
|
attachFile: "添加附件"
|
||||||
more: "更多!"
|
more: "更多!"
|
||||||
featured: "精選"
|
featured: "精選"
|
||||||
usernameOrUserId: "用戶名或用戶ID"
|
usernameOrUserId: "使用者名稱或使用者 ID"
|
||||||
noSuchUser: "用戶不存在"
|
noSuchUser: "使用者不存在"
|
||||||
|
lookup: "查詢"
|
||||||
announcements: "公告"
|
announcements: "公告"
|
||||||
imageUrl: "圖片URL"
|
imageUrl: "圖片URL"
|
||||||
remove: "刪除"
|
remove: "刪除"
|
||||||
@ -192,6 +218,8 @@ upload: "上傳"
|
|||||||
fromDrive: "從雲端"
|
fromDrive: "從雲端"
|
||||||
fromUrl: "從URL"
|
fromUrl: "從URL"
|
||||||
uploadFromUrl: "從網址上傳"
|
uploadFromUrl: "從網址上傳"
|
||||||
|
uploadFromUrlDescription: "您要上傳的文件的URL"
|
||||||
|
uploadFromUrlRequested: "已請求上傳"
|
||||||
uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
|
uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
|
||||||
explore: "探索"
|
explore: "探索"
|
||||||
games: "Misskey 遊戲"
|
games: "Misskey 遊戲"
|
||||||
@ -199,9 +227,11 @@ messageRead: "已讀"
|
|||||||
noMoreHistory: "沒有更多歷史紀錄"
|
noMoreHistory: "沒有更多歷史紀錄"
|
||||||
startMessaging: "開始傳送訊息"
|
startMessaging: "開始傳送訊息"
|
||||||
nUsersRead: "{n}人已讀"
|
nUsersRead: "{n}人已讀"
|
||||||
|
agreeTo: "我同意{0}"
|
||||||
tos: "使用條款"
|
tos: "使用條款"
|
||||||
start: "開始"
|
start: "開始"
|
||||||
home: "首頁"
|
home: "首頁"
|
||||||
|
remoteUserCaution: "由於該用戶來自遠端實例,因此資料用戶並未即時更新。"
|
||||||
activity: "動態"
|
activity: "動態"
|
||||||
images: "圖片"
|
images: "圖片"
|
||||||
birthday: "生日"
|
birthday: "生日"
|
||||||
@ -209,10 +239,13 @@ yearsOld: "{age}歲"
|
|||||||
registeredDate: "註冊日期"
|
registeredDate: "註冊日期"
|
||||||
location: "位置"
|
location: "位置"
|
||||||
theme: "外觀主題"
|
theme: "外觀主題"
|
||||||
|
themeForLightMode: "在淺色模式下使用的主題"
|
||||||
|
themeForDarkMode: "在深色模式下使用的主題"
|
||||||
light: "淺色"
|
light: "淺色"
|
||||||
dark: "灰暗"
|
dark: "灰暗"
|
||||||
lightThemes: "明亮主題"
|
lightThemes: "明亮主題"
|
||||||
darkThemes: "灰暗主題"
|
darkThemes: "灰暗主題"
|
||||||
|
syncDeviceDarkMode: "將深色模式與設備設置同步"
|
||||||
drive: "雲端硬碟"
|
drive: "雲端硬碟"
|
||||||
fileName: "檔案名稱"
|
fileName: "檔案名稱"
|
||||||
selectFile: "選擇檔案"
|
selectFile: "選擇檔案"
|
||||||
@ -230,11 +263,14 @@ emptyFolder: "空的資料夾"
|
|||||||
unableToDelete: "無法刪除"
|
unableToDelete: "無法刪除"
|
||||||
inputNewFileName: "輸入檔案名稱"
|
inputNewFileName: "輸入檔案名稱"
|
||||||
inputNewFolderName: "輸入新資料夾的名稱"
|
inputNewFolderName: "輸入新資料夾的名稱"
|
||||||
|
circularReferenceFolder: "目標文件夾是您要移動的文件夾的子文件夾。"
|
||||||
|
hasChildFilesOrFolders: "此文件夾不是空的,無法刪除。"
|
||||||
copyUrl: "複製URL"
|
copyUrl: "複製URL"
|
||||||
rename: "重新命名"
|
rename: "重新命名"
|
||||||
avatar: "頭像"
|
avatar: "頭像"
|
||||||
banner: "橫幅"
|
banner: "橫幅"
|
||||||
nsfw: "敏感內容"
|
nsfw: "敏感內容"
|
||||||
|
whenServerDisconnected: "與服務器的連接中斷時"
|
||||||
disconnectedFromServer: "與伺服器中斷連線"
|
disconnectedFromServer: "與伺服器中斷連線"
|
||||||
reload: "重新載入"
|
reload: "重新載入"
|
||||||
doNothing: "無視"
|
doNothing: "無視"
|
||||||
@ -261,10 +297,12 @@ connectSerice: "連線"
|
|||||||
disconnectSerice: "中斷連線"
|
disconnectSerice: "中斷連線"
|
||||||
enableLocalTimeline: "開啟本地時間軸"
|
enableLocalTimeline: "開啟本地時間軸"
|
||||||
enableGlobalTimeline: "開啟全球時間軸"
|
enableGlobalTimeline: "開啟全球時間軸"
|
||||||
|
disablingTimelinesInfo: "即使您禁用了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
||||||
registration: "註冊"
|
registration: "註冊"
|
||||||
enableRegistration: "開啟新用戶註冊"
|
enableRegistration: "開啟新用戶註冊"
|
||||||
invite: "邀請"
|
invite: "邀請"
|
||||||
proxyRemoteFiles: "代理遠程檔案"
|
proxyRemoteFiles: "遠端代理檔案"
|
||||||
|
proxyRemoteFilesDescription: "啟用此設置後,由於超出存儲容量而未保存或刪除的遠程文件將被本地代理,並且將生成預覽圖。這不影響服務器的存儲。"
|
||||||
driveCapacityPerLocalAccount: "每個本地用戶的雲端容量"
|
driveCapacityPerLocalAccount: "每個本地用戶的雲端容量"
|
||||||
driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量"
|
driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量"
|
||||||
inMb: "以Mbps為單位"
|
inMb: "以Mbps為單位"
|
||||||
@ -272,6 +310,7 @@ iconUrl: "圖像URL"
|
|||||||
bannerUrl: "橫幅圖片URL"
|
bannerUrl: "橫幅圖片URL"
|
||||||
basicInfo: "基本資訊"
|
basicInfo: "基本資訊"
|
||||||
pinnedUsers: "置頂用戶"
|
pinnedUsers: "置頂用戶"
|
||||||
|
pinnedUsersDescription: "在「發現」頁面中使用換行標記想要置頂的用戶。"
|
||||||
hcaptcha: "hCaptcha"
|
hcaptcha: "hCaptcha"
|
||||||
enableHcaptcha: "啟用 hCaptcha"
|
enableHcaptcha: "啟用 hCaptcha"
|
||||||
hcaptchaSiteKey: "網站金鑰"
|
hcaptchaSiteKey: "網站金鑰"
|
||||||
@ -280,13 +319,21 @@ recaptcha: "reCAPTCHA"
|
|||||||
enableRecaptcha: "啟用 reCAPTCHA"
|
enableRecaptcha: "啟用 reCAPTCHA"
|
||||||
recaptchaSiteKey: "網站金鑰"
|
recaptchaSiteKey: "網站金鑰"
|
||||||
recaptchaSecretKey: "金鑰"
|
recaptchaSecretKey: "金鑰"
|
||||||
|
avoidMultiCaptchaConfirm: "使用多種驗證方式可能會造成干擾,您要禁用其他驗證方式嗎?您可以按“取消”保留多種驗證方式。"
|
||||||
|
antennas: "天線"
|
||||||
|
manageAntennas: "管理天線"
|
||||||
name: "名稱"
|
name: "名稱"
|
||||||
antennaKeywords: "包含的關鍵字"
|
antennaSource: "接收來源"
|
||||||
|
antennaKeywords: "包含關鍵字"
|
||||||
antennaExcludeKeywords: "排除關鍵字"
|
antennaExcludeKeywords: "排除關鍵字"
|
||||||
|
antennaKeywordsDescription: "用空格分隔指定AND、用換行符分隔指定OR"
|
||||||
notifyAntenna: "通知我有新的貼文"
|
notifyAntenna: "通知我有新的貼文"
|
||||||
serviceworker: "ServiceWorker"
|
serviceworker: "ServiceWorker"
|
||||||
enableServiceworker: "開啟 ServiceWorker"
|
enableServiceworker: "開啟 ServiceWorker"
|
||||||
|
antennaUsersDescription: "指定用換行符分隔的用戶名"
|
||||||
caseSensitive: "區分大小寫"
|
caseSensitive: "區分大小寫"
|
||||||
|
withReplies: "包含回覆"
|
||||||
|
connectedTo: "您的帳號已連接到以下社交帳號"
|
||||||
notesAndReplies: "貼文與回覆"
|
notesAndReplies: "貼文與回覆"
|
||||||
withFiles: "附件"
|
withFiles: "附件"
|
||||||
silence: "禁言"
|
silence: "禁言"
|
||||||
@ -303,6 +350,9 @@ popularTags: "熱門標籤"
|
|||||||
userList: "清單"
|
userList: "清單"
|
||||||
about: "資訊"
|
about: "資訊"
|
||||||
aboutMisskey: "關於 Misskey"
|
aboutMisskey: "關於 Misskey"
|
||||||
|
aboutMisskeyText: "Misskey是由syuilo於2014年開發的開放源代碼軟件。"
|
||||||
|
misskeyMembers: "現在由以下成員開發及維護:"
|
||||||
|
misskeySource: "源代碼在這裡公開:"
|
||||||
misskeyTranslation: "幫助我們為Misskey的翻譯工作出一分力:"
|
misskeyTranslation: "幫助我們為Misskey的翻譯工作出一分力:"
|
||||||
misskeyDonate: "向Misskey捐款以支援我們開發工作:"
|
misskeyDonate: "向Misskey捐款以支援我們開發工作:"
|
||||||
morePatrons: "感激你們的支持、 幫助。 🥰"
|
morePatrons: "感激你們的支持、 幫助。 🥰"
|
||||||
@ -320,7 +370,6 @@ unregister: "刪除賬戶"
|
|||||||
passwordLessLogin: "設置無密碼登入"
|
passwordLessLogin: "設置無密碼登入"
|
||||||
resetPassword: "重置密碼"
|
resetPassword: "重置密碼"
|
||||||
newPasswordIs: "新密碼為「{password}」"
|
newPasswordIs: "新密碼為「{password}」"
|
||||||
autoReloadWhenDisconnected: "和伺服器斷線時自動重新載入"
|
|
||||||
autoNoteWatch: "自動追隨貼文"
|
autoNoteWatch: "自動追隨貼文"
|
||||||
autoNoteWatchDescription: "收到反應或回覆過的貼文的通知"
|
autoNoteWatchDescription: "收到反應或回覆過的貼文的通知"
|
||||||
reduceUiAnimation: "減少介面的動態視覺"
|
reduceUiAnimation: "減少介面的動態視覺"
|
||||||
@ -338,6 +387,7 @@ close: "關閉"
|
|||||||
group: "群組"
|
group: "群組"
|
||||||
groups: "群組"
|
groups: "群組"
|
||||||
createGroup: "創建群組"
|
createGroup: "創建群組"
|
||||||
|
ownedGroups: "擁有的群組"
|
||||||
joinedGroups: "群組成員"
|
joinedGroups: "群組成員"
|
||||||
invites: "邀請"
|
invites: "邀請"
|
||||||
groupName: "群組名稱"
|
groupName: "群組名稱"
|
||||||
@ -359,6 +409,7 @@ noMessagesYet: "沒有訊息"
|
|||||||
newMessageExists: "有新的訊息"
|
newMessageExists: "有新的訊息"
|
||||||
onlyOneFileCanBeAttached: "只能添加一個附件"
|
onlyOneFileCanBeAttached: "只能添加一個附件"
|
||||||
signinRequired: "請先登入"
|
signinRequired: "請先登入"
|
||||||
|
invitations: "邀請"
|
||||||
invitationCode: "邀請碼"
|
invitationCode: "邀請碼"
|
||||||
checking: "確認中"
|
checking: "確認中"
|
||||||
available: "可用的"
|
available: "可用的"
|
||||||
@ -371,15 +422,51 @@ normalPassword: "密碼強度普通"
|
|||||||
strongPassword: "密碼強度堅強"
|
strongPassword: "密碼強度堅強"
|
||||||
passwordMatched: "密碼一致"
|
passwordMatched: "密碼一致"
|
||||||
passwordNotMatched: "密碼不一致"
|
passwordNotMatched: "密碼不一致"
|
||||||
|
signinWith: "以{x}登錄"
|
||||||
signinFailed: "登入失敗。 請檢查用戶名和密碼。"
|
signinFailed: "登入失敗。 請檢查用戶名和密碼。"
|
||||||
|
tapSecurityKey: "點擊安全密鑰"
|
||||||
|
or: "或者"
|
||||||
uiLanguage: "介面語言"
|
uiLanguage: "介面語言"
|
||||||
|
groupInvited: "您有新的群組邀請"
|
||||||
|
aboutX: "關於{x}"
|
||||||
|
useOsNativeEmojis: "使用OS原生表情符號"
|
||||||
|
youHaveNoGroups: "找不到群組"
|
||||||
|
joinOrCreateGroup: "請加入現有群組,或創建新群組。"
|
||||||
|
noHistory: "沒有歷史紀錄"
|
||||||
|
disableAnimatedMfm: "禁用MFM動畫"
|
||||||
|
doing: "正在進行"
|
||||||
|
category: "類別"
|
||||||
tags: "標籤"
|
tags: "標籤"
|
||||||
|
docSource: "文件來源"
|
||||||
|
createAccount: "建立帳戶"
|
||||||
|
existingAcount: "現有帳戶"
|
||||||
|
regenerate: "再生"
|
||||||
fontSize: "字體大小"
|
fontSize: "字體大小"
|
||||||
|
openImageInNewTab: "於新分頁中開啟圖片"
|
||||||
|
local: "本地"
|
||||||
|
remote: "遠端"
|
||||||
total: "合計"
|
total: "合計"
|
||||||
clinetSettings: "用戶端設定"
|
weekOverWeekChanges: "與上週相比"
|
||||||
|
dayOverDayChanges: "與前一日相比"
|
||||||
|
appearance: "外觀"
|
||||||
|
clientSettings: "用戶端設定"
|
||||||
|
accountSettings: "帳號設定"
|
||||||
|
promotion: "推廣貼文"
|
||||||
|
numberOfDays: "有效天數"
|
||||||
|
hideThisNote: "隱藏此貼文"
|
||||||
|
objectStorageBaseUrl: "Base URL"
|
||||||
|
objectStorageBucket: "儲存空間(Bucket)"
|
||||||
|
objectStoragePrefix: "前綴"
|
||||||
|
objectStorageEndpoint: "訪問網域名稱(Endpoint)"
|
||||||
|
objectStorageEndpointDesc: "如要使用AWS S3,請留空。否則請根據伺服器要求以'<host>'或 '<host>:<port>'的形式設定訪問網域名稱(Endpoint)。"
|
||||||
|
objectStorageRegion: "地域(Region)"
|
||||||
|
objectStorageUseSSL: "使用SSL"
|
||||||
|
objectStorageUseProxy: "使用網路代理"
|
||||||
serverLogs: "伺服器日誌"
|
serverLogs: "伺服器日誌"
|
||||||
deleteAll: "刪除所有記錄"
|
deleteAll: "刪除所有記錄"
|
||||||
|
sounds: "音效"
|
||||||
none: "無"
|
none: "無"
|
||||||
|
showInPage: "在頁面中顯示"
|
||||||
volume: "音量"
|
volume: "音量"
|
||||||
details: "詳細資訊"
|
details: "詳細資訊"
|
||||||
chooseEmoji: "選擇您的表情符號\n"
|
chooseEmoji: "選擇您的表情符號\n"
|
||||||
@ -387,23 +474,127 @@ unableToProcess: "操作無法完成"
|
|||||||
recentUsed: "最近使用"
|
recentUsed: "最近使用"
|
||||||
install: "安裝"
|
install: "安裝"
|
||||||
uninstall: "解除安裝"
|
uninstall: "解除安裝"
|
||||||
|
installedApps: "已授權的應用程式"
|
||||||
|
nothing: "未發現"
|
||||||
|
installedDate: "安裝時間"
|
||||||
lastUsedDate: "最後上線日期"
|
lastUsedDate: "最後上線日期"
|
||||||
state: "狀態"
|
state: "狀態"
|
||||||
|
sort: "排序"
|
||||||
|
ascendingOrder: "昇冪"
|
||||||
|
descendingOrder: "降冪"
|
||||||
|
scratchpad: "暫存記憶體"
|
||||||
output: "輸出"
|
output: "輸出"
|
||||||
|
script: "腳本"
|
||||||
|
updateRemoteUser: "更新非本地用戶資料"
|
||||||
deleteAllFiles: "刪除所有檔案"
|
deleteAllFiles: "刪除所有檔案"
|
||||||
deleteAllFilesConfirm: "要删除所有檔案吗?"
|
deleteAllFilesConfirm: "要删除所有檔案吗?"
|
||||||
|
removeAllFollowing: "解除所有追隨"
|
||||||
|
userSuspended: "該用戶已被凍結"
|
||||||
userSilenced: "該用戶已被禁言。"
|
userSilenced: "該用戶已被禁言。"
|
||||||
|
sidebar: "側邊列"
|
||||||
|
divider: "分割線"
|
||||||
|
addItem: "新增項目"
|
||||||
|
rooms: "房間"
|
||||||
|
relays: "中繼"
|
||||||
|
addRelay: "添加中繼"
|
||||||
|
inboxUrl: "私信URL"
|
||||||
|
addedRelays: "已添加的中繼"
|
||||||
|
serviceworkerInfo: "您需要啟用推送通知"
|
||||||
deletedNote: "已删除的貼文"
|
deletedNote: "已删除的貼文"
|
||||||
|
invisibleNote: "隱藏的帖子"
|
||||||
|
enableInfiniteScroll: "啟用自動滾動頁面模式"
|
||||||
|
visibility: "公開範圍"
|
||||||
|
poll: "投票"
|
||||||
|
useCw: "隱藏內容"
|
||||||
|
enablePlayer: "打開播放器"
|
||||||
|
disablePlayer: "關閉播放器"
|
||||||
|
expandTweet: "展開推文"
|
||||||
|
themeEditor: "主題編輯器"
|
||||||
|
description: "描述"
|
||||||
|
author: "作者"
|
||||||
|
leaveConfirm: "有未保存的更改。要放棄嗎?"
|
||||||
|
manage: "管理"
|
||||||
|
plugins: "插件"
|
||||||
|
pluginInstallWarn: "請不要安裝來源不明的插件。"
|
||||||
|
deck: "多欄模式"
|
||||||
|
undeck: "取消多欄模式"
|
||||||
|
permission: "權限"
|
||||||
|
enableAll: "啟用全部"
|
||||||
|
disableAll: "停用全部"
|
||||||
|
tokenRequested: "允許訪問帳號"
|
||||||
|
notificationType: "通知形式"
|
||||||
|
edit: "編輯"
|
||||||
|
useStarForReactionFallback: "以★代替未知的表情符號"
|
||||||
|
emailConfig: "電子郵件伺服器設定"
|
||||||
|
enableEmail: "啟用發送電郵功能"
|
||||||
|
emailConfigInfo: "用於確認電郵地址及密碼重置"
|
||||||
|
email: "電郵地址"
|
||||||
|
smtpConfig: "SMTP伺服器設定"
|
||||||
|
smtpHost: "主機"
|
||||||
|
smtpPort: "端口"
|
||||||
|
smtpUser: "使用者名稱"
|
||||||
|
smtpPass: "密碼"
|
||||||
|
emptyToDisableSmtpAuth: "留空使用者名稱和密碼以禁用SMTP驗證。"
|
||||||
|
testEmail: "郵件測試發送"
|
||||||
|
display: "檢視"
|
||||||
|
copy: "複製"
|
||||||
|
metrics: "指標"
|
||||||
|
overview: "概覽"
|
||||||
|
logs: "日誌"
|
||||||
|
delayed: "延遲"
|
||||||
|
database: "資料庫"
|
||||||
|
channel: "頻道"
|
||||||
|
create: "新增"
|
||||||
|
notificationSetting: "通知設定"
|
||||||
|
other: "其他"
|
||||||
|
sample: "範例 "
|
||||||
|
abuseReports: "檢舉"
|
||||||
|
reportAbuse: "檢舉"
|
||||||
|
reportAbuseOf: "檢舉{name}"
|
||||||
|
send: "發送"
|
||||||
|
openInNewTab: "在新分頁中開啟"
|
||||||
|
random: "隨機"
|
||||||
|
_reversi:
|
||||||
|
total: "合計"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "自動重載"
|
||||||
|
dialog: "以對話框警告"
|
||||||
|
quiet: "適當地警告"
|
||||||
|
_channel:
|
||||||
|
create: "建立頻道"
|
||||||
|
edit: "編輯頻道"
|
||||||
|
setBanner: "設定橫幅"
|
||||||
|
removeBanner: "移除封面圖"
|
||||||
|
featured: "流行"
|
||||||
|
owned: "管理中"
|
||||||
|
following: "關注中"
|
||||||
|
usersCount: "有{n}人參與"
|
||||||
|
notesCount: "有{n}個帖子"
|
||||||
|
_sidebar:
|
||||||
|
icon: "頭像"
|
||||||
|
hide: "隱藏"
|
||||||
|
_wordMute:
|
||||||
|
muteWords: "加入靜音文字"
|
||||||
_theme:
|
_theme:
|
||||||
|
constant: "常數"
|
||||||
|
color: "顏色"
|
||||||
func: "函数"
|
func: "函数"
|
||||||
keys:
|
keys:
|
||||||
|
bg: "背景"
|
||||||
|
fg: "文本"
|
||||||
mention: "提及"
|
mention: "提及"
|
||||||
renote: "轉發貼文"
|
renote: "轉發貼文"
|
||||||
|
divider: "分割線"
|
||||||
|
infoBg: "資訊背景"
|
||||||
|
infoFg: "資訊內容"
|
||||||
|
infoWarnBg: "警告背景"
|
||||||
|
infoWarnFg: "警告字元"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "貼文"
|
note: "貼文"
|
||||||
noteMy: "我的貼文"
|
noteMy: "我的貼文"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
chat: "傳送訊息"
|
chat: "傳送訊息"
|
||||||
|
channel: "頻道通知"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "未知"
|
unknown: "未知"
|
||||||
future: "未來"
|
future: "未來"
|
||||||
@ -434,6 +625,7 @@ _tutorial:
|
|||||||
step4_1: "筆記發出去了嗎?"
|
step4_1: "筆記發出去了嗎?"
|
||||||
step4_2: "如果你的貼文有顯示在時間軸上,就代表已經發文成功。"
|
step4_2: "如果你的貼文有顯示在時間軸上,就代表已經發文成功。"
|
||||||
step5_1: "現在試試看追隨其他人來讓你的時間軸變得更生動吧。"
|
step5_1: "現在試試看追隨其他人來讓你的時間軸變得更生動吧。"
|
||||||
|
step5_2: "你可以在{featured}上看到受歡迎的貼文,你也可以選擇從列表中追隨你喜歡的人,或者在{explore}上找到熱門使用者。"
|
||||||
step5_3: "想要追隨其他人,只要點擊他們的頭像並按「追隨」即可。"
|
step5_3: "想要追隨其他人,只要點擊他們的頭像並按「追隨」即可。"
|
||||||
step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。"
|
step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。"
|
||||||
step6_1: "現在你可以在時間軸上看到其他用戶的貼文"
|
step6_1: "現在你可以在時間軸上看到其他用戶的貼文"
|
||||||
@ -454,6 +646,16 @@ _permissions:
|
|||||||
"read:reactions": "查看反應"
|
"read:reactions": "查看反應"
|
||||||
"write:reactions": "編輯反應"
|
"write:reactions": "編輯反應"
|
||||||
"write:votes": "投票"
|
"write:votes": "投票"
|
||||||
|
"read:user-groups": "顯示使用者群組"
|
||||||
|
"write:user-groups": "編輯使用者群組"
|
||||||
|
"read:channels": "已查看的頻道"
|
||||||
|
"write:channels": "操作頻道"
|
||||||
|
_antennaSources:
|
||||||
|
all: "全部貼文"
|
||||||
|
homeTimeline: "來自已追隨使用者的貼文"
|
||||||
|
users: "來自特定使用者的貼文"
|
||||||
|
userList: "來自特定清單中的貼文"
|
||||||
|
userGroup: "來自特定群組的貼文"
|
||||||
_weekday:
|
_weekday:
|
||||||
sunday: "週日"
|
sunday: "週日"
|
||||||
monday: "週一"
|
monday: "週一"
|
||||||
@ -463,60 +665,220 @@ _weekday:
|
|||||||
friday: "週五"
|
friday: "週五"
|
||||||
saturday: "週六"
|
saturday: "週六"
|
||||||
_widgets:
|
_widgets:
|
||||||
|
memo: "備忘錄"
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
timeline: "時間軸"
|
timeline: "時間軸"
|
||||||
|
calendar: "行事曆"
|
||||||
|
trends: "發燒貼文"
|
||||||
clock: "時鐘"
|
clock: "時鐘"
|
||||||
rss: "RSS閱讀器"
|
rss: "RSS閱讀器"
|
||||||
activity: "動態"
|
activity: "動態"
|
||||||
photos: "照片"
|
photos: "照片"
|
||||||
|
digitalClock: "電子時鐘"
|
||||||
|
federation: "聯邦宇宙"
|
||||||
_cw:
|
_cw:
|
||||||
|
hide: "隱藏"
|
||||||
show: "瀏覽更多"
|
show: "瀏覽更多"
|
||||||
|
chars: "{count}字元"
|
||||||
files: "{count} 個檔案"
|
files: "{count} 個檔案"
|
||||||
_poll:
|
_poll:
|
||||||
|
noOnlyOneChoice: "至少需要兩個選項。"
|
||||||
|
expiration: "期限"
|
||||||
|
infinite: "無期限"
|
||||||
|
deadlineDate: "截止日期"
|
||||||
deadlineTime: "小時"
|
deadlineTime: "小時"
|
||||||
|
votesCount: "{n}票"
|
||||||
|
totalVotes: "一共{n}票"
|
||||||
vote: "投票"
|
vote: "投票"
|
||||||
|
showResult: "顯示結果"
|
||||||
voted: "已投票"
|
voted: "已投票"
|
||||||
|
closed: "已結束"
|
||||||
_visibility:
|
_visibility:
|
||||||
|
public: "公開"
|
||||||
home: "首頁"
|
home: "首頁"
|
||||||
followers: "追隨者"
|
followers: "追隨者"
|
||||||
|
specified: "指定使用者"
|
||||||
|
specifiedDescription: "僅發送至指定使用者"
|
||||||
|
localOnly: "僅限本地"
|
||||||
|
localOnlyDescription: "對遠端使用者隱藏"
|
||||||
|
_postForm:
|
||||||
|
replyPlaceholder: "回覆此貼文..."
|
||||||
|
quotePlaceholder: "引用此貼文..."
|
||||||
|
channelPlaceholder: "發佈到頻道"
|
||||||
|
_placeholders:
|
||||||
|
a: "今天過得如何?"
|
||||||
|
b: "有什麼新鮮事嗎?"
|
||||||
|
c: "有什麼新鮮想法嗎?"
|
||||||
|
d: "想要發布些什麼嗎?"
|
||||||
|
e: "寫些什麼吧..."
|
||||||
|
f: "期待你發佈的內容..."
|
||||||
_profile:
|
_profile:
|
||||||
name: "名稱"
|
name: "名稱"
|
||||||
username: "用戶名"
|
username: "使用者名稱"
|
||||||
|
description: "關於我"
|
||||||
|
youCanIncludeHashtags: "你也可以在「關於我」中加上 #tag"
|
||||||
|
metadata: "更多資訊"
|
||||||
|
metadataLabel: "標籤"
|
||||||
|
metadataContent: "内容"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
allNotes: "全部貼文"
|
||||||
followingList: "追隨中"
|
followingList: "追隨中"
|
||||||
muteList: "禁言"
|
muteList: "消音"
|
||||||
blockingList: "封鎖"
|
blockingList: "封鎖"
|
||||||
userLists: "清單"
|
userLists: "清單"
|
||||||
|
_charts:
|
||||||
|
usersIncDec: "使用者増減"
|
||||||
|
usersTotal: "使用者合共"
|
||||||
|
activeUsers: "活躍使用者"
|
||||||
|
notesIncDec: "貼文増減"
|
||||||
|
localNotesIncDec: "本地貼文増減"
|
||||||
|
remoteNotesIncDec: "非本地貼文的數目增减"
|
||||||
|
notesTotal: "貼文合共"
|
||||||
|
filesIncDec: "檔案増減"
|
||||||
|
filesTotal: "累計檔案"
|
||||||
|
storageUsageIncDec: "儲存空間的増減"
|
||||||
|
storageUsageTotal: "已使用的儲存空間合共"
|
||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
|
requests: "請求"
|
||||||
|
users: "使用者増減"
|
||||||
|
usersTotal: "總計使用者"
|
||||||
|
notes: "貼文増減"
|
||||||
|
notesTotal: "累計貼文"
|
||||||
|
ff: "追隨/追隨者的増減"
|
||||||
|
ffTotal: "追隨/追隨者累計"
|
||||||
cacheSize: "增加或減少快取用量"
|
cacheSize: "增加或減少快取用量"
|
||||||
cacheSizeTotal: "快取大小總計"
|
cacheSizeTotal: "快取大小總計"
|
||||||
|
files: "檔案數量的増減"
|
||||||
|
filesTotal: "檔案數量總計"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "首頁"
|
home: "首頁"
|
||||||
|
local: "本地"
|
||||||
|
social: "社群"
|
||||||
|
global: "全域"
|
||||||
_rooms:
|
_rooms:
|
||||||
|
roomOf: "{user}的房間"
|
||||||
|
addFurniture: "擺放家具"
|
||||||
|
translate: "移動 "
|
||||||
|
rotate: "旋轉"
|
||||||
|
exit: "返回"
|
||||||
|
remove: "移除"
|
||||||
|
clear: "全部移除"
|
||||||
|
clearConfirm: "確定要移除全部家具嗎?"
|
||||||
|
leaveConfirm: "修改未儲存,是否要離開?"
|
||||||
|
chooseImage: "選擇圖像"
|
||||||
|
roomType: "房間種類"
|
||||||
|
carpetColor: "地板顏色"
|
||||||
_roomType:
|
_roomType:
|
||||||
default: "預設"
|
default: "預設"
|
||||||
|
washitsu: "和室"
|
||||||
_furnitures:
|
_furnitures:
|
||||||
|
milk: "牛奶盒"
|
||||||
|
bed: "床"
|
||||||
|
low-table: "咖啡桌"
|
||||||
|
desk: "書桌"
|
||||||
|
chair: "椅子"
|
||||||
|
chair2: "椅子2"
|
||||||
|
fan: "通風機"
|
||||||
|
pc: "電腦"
|
||||||
|
plant: "觀葉植物"
|
||||||
|
plant2: "觀葉植物2"
|
||||||
|
eraser: "橡皮擦"
|
||||||
|
pencil: "鉛筆"
|
||||||
|
pudding: "布丁"
|
||||||
|
cardboard-box: "紙板箱"
|
||||||
|
cardboard-box2: "紙板箱2"
|
||||||
|
cardboard-box3: "紙板箱3"
|
||||||
|
book: "讀物"
|
||||||
|
book2: "讀物2"
|
||||||
|
piano: "鋼琴"
|
||||||
|
moon: "月亮"
|
||||||
|
corkboard: "木栓板"
|
||||||
|
mousepad: "滑鼠墊"
|
||||||
monitor: "監視器"
|
monitor: "監視器"
|
||||||
keyboard: "鍵盤"
|
keyboard: "鍵盤"
|
||||||
|
carpet-stripe: "條紋地毯"
|
||||||
|
bin: "垃圾箱"
|
||||||
|
cup-noodle: "杯面"
|
||||||
|
holo-display: "投影機"
|
||||||
|
energy-drink: "能量飲料"
|
||||||
|
doll-ai: "小藍的人偶公仔"
|
||||||
|
banknote: "大疊鈔票"
|
||||||
_pages:
|
_pages:
|
||||||
|
newPage: "建立頁面"
|
||||||
|
editPage: "編輯頁面"
|
||||||
|
created: "頁面已建立"
|
||||||
|
updated: "頁面已更新"
|
||||||
deleted: "頁面已被刪除"
|
deleted: "頁面已被刪除"
|
||||||
|
editThisPage: "編輯此頁面"
|
||||||
|
viewSource: "檢視原始碼"
|
||||||
|
viewPage: "顯示頁面"
|
||||||
like: "喜歡"
|
like: "喜歡"
|
||||||
unlike: "收回喜歡"
|
unlike: "收回喜歡"
|
||||||
|
my: "我的頁面"
|
||||||
|
liked: "已喜歡的頁面"
|
||||||
|
inspector: "面板檢查"
|
||||||
|
variables: "變數"
|
||||||
|
title: "標題"
|
||||||
|
url: "頁面網址"
|
||||||
|
fontSerif: "襯線體"
|
||||||
|
fontSansSerif: "無襯線體"
|
||||||
|
inputBlocks: "輸入"
|
||||||
blocks:
|
blocks:
|
||||||
|
section: "區段"
|
||||||
image: "圖片"
|
image: "圖片"
|
||||||
|
button: "按鈕"
|
||||||
|
if: "如果"
|
||||||
|
_if:
|
||||||
|
variable: "變數"
|
||||||
|
_post:
|
||||||
|
text: "内容"
|
||||||
|
_textInput:
|
||||||
|
name: "變數名稱"
|
||||||
|
text: "標題"
|
||||||
_textareaInput:
|
_textareaInput:
|
||||||
name: "變數名稱"
|
name: "變數名稱"
|
||||||
|
text: "標題"
|
||||||
numberInput: "輸入數值"
|
numberInput: "輸入數值"
|
||||||
_numberInput:
|
_numberInput:
|
||||||
name: "變數名稱"
|
name: "變數名稱"
|
||||||
|
text: "標題"
|
||||||
_canvas:
|
_canvas:
|
||||||
width: "寬度"
|
width: "寬度"
|
||||||
_counter:
|
height: "高度"
|
||||||
|
switch: "開關"
|
||||||
|
_switch:
|
||||||
|
name: "變數名稱"
|
||||||
text: "標題"
|
text: "標題"
|
||||||
|
default: "預設值"
|
||||||
|
counter: "計數器"
|
||||||
|
_counter:
|
||||||
|
name: "變數名稱"
|
||||||
|
text: "標題"
|
||||||
|
inc: "増加値"
|
||||||
_button:
|
_button:
|
||||||
text: "標題"
|
text: "標題"
|
||||||
|
colored: "彩色"
|
||||||
|
_action:
|
||||||
|
_dialog:
|
||||||
|
content: "内容"
|
||||||
|
resetRandom: "重設亂數"
|
||||||
|
pushEvent: "發送事件"
|
||||||
|
_pushEvent:
|
||||||
|
event: "事件名稱"
|
||||||
|
no-variable: "沒有"
|
||||||
|
callAiScript: "調用AiScript"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "函數名稱"
|
||||||
|
radioButton: "選項"
|
||||||
|
_radioButton:
|
||||||
|
name: "變數名稱"
|
||||||
|
title: "標題"
|
||||||
script:
|
script:
|
||||||
categories:
|
categories:
|
||||||
|
logical: "邏輯運算"
|
||||||
|
operation: "計算"
|
||||||
|
comparison: "對比"
|
||||||
|
random: "隨機"
|
||||||
value: "數值 "
|
value: "數值 "
|
||||||
fn: "函数"
|
fn: "函数"
|
||||||
text: "文本操作"
|
text: "文本操作"
|
||||||
@ -539,18 +901,22 @@ _pages:
|
|||||||
_add:
|
_add:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
|
subtract: "减去"
|
||||||
_subtract:
|
_subtract:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
|
multiply: "乘"
|
||||||
_multiply:
|
_multiply:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
|
divide: "除"
|
||||||
_divide:
|
_divide:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
_mod:
|
_mod:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
|
round: "四舍五入"
|
||||||
_round:
|
_round:
|
||||||
arg1: "數值"
|
arg1: "數值"
|
||||||
eq: "A和B相等"
|
eq: "A和B相等"
|
||||||
@ -592,6 +958,7 @@ _pages:
|
|||||||
not: "否"
|
not: "否"
|
||||||
_not:
|
_not:
|
||||||
arg1: "否"
|
arg1: "否"
|
||||||
|
random: "隨機"
|
||||||
_random:
|
_random:
|
||||||
arg1: "機率"
|
arg1: "機率"
|
||||||
rannum: "亂數"
|
rannum: "亂數"
|
||||||
@ -654,12 +1021,31 @@ _relayStatus:
|
|||||||
accepted: "已通過核准"
|
accepted: "已通過核准"
|
||||||
rejected: "已拒絕"
|
rejected: "已拒絕"
|
||||||
_notification:
|
_notification:
|
||||||
|
youRenoted: "{name} 轉發了你的貼文"
|
||||||
youGotPoll: "{name}已投票"
|
youGotPoll: "{name}已投票"
|
||||||
youWereFollowed: "您有新的追隨者"
|
youWereFollowed: "您有新的追隨者"
|
||||||
yourFollowRequestAccepted: "您的追隨請求已通過"
|
yourFollowRequestAccepted: "您的追隨請求已通過"
|
||||||
|
youWereInvitedToGroup: "您有新的群組邀請"
|
||||||
|
_types:
|
||||||
|
all: "全部 "
|
||||||
|
follow: "追隨中"
|
||||||
|
mention: "提及"
|
||||||
|
reply: "回覆"
|
||||||
|
renote: "轉發貼文"
|
||||||
|
quote: "引用"
|
||||||
|
reaction: "反應"
|
||||||
_deck:
|
_deck:
|
||||||
|
swapLeft: "向左移動"
|
||||||
|
swapRight: "向右移動"
|
||||||
|
swapUp: "往上移動"
|
||||||
|
swapDown: "往下移動"
|
||||||
|
stackLeft: "向左折疊"
|
||||||
|
popRight: "向右彈出"
|
||||||
_columns:
|
_columns:
|
||||||
|
widgets: "小工具"
|
||||||
notifications: "通知"
|
notifications: "通知"
|
||||||
tl: "時間軸"
|
tl: "時間軸"
|
||||||
|
antenna: "天線"
|
||||||
list: "清單"
|
list: "清單"
|
||||||
mentions: "提及"
|
mentions: "提及"
|
||||||
|
direct: "指定使用者"
|
||||||
|
14
migration/1595075960584-blurhash.ts
Normal file
14
migration/1595075960584-blurhash.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class blurhash1595075960584 implements MigrationInterface {
|
||||||
|
name = 'blurhash1595075960584'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" ADD "blurhash" character varying(128)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "blurhash"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
migration/1595077605646-blurhash-for-avatar-banner.ts
Normal file
20
migration/1595077605646-blurhash-for-avatar-banner.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class blurhashForAvatarBanner1595077605646 implements MigrationInterface {
|
||||||
|
name = 'blurhashForAvatarBanner1595077605646'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarColor"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerColor"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarBlurhash" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "bannerColor" character varying(32)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user" ADD "avatarColor" character varying(32)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1595676934834-instance-icon-url.ts
Normal file
14
migration/1595676934834-instance-icon-url.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class instanceIconUrl1595676934834 implements MigrationInterface {
|
||||||
|
name = 'instanceIconUrl1595676934834'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" ADD "iconUrl" character varying(256) DEFAULT null`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "iconUrl"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
migration/1595771249699-word-mute.ts
Normal file
30
migration/1595771249699-word-mute.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class wordMute1595771249699 implements MigrationInterface {
|
||||||
|
name = 'wordMute1595771249699'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "muted_note" ("id" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "PK_897e2eff1c0b9b64e55ca1418a4" PRIMARY KEY ("id"))`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_70ab9786313d78e4201d81cdb8" ON "muted_note" ("noteId") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_d8e07aa18c2d64e86201601aec" ON "muted_note" ("userId") `);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a8c6bfd637d3f1d67a27c48e27" ON "muted_note" ("noteId", "userId") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "enableWordMute" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "mutedWords" jsonb NOT NULL DEFAULT '[]'`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_3befe6f999c86aff06eb0257b4" ON "user_profile" ("enableWordMute") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" ADD CONSTRAINT "FK_70ab9786313d78e4201d81cdb89" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" ADD CONSTRAINT "FK_d8e07aa18c2d64e86201601aec1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" DROP CONSTRAINT "FK_d8e07aa18c2d64e86201601aec1"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" DROP CONSTRAINT "FK_70ab9786313d78e4201d81cdb89"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_3befe6f999c86aff06eb0257b4"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "mutedWords"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "enableWordMute"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_a8c6bfd637d3f1d67a27c48e27"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_d8e07aa18c2d64e86201601aec"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_70ab9786313d78e4201d81cdb8"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "muted_note"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
migration/1595782306083-word-mute2.ts
Normal file
18
migration/1595782306083-word-mute2.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class wordMute21595782306083 implements MigrationInterface {
|
||||||
|
name = 'wordMute21595782306083'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TYPE "muted_note_reason_enum" AS ENUM('word', 'manual', 'spam', 'other')`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" ADD "reason" "muted_note_reason_enum" NOT NULL`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_636e977ff90b23676fb5624b25" ON "muted_note" ("reason") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_636e977ff90b23676fb5624b25"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "muted_note" DROP COLUMN "reason"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "muted_note_reason_enum"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
58
migration/1596548170836-channel.ts
Normal file
58
migration/1596548170836-channel.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class channel1596548170836 implements MigrationInterface {
|
||||||
|
name = 'channel1596548170836'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "channel" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "lastNotedAt" TIMESTAMP WITH TIME ZONE, "userId" character varying(32) NOT NULL, "name" character varying(128) NOT NULL, "description" character varying(2048), "bannerId" character varying(32), "notesCount" integer NOT NULL DEFAULT 0, "usersCount" integer NOT NULL DEFAULT 0, CONSTRAINT "PK_590f33ee6ee7d76437acf362e39" PRIMARY KEY ("id"))`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_71cb7b435b7c0d4843317e7e16" ON "channel" ("createdAt") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_29ef80c6f13bcea998447fce43" ON "channel" ("lastNotedAt") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_823bae55bd81b3be6e05cff438" ON "channel" ("userId") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_0f58c11241e649d2a638a8de94" ON "channel" ("notesCount") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_094b86cd36bb805d1aa1e8cc9a" ON "channel" ("usersCount") `);
|
||||||
|
await queryRunner.query(`CREATE TABLE "channel_following" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "followeeId" character varying(32) NOT NULL, "followerId" character varying(32) NOT NULL, CONSTRAINT "PK_8b104be7f7415113f2a02cd5bdd" PRIMARY KEY ("id"))`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_11e71f2511589dcc8a4d3214f9" ON "channel_following" ("createdAt") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_0e43068c3f92cab197c3d3cd86" ON "channel_following" ("followeeId") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_6d8084ec9496e7334a4602707e" ON "channel_following" ("followerId") `);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_2e230dd45a10e671d781d99f3e" ON "channel_following" ("followerId", "followeeId") `);
|
||||||
|
await queryRunner.query(`CREATE TABLE "channel_note_pining" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "channelId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, CONSTRAINT "PK_44f7474496bcf2e4b741681146d" PRIMARY KEY ("id"))`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_8125f950afd3093acb10d2db8a" ON "channel_note_pining" ("channelId") `);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_f36fed37d6d4cdcc68c803cd9c" ON "channel_note_pining" ("channelId", "noteId") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" ADD "channelId" character varying(32) DEFAULT null`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel" ADD CONSTRAINT "FK_823bae55bd81b3be6e05cff4383" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel" ADD CONSTRAINT "FK_999da2bcc7efadbfe0e92d3bc19" FOREIGN KEY ("bannerId") REFERENCES "drive_file"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_f22169eb10657bded6d875ac8f9" FOREIGN KEY ("channelId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" ADD CONSTRAINT "FK_0e43068c3f92cab197c3d3cd86e" FOREIGN KEY ("followeeId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" ADD CONSTRAINT "FK_6d8084ec9496e7334a4602707e1" FOREIGN KEY ("followerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_note_pining" ADD CONSTRAINT "FK_8125f950afd3093acb10d2db8a8" FOREIGN KEY ("channelId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_note_pining" ADD CONSTRAINT "FK_10b19ef67d297ea9de325cd4502" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_note_pining" DROP CONSTRAINT "FK_10b19ef67d297ea9de325cd4502"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_note_pining" DROP CONSTRAINT "FK_8125f950afd3093acb10d2db8a8"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" DROP CONSTRAINT "FK_6d8084ec9496e7334a4602707e1"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" DROP CONSTRAINT "FK_0e43068c3f92cab197c3d3cd86e"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" DROP CONSTRAINT "FK_f22169eb10657bded6d875ac8f9"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel" DROP CONSTRAINT "FK_999da2bcc7efadbfe0e92d3bc19"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel" DROP CONSTRAINT "FK_823bae55bd81b3be6e05cff4383"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "channelId"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_f36fed37d6d4cdcc68c803cd9c"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_8125f950afd3093acb10d2db8a"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "channel_note_pining"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_2e230dd45a10e671d781d99f3e"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_6d8084ec9496e7334a4602707e"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_0e43068c3f92cab197c3d3cd86"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_11e71f2511589dcc8a4d3214f9"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "channel_following"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_094b86cd36bb805d1aa1e8cc9a"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_0f58c11241e649d2a638a8de94"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_823bae55bd81b3be6e05cff438"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_29ef80c6f13bcea998447fce43"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_71cb7b435b7c0d4843317e7e16"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "channel"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1596786425167-channel2.ts
Normal file
14
migration/1596786425167-channel2.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class channel21596786425167 implements MigrationInterface {
|
||||||
|
name = 'channel21596786425167'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "readCursor"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1597230137744-objectStorageSetPublicRead.ts
Normal file
14
migration/1597230137744-objectStorageSetPublicRead.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class objectStorageSetPublicRead1597230137744 implements MigrationInterface {
|
||||||
|
name = 'objectStorageSetPublicRead1597230137744'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "objectStorageSetPublicRead" boolean NOT NULL DEFAULT false`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
migration/1597236229720-IncludingNotificationTypes.ts
Normal file
16
migration/1597236229720-IncludingNotificationTypes.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class IncludingNotificationTypes1597236229720 implements MigrationInterface {
|
||||||
|
name = 'IncludingNotificationTypes1597236229720'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TYPE "user_profile_includingnotificationtypes_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "includingNotificationTypes" "user_profile_includingnotificationtypes_enum" array`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "includingNotificationTypes"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "user_profile_includingnotificationtypes_enum"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1597385880794-add-sensitive-index.ts
Normal file
14
migration/1597385880794-add-sensitive-index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class addSensitiveIndex1597385880794 implements MigrationInterface {
|
||||||
|
name = 'addSensitiveIndex1597385880794'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_a7eba67f8b3fa27271e85d2e26" ON "drive_file" ("isSensitive") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_a7eba67f8b3fa27271e85d2e26"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
migration/1597459042300-channel-unread.ts
Normal file
27
migration/1597459042300-channel-unread.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class channelUnread1597459042300 implements MigrationInterface {
|
||||||
|
name = 'channelUnread1597459042300'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`TRUNCATE TABLE "note_unread"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "readCursor"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_unread" ADD "isMentioned" boolean NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_unread" ADD "noteChannelId" character varying(32)`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_25b1dd384bec391b07b74b861c" ON "note_unread" ("isMentioned") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_89a29c9237b8c3b6b3cbb4cb30" ON "note_unread" ("isSpecified") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_29e8c1d579af54d4232939f994" ON "note_unread" ("noteUserId") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_6a57f051d82c6d4036c141e107" ON "note_unread" ("noteChannelId") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_6a57f051d82c6d4036c141e107"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_29e8c1d579af54d4232939f994"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_89a29c9237b8c3b6b3cbb4cb30"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_25b1dd384bec391b07b74b861c"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_unread" DROP COLUMN "noteChannelId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_unread" DROP COLUMN "isMentioned"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
migration/1597893996136-ChannelNoteIdDescIndex.ts
Normal file
16
migration/1597893996136-ChannelNoteIdDescIndex.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class ChannelNoteIdDescIndex1597893996136 implements MigrationInterface {
|
||||||
|
name = 'ChannelNoteIdDescIndex1597893996136'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_note_on_channelId_and_id_desc" ON "note" ("channelId", "id" desc)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_note_on_channelId_and_id_desc"`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
migration/1600353287890-mutingNotificationTypes.ts
Normal file
20
migration/1600353287890-mutingNotificationTypes.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class mutingNotificationTypes1600353287890 implements MigrationInterface {
|
||||||
|
name = 'mutingNotificationTypes1600353287890'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "includingNotificationTypes"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "public"."user_profile_includingnotificationtypes_enum"`);
|
||||||
|
await queryRunner.query(`CREATE TYPE "user_profile_mutingnotificationtypes_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "mutingNotificationTypes" "user_profile_mutingnotificationtypes_enum" array NOT NULL DEFAULT '{}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "mutingNotificationTypes"`);
|
||||||
|
await queryRunner.query(`DROP TYPE "user_profile_mutingnotificationtypes_enum"`);
|
||||||
|
await queryRunner.query(`CREATE TYPE "public"."user_profile_includingnotificationtypes_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "includingNotificationTypes" "user_profile_includingnotificationtypes_enum" array`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
migration/1603094348345-refine-abuse-user-report.ts
Normal file
32
migration/1603094348345-refine-abuse-user-report.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class refineAbuseUserReport1603094348345 implements MigrationInterface {
|
||||||
|
name = 'refineAbuseUserReport1603094348345'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_d049123c413e68ca52abe734203"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_d049123c413e68ca52abe73420"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_5cd442c3b2e74fdd99dae20243"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" RENAME COLUMN "userId" TO "targetUserId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "assigneeId" character varying(32)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "resolved" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "comment"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(2048) NOT NULL DEFAULT '{}'::varchar[]`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_2b15aaf4a0dc5be3499af7ab6a" ON "abuse_user_report" ("resolved") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de" FOREIGN KEY ("assigneeId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_2b15aaf4a0dc5be3499af7ab6a"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "comment"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(512) NOT NULL DEFAULT '{}'::varchar[]`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "resolved"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "assigneeId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" RENAME COLUMN "targetUserId" TO "userId"`);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5cd442c3b2e74fdd99dae20243" ON "abuse_user_report" ("userId", "reporterId") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_d049123c413e68ca52abe73420" ON "abuse_user_report" ("userId") `);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_d049123c413e68ca52abe734203" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
migration/1603095701770-refine-abuse-user-report2.ts
Normal file
20
migration/1603095701770-refine-abuse-user-report2.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class refineAbuseUserReport21603095701770 implements MigrationInterface {
|
||||||
|
name = 'refineAbuseUserReport21603095701770'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "targetUserHost" character varying(128)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "reporterHost" character varying(128)`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_4ebbf7f93cdc10e8d1ef2fc6cd" ON "abuse_user_report" ("targetUserHost") `);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_f8d8b93740ad12c4ce8213a199" ON "abuse_user_report" ("reporterHost") `);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_f8d8b93740ad12c4ce8213a199"`);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_4ebbf7f93cdc10e8d1ef2fc6cd"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "reporterHost"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "targetUserHost"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1603776877564-instance-theme-color.ts
Normal file
14
migration/1603776877564-instance-theme-color.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class instanceThemeColor1603776877564 implements MigrationInterface {
|
||||||
|
name = 'instanceThemeColor1603776877564'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" ADD "themeColor" character varying(64) DEFAULT null`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1603781553011-instance-favicon.ts
Normal file
14
migration/1603781553011-instance-favicon.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class instanceFavicon1603781553011 implements MigrationInterface {
|
||||||
|
name = 'instanceFavicon1603781553011'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" ADD "faviconUrl" character varying(256) DEFAULT null`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
163
package.json
163
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||||
"version": "12.41.2",
|
"version": "12.51.0",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -30,27 +30,26 @@
|
|||||||
"resolutions": {
|
"resolutions": {
|
||||||
"chokidar": "^3.3.1",
|
"chokidar": "^3.3.1",
|
||||||
"constantinople": "^4.0.1",
|
"constantinople": "^4.0.1",
|
||||||
"core-js": "^3.6.5",
|
|
||||||
"gulp/gulp-cli/yargs/yargs-parser": "5.0.0-security.0",
|
"gulp/gulp-cli/yargs/yargs-parser": "5.0.0-security.0",
|
||||||
"lodash": "^4.17.19",
|
"jsonld/rdf-canonize/node-forge": "0.10.0",
|
||||||
"mocha/serialize-javascript": "^3.1.0"
|
"lodash": "^4.17.20"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-transform-runtime": "7.10.3",
|
"@babel/plugin-transform-runtime": "7.11.0",
|
||||||
"@elastic/elasticsearch": "7.8.0",
|
"@elastic/elasticsearch": "7.8.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "1.2.29",
|
"@fortawesome/fontawesome-svg-core": "1.2.32",
|
||||||
"@fortawesome/free-brands-svg-icons": "5.13.1",
|
"@fortawesome/free-brands-svg-icons": "5.15.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "5.13.1",
|
"@fortawesome/free-regular-svg-icons": "5.15.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "5.13.1",
|
"@fortawesome/free-solid-svg-icons": "5.15.1",
|
||||||
"@fortawesome/vue-fontawesome": "0.1.10",
|
"@fortawesome/vue-fontawesome": "3.0.0-2",
|
||||||
"@koa/cors": "3.1.0",
|
"@koa/cors": "3.1.0",
|
||||||
"@koa/multer": "3.0.0",
|
"@koa/multer": "3.0.0",
|
||||||
"@koa/router": "9.0.1",
|
"@koa/router": "9.0.1",
|
||||||
"@sinonjs/fake-timers": "6.0.1",
|
"@sinonjs/fake-timers": "6.0.1",
|
||||||
"@syuilo/aiscript": "0.7.2",
|
"@syuilo/aiscript": "0.11.1",
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/bull": "3.14.0",
|
"@types/bull": "3.14.0",
|
||||||
"@types/cbor": "5.0.0",
|
"@types/cbor": "5.0.1",
|
||||||
"@types/dateformat": "3.0.1",
|
"@types/dateformat": "3.0.1",
|
||||||
"@types/double-ended-queue": "2.1.1",
|
"@types/double-ended-queue": "2.1.1",
|
||||||
"@types/escape-regexp": "0.0.0",
|
"@types/escape-regexp": "0.0.0",
|
||||||
@ -93,28 +92,30 @@
|
|||||||
"@types/request-stats": "3.0.0",
|
"@types/request-stats": "3.0.0",
|
||||||
"@types/rimraf": "3.0.0",
|
"@types/rimraf": "3.0.0",
|
||||||
"@types/seedrandom": "2.4.28",
|
"@types/seedrandom": "2.4.28",
|
||||||
"@types/sharp": "0.25.0",
|
"@types/sharp": "0.26.0",
|
||||||
"@types/sinonjs__fake-timers": "6.0.1",
|
"@types/sinonjs__fake-timers": "6.0.1",
|
||||||
"@types/speakeasy": "2.0.5",
|
"@types/speakeasy": "2.0.5",
|
||||||
"@types/tinycolor2": "1.4.2",
|
"@types/tinycolor2": "1.4.2",
|
||||||
"@types/tmp": "0.2.0",
|
"@types/tmp": "0.2.0",
|
||||||
"@types/uuid": "8.0.0",
|
"@types/uuid": "8.3.0",
|
||||||
"@types/web-push": "3.3.0",
|
"@types/web-push": "3.3.0",
|
||||||
"@types/webpack": "4.41.18",
|
"@types/webpack": "4.41.22",
|
||||||
"@types/webpack-stream": "3.2.11",
|
"@types/webpack-stream": "3.2.11",
|
||||||
"@types/websocket": "1.0.1",
|
"@types/websocket": "1.0.1",
|
||||||
"@types/ws": "7.2.6",
|
"@types/ws": "7.2.7",
|
||||||
"@typescript-eslint/parser": "3.6.0",
|
"@typescript-eslint/parser": "4.4.0",
|
||||||
|
"@vue/compiler-sfc": "3.0.2",
|
||||||
"abort-controller": "3.0.0",
|
"abort-controller": "3.0.0",
|
||||||
"apexcharts": "3.19.3",
|
"apexcharts": "3.22.0",
|
||||||
"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",
|
||||||
"aws-sdk": "2.713.0",
|
"aws-sdk": "2.770.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bull": "3.15.0",
|
"blurhash": "1.1.3",
|
||||||
|
"bull": "3.18.0",
|
||||||
"cafy": "15.2.1",
|
"cafy": "15.2.1",
|
||||||
"cbor": "5.0.2",
|
"cbor": "5.1.0",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
"chart.js": "2.9.3",
|
"chart.js": "2.9.3",
|
||||||
"cli-highlight": "2.1.4",
|
"cli-highlight": "2.1.4",
|
||||||
@ -122,47 +123,46 @@
|
|||||||
"content-disposition": "0.5.3",
|
"content-disposition": "0.5.3",
|
||||||
"core-js": "3.6.5",
|
"core-js": "3.6.5",
|
||||||
"crc-32": "1.2.0",
|
"crc-32": "1.2.0",
|
||||||
"css-loader": "3.6.0",
|
"css-loader": "5.0.0",
|
||||||
"cssnano": "4.1.10",
|
"cssnano": "4.1.10",
|
||||||
"dateformat": "3.0.3",
|
"dateformat": "3.0.3",
|
||||||
"deep-entries": "3.1.0",
|
"deep-entries": "3.1.0",
|
||||||
"diskusage": "1.1.3",
|
"diskusage": "1.1.3",
|
||||||
"double-ended-queue": "2.1.0-0",
|
"double-ended-queue": "2.1.0-0",
|
||||||
"escape-regexp": "0.0.1",
|
"escape-regexp": "0.0.1",
|
||||||
"eslint": "7.4.0",
|
"eslint": "7.11.0",
|
||||||
"eslint-plugin-vue": "6.2.2",
|
"eslint-plugin-vue": "7.1.0",
|
||||||
"eventemitter3": "4.0.4",
|
"eventemitter3": "4.0.7",
|
||||||
"feed": "4.2.1",
|
"feed": "4.2.1",
|
||||||
"fibers": "5.0.0",
|
"fibers": "5.0.0",
|
||||||
"file-type": "14.6.2",
|
"file-type": "16.0.0",
|
||||||
"fluent-ffmpeg": "2.1.2",
|
"fluent-ffmpeg": "2.1.2",
|
||||||
"glob": "7.1.6",
|
"glob": "7.1.6",
|
||||||
|
"got": "11.7.0",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-clean-css": "4.3.0",
|
|
||||||
"gulp-dart-sass": "1.0.2",
|
|
||||||
"gulp-rename": "2.0.0",
|
"gulp-rename": "2.0.0",
|
||||||
"gulp-replace": "1.0.0",
|
"gulp-replace": "1.0.0",
|
||||||
"gulp-sourcemaps": "2.6.5",
|
"gulp-sourcemaps": "2.6.5",
|
||||||
"gulp-terser": "1.2.0",
|
"gulp-terser": "1.4.0",
|
||||||
"gulp-tslint": "8.1.4",
|
"gulp-tslint": "8.1.4",
|
||||||
"gulp-typescript": "6.0.0-alpha.1",
|
"gulp-typescript": "6.0.0-alpha.1",
|
||||||
"hard-source-webpack-plugin": "0.13.1",
|
"hard-source-webpack-plugin": "0.13.1",
|
||||||
"hcaptcha": "0.0.2",
|
"hcaptcha": "0.0.2",
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"http-proxy-agent": "4.0.1",
|
"http-proxy-agent": "4.0.1",
|
||||||
"http-signature": "1.3.4",
|
"http-signature": "1.3.5",
|
||||||
"https-proxy-agent": "5.0.0",
|
"https-proxy-agent": "5.0.0",
|
||||||
"idb-keyval": "3.2.0",
|
"idb-keyval": "3.2.0",
|
||||||
"insert-text-at-cursor": "0.3.0",
|
"insert-text-at-cursor": "0.3.0",
|
||||||
"is-root": "2.1.0",
|
"is-root": "2.1.0",
|
||||||
"is-svg": "4.2.1",
|
"is-svg": "4.2.1",
|
||||||
"js-yaml": "3.14.0",
|
"js-yaml": "3.14.0",
|
||||||
"jsdom": "16.3.0",
|
"jsdom": "16.4.0",
|
||||||
"json5": "2.1.3",
|
"json5": "2.1.3",
|
||||||
"json5-loader": "4.0.0",
|
"json5-loader": "4.0.1",
|
||||||
"jsonld": "3.1.1",
|
"jsonld": "3.2.0",
|
||||||
"jsrsasign": "8.0.20",
|
"jsrsasign": "8.0.20",
|
||||||
"katex": "0.11.1",
|
"katex": "0.12.0",
|
||||||
"koa": "2.13.0",
|
"koa": "2.13.0",
|
||||||
"koa-bodyparser": "4.3.0",
|
"koa-bodyparser": "4.3.0",
|
||||||
"koa-favicon": "2.1.0",
|
"koa-favicon": "2.1.0",
|
||||||
@ -171,98 +171,91 @@
|
|||||||
"koa-mount": "4.0.0",
|
"koa-mount": "4.0.0",
|
||||||
"koa-send": "5.0.1",
|
"koa-send": "5.0.1",
|
||||||
"koa-slow": "2.1.0",
|
"koa-slow": "2.1.0",
|
||||||
"koa-views": "6.3.0",
|
"koa-views": "6.3.1",
|
||||||
"langmap": "0.0.16",
|
"langmap": "0.0.16",
|
||||||
"lookup-dns-cache": "2.1.0",
|
"lookup-dns-cache": "2.1.0",
|
||||||
"markdown-it": "11.0.0",
|
"markdown-it": "11.0.1",
|
||||||
"markdown-it-anchor": "5.3.0",
|
"markdown-it-anchor": "6.0.0",
|
||||||
"mocha": "8.0.1",
|
"mocha": "8.1.3",
|
||||||
"moji": "0.5.1",
|
"moji": "0.5.1",
|
||||||
"ms": "2.1.2",
|
"ms": "2.1.2",
|
||||||
"multer": "1.4.2",
|
"multer": "1.4.2",
|
||||||
"nested-property": "2.0.1",
|
"nested-property": "4.0.0",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.1",
|
||||||
"nodemailer": "6.4.10",
|
"nodemailer": "6.4.13",
|
||||||
"nprogress": "0.2.0",
|
|
||||||
"object-assign-deep": "0.4.0",
|
"object-assign-deep": "0.4.0",
|
||||||
"os-utils": "0.0.14",
|
"os-utils": "0.0.14",
|
||||||
"parse5": "6.0.0",
|
"p-cancelable": "2.0.0",
|
||||||
"parsimmon": "1.14.0",
|
"parse5": "6.0.1",
|
||||||
"pg": "8.3.0",
|
"parsimmon": "1.16.0",
|
||||||
"portal-vue": "2.1.7",
|
"pg": "8.4.1",
|
||||||
"portscanner": "2.2.0",
|
"portscanner": "2.2.0",
|
||||||
"postcss-loader": "3.0.0",
|
"postcss": "8.1.3",
|
||||||
"prismjs": "1.20.0",
|
"postcss-loader": "4.0.4",
|
||||||
|
"prismjs": "1.22.0",
|
||||||
"probe-image-size": "5.0.0",
|
"probe-image-size": "5.0.0",
|
||||||
"promise-limit": "2.7.0",
|
"promise-limit": "2.7.0",
|
||||||
"promise-sequential": "1.1.1",
|
"promise-sequential": "1.1.1",
|
||||||
"pug": "2.0.4",
|
"pug": "2.0.4",
|
||||||
"punycode": "2.1.1",
|
"punycode": "2.1.1",
|
||||||
"pureimage": "0.2.1",
|
"pureimage": "0.2.5",
|
||||||
"qrcode": "1.4.4",
|
"qrcode": "1.4.4",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"randomcolor": "0.5.4",
|
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"recaptcha-promise": "0.1.3",
|
"re2": "1.15.8",
|
||||||
|
"recaptcha-promise": "1.0.0",
|
||||||
"reconnecting-websocket": "4.4.0",
|
"reconnecting-websocket": "4.4.0",
|
||||||
"redis": "3.0.2",
|
"redis": "3.0.2",
|
||||||
"redis-lock": "0.1.4",
|
"redis-lock": "0.1.4",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"regenerator-runtime": "0.13.5",
|
"regenerator-runtime": "0.13.7",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
"request-stats": "3.0.0",
|
"request-stats": "3.0.0",
|
||||||
"require-all": "3.0.0",
|
"require-all": "3.0.0",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"rndstr": "1.0.0",
|
"rndstr": "1.0.0",
|
||||||
"s-age": "1.1.2",
|
"s-age": "1.1.2",
|
||||||
"sass": "1.26.10",
|
"sass": "1.27.0",
|
||||||
"sass-loader": "9.0.2",
|
"sass-loader": "10.0.4",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"sharp": "0.25.4",
|
"sharp": "0.26.2",
|
||||||
"speakeasy": "2.0.0",
|
"speakeasy": "2.0.0",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"style-loader": "1.2.1",
|
"style-loader": "2.0.0",
|
||||||
"summaly": "2.4.0",
|
"summaly": "2.4.0",
|
||||||
"syslog-pro": "1.0.0",
|
"syslog-pro": "1.0.0",
|
||||||
"systeminformation": "4.26.9",
|
"systeminformation": "4.27.10",
|
||||||
"syuilo-password-strength": "0.0.1",
|
"syuilo-password-strength": "0.0.1",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.117.1",
|
"three": "0.117.1",
|
||||||
"tinycolor2": "1.4.1",
|
"tinycolor2": "1.4.2",
|
||||||
"tmp": "0.2.1",
|
"tmp": "0.2.1",
|
||||||
"ts-loader": "8.0.0",
|
"ts-loader": "8.0.6",
|
||||||
"ts-node": "8.10.2",
|
"ts-node": "9.0.0",
|
||||||
"tslint": "6.1.2",
|
"tslint": "6.1.3",
|
||||||
"tslint-sonarts": "1.9.0",
|
"tslint-sonarts": "1.9.0",
|
||||||
"typeorm": "0.2.25",
|
"typeorm": "0.2.28",
|
||||||
"typescript": "3.9.6",
|
"typescript": "4.0.3",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"url-loader": "4.1.0",
|
"url-loader": "4.1.1",
|
||||||
"uuid": "8.2.0",
|
"uuid": "8.3.1",
|
||||||
"v-animate-css": "0.0.3",
|
|
||||||
"v-debounce": "0.1.2",
|
"v-debounce": "0.1.2",
|
||||||
"vue": "2.6.11",
|
"vue": "3.0.2",
|
||||||
"vue-color": "2.7.1",
|
"vue-color": "2.7.1",
|
||||||
"vue-content-loading": "1.6.0",
|
"vue-draggable-next": "1.0.8",
|
||||||
"vue-cropperjs": "4.1.0",
|
"vue-i18n": "9.0.0-beta.6",
|
||||||
"vue-i18n": "8.18.2",
|
"vue-json-pretty": "1.7.0",
|
||||||
"vue-json-pretty": "1.6.5",
|
"vue-loader": "16.0.0-beta.8",
|
||||||
"vue-loader": "15.9.3",
|
"vue-prism-editor": "1.2.2",
|
||||||
"vue-marquee-text-component": "1.1.1",
|
"vue-router": "4.0.0-beta.13",
|
||||||
"vue-meta": "2.4.0",
|
|
||||||
"vue-prism-component": "1.2.0",
|
|
||||||
"vue-prism-editor": "0.6.1",
|
|
||||||
"vue-router": "3.3.4",
|
|
||||||
"vue-style-loader": "4.1.2",
|
"vue-style-loader": "4.1.2",
|
||||||
"vue-svg-inline-loader-corejs3": "1.5.0",
|
"vue-template-compiler": "2.6.12",
|
||||||
"vue-template-compiler": "2.6.11",
|
"vuex": "4.0.0-beta.4",
|
||||||
"vuedraggable": "2.24.0",
|
"vuex-persistedstate": "3.1.0",
|
||||||
"vuex": "3.5.1",
|
|
||||||
"vuex-persistedstate": "3.0.1",
|
|
||||||
"web-push": "3.4.4",
|
"web-push": "3.4.4",
|
||||||
"webpack": "5.0.0-beta.22",
|
"webpack": "5.2.0",
|
||||||
"webpack-cli": "3.3.12",
|
"webpack-cli": "4.1.0",
|
||||||
"websocket": "1.0.31",
|
"websocket": "1.0.32",
|
||||||
"ws": "7.3.1",
|
"ws": "7.3.1",
|
||||||
"xev": "2.0.1"
|
"xev": "2.0.1"
|
||||||
},
|
},
|
||||||
|
21
src/@types/nested-property.d.ts
vendored
21
src/@types/nested-property.d.ts
vendored
@ -1,21 +0,0 @@
|
|||||||
type Obj = { [key: string]: any };
|
|
||||||
|
|
||||||
declare module 'nested-property' {
|
|
||||||
interface IHasNestedPropertyOptions {
|
|
||||||
own?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IIsInNestedPropertyOptions {
|
|
||||||
validPath?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function set<T>(object: T, property: string, value: any): T;
|
|
||||||
|
|
||||||
export function get(object: Obj, property: string): any;
|
|
||||||
|
|
||||||
export function has(object: Obj, property: string, options?: IHasNestedPropertyOptions): boolean;
|
|
||||||
|
|
||||||
export function hasOwn(object: Obj, property: string, options?: IHasNestedPropertyOptions): boolean;
|
|
||||||
|
|
||||||
export function isIn(object: Obj, property: string, objectInPath: Obj, options?: IIsInNestedPropertyOptions): boolean;
|
|
||||||
}
|
|
12
src/client/.eslintrc
Normal file
12
src/client/.eslintrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"globals": {
|
||||||
|
"_DEV_": false,
|
||||||
|
"_LANGS_": false,
|
||||||
|
"_VERSION_": false,
|
||||||
|
"_ENV_": false,
|
||||||
|
"_PERF_PREFIX_": false,
|
||||||
|
"_DATA_TRANSFER_DRIVE_FILE_": false,
|
||||||
|
"_DATA_TRANSFER_DRIVE_FOLDER_": false,
|
||||||
|
"_DATA_TRANSFER_DECK_COLUMN_": false
|
||||||
|
}
|
||||||
|
}
|
8
src/client/@types/global.d.ts
vendored
Normal file
8
src/client/@types/global.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
declare const _LANGS_: string[];
|
||||||
|
declare const _VERSION_: string;
|
||||||
|
declare const _ENV_: string;
|
||||||
|
declare const _DEV_: boolean;
|
||||||
|
declare const _PERF_PREFIX_: string;
|
||||||
|
declare const _DATA_TRANSFER_DRIVE_FILE_: string;
|
||||||
|
declare const _DATA_TRANSFER_DRIVE_FOLDER_: string;
|
||||||
|
declare const _DATA_TRANSFER_DECK_COLUMN_: string;
|
12
src/client/@types/vuex-shim.d.ts
vendored
Normal file
12
src/client/@types/vuex-shim.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { ComponentCustomProperties } from 'vue';
|
||||||
|
import { Store } from 'vuex';
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
// tslint:disable-next-line:no-empty-interface
|
||||||
|
interface State {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComponentCustomProperties {
|
||||||
|
$store: Store<State>;
|
||||||
|
}
|
||||||
|
}
|
@ -1,765 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="mk-app" v-hotkey.global="keymap">
|
|
||||||
<header class="header">
|
|
||||||
<div class="title" ref="title">
|
|
||||||
<transition :name="$store.state.device.animation ? 'header' : ''" mode="out-in" appear>
|
|
||||||
<button class="_button back" v-if="canBack" @click="back()"><fa :icon="faChevronLeft"/></button>
|
|
||||||
</transition>
|
|
||||||
<transition :name="$store.state.device.animation ? 'header' : ''" mode="out-in" appear>
|
|
||||||
<div class="body" :key="pageKey">
|
|
||||||
<div class="default">
|
|
||||||
<portal-target name="avatar" slim/>
|
|
||||||
<h1 class="title"><portal-target name="icon" slim/><portal-target name="title" slim/></h1>
|
|
||||||
</div>
|
|
||||||
<div class="custom">
|
|
||||||
<portal-target name="header" slim/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="sub">
|
|
||||||
<button v-if="widgetsEditMode" class="_button edit active" @click="widgetsEditMode = false"><fa :icon="faGripVertical"/></button>
|
|
||||||
<button v-else class="_button edit" @click="widgetsEditMode = true"><fa :icon="faGripVertical"/></button>
|
|
||||||
<div class="search">
|
|
||||||
<fa :icon="faSearch"/>
|
|
||||||
<input type="search" :placeholder="$t('search')" v-model="searchQuery" v-autocomplete="{ model: 'searchQuery' }" :disabled="searchWait" @keypress="searchKeypress"/>
|
|
||||||
</div>
|
|
||||||
<button v-if="$store.getters.isSignedIn" class="post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
|
|
||||||
<x-clock v-if="isDesktop" class="clock"/>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<x-sidebar ref="nav"/>
|
|
||||||
|
|
||||||
<div class="contents" ref="contents" :class="{ wallpaper }">
|
|
||||||
<main ref="main">
|
|
||||||
<div class="content">
|
|
||||||
<transition :name="$store.state.device.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
|
|
||||||
<keep-alive :include="['index']">
|
|
||||||
<router-view></router-view>
|
|
||||||
</keep-alive>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
<div class="powerd-by" :class="{ visible: !$store.getters.isSignedIn }">
|
|
||||||
<b><router-link to="/">{{ host }}</router-link></b>
|
|
||||||
<small>Powered by <a href="https://github.com/syuilo/misskey" target="_blank">Misskey</a></small>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<template v-if="isDesktop">
|
|
||||||
<div v-for="place in ['left', 'right']" ref="widgets" class="widgets" :class="{ edit: widgetsEditMode, fixed: $store.state.device.fixedWidgetsPosition, empty: widgets[place].length === 0 && !widgetsEditMode }" :key="place">
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="container" v-if="widgetsEditMode">
|
|
||||||
<mk-button primary @click="addWidget(place)" class="add"><fa :icon="faPlus"/></mk-button>
|
|
||||||
<x-draggable
|
|
||||||
:list="widgets[place]"
|
|
||||||
handle=".handle"
|
|
||||||
animation="150"
|
|
||||||
class="sortable"
|
|
||||||
@sort="onWidgetSort"
|
|
||||||
>
|
|
||||||
<div v-for="widget in widgets[place]" class="customize-container _panel" :key="widget.id">
|
|
||||||
<header>
|
|
||||||
<span class="handle"><fa :icon="faBars"/></span>{{ $t('_widgets.' + widget.name) }}<button class="remove _button" @click="removeWidget(widget)"><fa :icon="faTimes"/></button>
|
|
||||||
</header>
|
|
||||||
<div @click="widgetFunc(widget.id)">
|
|
||||||
<component class="_close_ _forceContainerFull_" :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-draggable>
|
|
||||||
</div>
|
|
||||||
<div class="container" v-else>
|
|
||||||
<component v-for="widget in widgets[place]" class="_close_ _forceContainerFull_" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<button class="button nav _button" @click="showNav" ref="navButton"><fa :icon="faBars"/><i v-if="navIndicated"><fa :icon="faCircle"/></i></button>
|
|
||||||
<button v-if="$route.name === 'index'" class="button home _button" @click="top()"><fa :icon="faHome"/></button>
|
|
||||||
<button v-else class="button home _button" @click="$router.push('/')"><fa :icon="faHome"/></button>
|
|
||||||
<button v-if="$store.getters.isSignedIn" class="button notifications _button" @click="$router.push('/my/notifications')"><fa :icon="faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button>
|
|
||||||
<button v-if="$store.getters.isSignedIn" class="button post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button v-if="$store.getters.isSignedIn" class="post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
|
|
||||||
|
|
||||||
<stream-indicator v-if="$store.getters.isSignedIn"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import { host } from './config';
|
|
||||||
import { search } from './scripts/search';
|
|
||||||
import { StickySidebar } from './scripts/sticky-sidebar';
|
|
||||||
import { widgets } from './widgets';
|
|
||||||
import XSidebar from './components/sidebar.vue';
|
|
||||||
|
|
||||||
const DESKTOP_THRESHOLD = 1100;
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XSidebar,
|
|
||||||
XClock: () => import('./components/header-clock.vue').then(m => m.default),
|
|
||||||
MkButton: () => import('./components/ui/button.vue').then(m => m.default),
|
|
||||||
XDraggable: () => import('vuedraggable'),
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
host: host,
|
|
||||||
pageKey: 0,
|
|
||||||
searching: false,
|
|
||||||
connection: null,
|
|
||||||
searchQuery: '',
|
|
||||||
searchWait: false,
|
|
||||||
widgetsEditMode: false,
|
|
||||||
isDesktop: window.innerWidth >= DESKTOP_THRESHOLD,
|
|
||||||
canBack: false,
|
|
||||||
menuDef: this.$store.getters.nav({}),
|
|
||||||
wallpaper: localStorage.getItem('wallpaper') != null,
|
|
||||||
faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
keymap(): any {
|
|
||||||
return {
|
|
||||||
'd': () => {
|
|
||||||
if (this.$store.state.device.syncDeviceDarkMode) return;
|
|
||||||
this.$store.commit('device/set', { key: 'darkMode', value: !this.$store.state.device.darkMode });
|
|
||||||
},
|
|
||||||
'p': this.post,
|
|
||||||
'n': this.post,
|
|
||||||
's': this.search,
|
|
||||||
'h|/': this.help
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
widgets(): any[] {
|
|
||||||
if (this.$store.getters.isSignedIn) {
|
|
||||||
const widgets = this.$store.state.deviceUser.widgets;
|
|
||||||
return {
|
|
||||||
left: widgets.filter(x => x.place === 'left'),
|
|
||||||
right: widgets.filter(x => x.place == null || x.place === 'right'),
|
|
||||||
mobile: widgets.filter(x => x.place === 'mobile'),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
left: [],
|
|
||||||
right: [{
|
|
||||||
name: 'welcome',
|
|
||||||
id: 'a', place: 'right', data: {}
|
|
||||||
}, {
|
|
||||||
name: 'calendar',
|
|
||||||
id: 'b', place: 'right', data: {}
|
|
||||||
}, {
|
|
||||||
name: 'trends',
|
|
||||||
id: 'c', place: 'right', data: {}
|
|
||||||
}],
|
|
||||||
mobile: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
menu(): string[] {
|
|
||||||
return this.$store.state.deviceUser.menu;
|
|
||||||
},
|
|
||||||
|
|
||||||
navIndicated(): boolean {
|
|
||||||
if (!this.$store.getters.isSignedIn) return false;
|
|
||||||
for (const def in this.menuDef) {
|
|
||||||
if (def === 'notifications') continue; // 通知は下にボタンとして表示されてるから
|
|
||||||
if (this.menuDef[def].indicated) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
$route(to, from) {
|
|
||||||
this.pageKey++;
|
|
||||||
this.canBack = (window.history.length > 0 && !['index'].includes(to.name));
|
|
||||||
},
|
|
||||||
|
|
||||||
isDesktop() {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.attachSticky();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
document.documentElement.style.overflowY = 'scroll';
|
|
||||||
|
|
||||||
if (this.$store.getters.isSignedIn) {
|
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
|
||||||
this.connection.on('notification', this.onNotification);
|
|
||||||
|
|
||||||
if (this.$store.state.deviceUser.widgets.length === 0) {
|
|
||||||
this.$store.commit('deviceUser/setWidgets', [{
|
|
||||||
name: 'calendar',
|
|
||||||
id: 'a', place: 'right', data: {}
|
|
||||||
}, {
|
|
||||||
name: 'notifications',
|
|
||||||
id: 'b', place: 'right', data: {}
|
|
||||||
}, {
|
|
||||||
name: 'trends',
|
|
||||||
id: 'c', place: 'right', data: {}
|
|
||||||
}]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
const adjustTitlePosition = () => {
|
|
||||||
const left = this.$refs.main.getBoundingClientRect().left - this.$refs.nav.$el.offsetWidth;
|
|
||||||
if (left >= 0) {
|
|
||||||
this.$refs.title.style.left = left + 'px';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
adjustTitlePosition();
|
|
||||||
|
|
||||||
const ro = new ResizeObserver((entries, observer) => {
|
|
||||||
adjustTitlePosition();
|
|
||||||
});
|
|
||||||
|
|
||||||
ro.observe(this.$refs.contents);
|
|
||||||
|
|
||||||
window.addEventListener('resize', adjustTitlePosition, { passive: true });
|
|
||||||
|
|
||||||
if (!this.isDesktop) {
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
if (window.innerWidth >= DESKTOP_THRESHOLD) this.isDesktop = true;
|
|
||||||
}, { passive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// widget follow
|
|
||||||
this.attachSticky();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
showNav() {
|
|
||||||
this.$refs.nav.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
attachSticky() {
|
|
||||||
if (!this.isDesktop) return;
|
|
||||||
if (this.$store.state.device.fixedWidgetsPosition) return;
|
|
||||||
|
|
||||||
const stickyWidgetColumns = this.$refs.widgets.map(w => new StickySidebar(w.children[1], w.children[0], w.offsetTop));
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
for (const stickyWidgetColumn of stickyWidgetColumns) {
|
|
||||||
stickyWidgetColumn.calc(window.scrollY);
|
|
||||||
}
|
|
||||||
}, { passive: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
top() {
|
|
||||||
window.scroll({ top: 0, behavior: 'smooth' });
|
|
||||||
},
|
|
||||||
|
|
||||||
help() {
|
|
||||||
this.$router.push('/docs/keyboard-shortcut');
|
|
||||||
},
|
|
||||||
|
|
||||||
back() {
|
|
||||||
if (this.canBack) window.history.back();
|
|
||||||
},
|
|
||||||
|
|
||||||
onTransition() {
|
|
||||||
if (window._scroll) window._scroll();
|
|
||||||
},
|
|
||||||
|
|
||||||
post() {
|
|
||||||
this.$root.post();
|
|
||||||
},
|
|
||||||
|
|
||||||
search() {
|
|
||||||
if (this.searching) return;
|
|
||||||
|
|
||||||
this.$root.dialog({
|
|
||||||
title: this.$t('search'),
|
|
||||||
input: true
|
|
||||||
}).then(async ({ canceled, result: query }) => {
|
|
||||||
if (canceled || query == null || query === '') return;
|
|
||||||
|
|
||||||
this.searching = true;
|
|
||||||
search(this, query).finally(() => {
|
|
||||||
this.searching = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
searchKeypress(e) {
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
this.searchWait = true;
|
|
||||||
search(this, this.searchQuery).finally(() => {
|
|
||||||
this.searchWait = false;
|
|
||||||
this.searchQuery = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async onNotification(notification) {
|
|
||||||
if (document.visibilityState === 'visible') {
|
|
||||||
this.$root.stream.send('readNotification', {
|
|
||||||
id: notification.id
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$root.new(await import('./components/toast.vue').then(m => m.default), {
|
|
||||||
notification
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$root.sound('notification');
|
|
||||||
},
|
|
||||||
|
|
||||||
widgetFunc(id) {
|
|
||||||
this.$refs[id][0].setting();
|
|
||||||
},
|
|
||||||
|
|
||||||
onWidgetSort() {
|
|
||||||
this.saveHome();
|
|
||||||
},
|
|
||||||
|
|
||||||
async addWidget(place) {
|
|
||||||
const { canceled, result: widget } = await this.$root.dialog({
|
|
||||||
type: null,
|
|
||||||
title: this.$t('chooseWidget'),
|
|
||||||
select: {
|
|
||||||
items: widgets.map(widget => ({
|
|
||||||
value: widget,
|
|
||||||
text: this.$t('_widgets.' + widget),
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
showCancelButton: true
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
|
|
||||||
this.$store.commit('deviceUser/addWidget', {
|
|
||||||
name: widget,
|
|
||||||
id: uuid(),
|
|
||||||
place: place,
|
|
||||||
data: {}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeWidget(widget) {
|
|
||||||
this.$store.commit('deviceUser/removeWidget', widget);
|
|
||||||
},
|
|
||||||
|
|
||||||
saveHome() {
|
|
||||||
this.$store.commit('deviceUser/setWidgets', [...this.widgets.left, ...this.widgets.right, ...this.widgets.mobile]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.mk-app {
|
|
||||||
$header-height: 60px;
|
|
||||||
$nav-width: 250px; // TODO: どこかに集約したい
|
|
||||||
$nav-icon-only-width: 80px; // TODO: どこかに集約したい
|
|
||||||
$main-width: 670px;
|
|
||||||
$ui-font-size: 1em; // TODO: どこかに集約したい
|
|
||||||
$nav-icon-only-threshold: 1279px; // TODO: どこかに集約したい
|
|
||||||
$nav-hide-threshold: 650px; // TODO: どこかに集約したい
|
|
||||||
$header-sub-hide-threshold: 1090px;
|
|
||||||
$left-widgets-hide-threshold: 1600px;
|
|
||||||
$right-widgets-hide-threshold: 1090px;
|
|
||||||
|
|
||||||
min-height: 100vh;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding-top: $header-height;
|
|
||||||
|
|
||||||
&, > .header > .body {
|
|
||||||
display: flex;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .header {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
height: $header-height;
|
|
||||||
width: calc(100% - #{$nav-width});
|
|
||||||
//background-color: var(--panel);
|
|
||||||
-webkit-backdrop-filter: blur(32px);
|
|
||||||
backdrop-filter: blur(32px);
|
|
||||||
background-color: var(--header);
|
|
||||||
border-bottom: solid 1px var(--divider);
|
|
||||||
|
|
||||||
@media (max-width: $nav-icon-only-threshold) {
|
|
||||||
width: calc(100% - #{$nav-icon-only-width});
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $nav-hide-threshold) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
position: relative;
|
|
||||||
line-height: $header-height;
|
|
||||||
height: $header-height;
|
|
||||||
max-width: $main-width;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> .back {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: $header-height;
|
|
||||||
width: $header-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .body {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
height: $header-height;
|
|
||||||
|
|
||||||
> .default {
|
|
||||||
padding: 0 $header-height;
|
|
||||||
|
|
||||||
> .avatar {
|
|
||||||
$size: 32px;
|
|
||||||
display: inline-block;
|
|
||||||
width: $size;
|
|
||||||
height: $size;
|
|
||||||
vertical-align: bottom;
|
|
||||||
margin: (($header-height - $size) / 2) 8px (($header-height - $size) / 2) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: $ui-font-size;
|
|
||||||
margin: 0;
|
|
||||||
line-height: $header-height;
|
|
||||||
|
|
||||||
> [data-icon] {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .custom {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .sub {
|
|
||||||
$post-button-size: 42px;
|
|
||||||
$post-button-margin: (($header-height - $post-button-size) / 2);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 16px;
|
|
||||||
height: $header-height;
|
|
||||||
|
|
||||||
@media (max-width: $header-sub-hide-threshold) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .edit {
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .search {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> input {
|
|
||||||
width: 220px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-right: 8px;
|
|
||||||
padding: 0 12px 0 42px;
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 38px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 38px;
|
|
||||||
color: var(--fg);
|
|
||||||
background: var(--bg);
|
|
||||||
-webkit-appearance: textfield;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> [data-icon] {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 16px;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .post {
|
|
||||||
width: $post-button-size;
|
|
||||||
height: $post-button-size;
|
|
||||||
margin-left: $post-button-margin;
|
|
||||||
border-radius: 100%;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .clock {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .contents {
|
|
||||||
display: flex;
|
|
||||||
margin: 0 auto;
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
&.wallpaper {
|
|
||||||
background: var(--wallpaperOverlay);
|
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
> main {
|
|
||||||
width: $main-width;
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
> .content {
|
|
||||||
> * {
|
|
||||||
min-height: calc(100vh - #{$header-height});
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: var(--margin);
|
|
||||||
|
|
||||||
&.full {
|
|
||||||
padding: 0 var(--margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.naked {
|
|
||||||
background: var(--bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .powerd-by {
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: center;
|
|
||||||
margin: 32px 0;
|
|
||||||
visibility: hidden;
|
|
||||||
|
|
||||||
&.visible {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.visible) {
|
|
||||||
@media (min-width: 850px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> small {
|
|
||||||
display: block;
|
|
||||||
margin-top: 8px;
|
|
||||||
opacity: 0.5;
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .widgets {
|
|
||||||
padding: 0 var(--margin);
|
|
||||||
box-shadow: 1px 0 0 0 var(--divider), -1px 0 0 0 var(--divider);
|
|
||||||
|
|
||||||
&.fixed {
|
|
||||||
position: sticky;
|
|
||||||
overflow: auto;
|
|
||||||
height: calc(100vh - #{$header-height});
|
|
||||||
top: $header-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
order: -1;
|
|
||||||
|
|
||||||
@media (max-width: $left-widgets-hide-threshold) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $right-widgets-hide-threshold) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .container {
|
|
||||||
position: sticky;
|
|
||||||
height: min-content;
|
|
||||||
min-height: calc(100vh - #{$header-height});
|
|
||||||
padding: var(--margin) 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
margin: var(--margin) 0;
|
|
||||||
width: 300px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .add {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customize-container {
|
|
||||||
margin: 8px 0;
|
|
||||||
|
|
||||||
> header {
|
|
||||||
position: relative;
|
|
||||||
line-height: 32px;
|
|
||||||
|
|
||||||
> .handle {
|
|
||||||
padding: 0 8px;
|
|
||||||
cursor: move;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .remove {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
padding: 0 8px;
|
|
||||||
line-height: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> div {
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .post {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
bottom: 32px;
|
|
||||||
right: 32px;
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
border-radius: 100%;
|
|
||||||
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
|
|
||||||
font-size: 22px;
|
|
||||||
|
|
||||||
@media (min-width: ($nav-hide-threshold + 1px)) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: ($header-sub-hide-threshold + 1px)) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .buttons {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
bottom: 0;
|
|
||||||
padding: 0 32px 32px 32px;
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: linear-gradient(0deg, var(--bg), var(--X1));
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
padding: 0 16px 16px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: ($nav-hide-threshold + 1px)) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .button {
|
|
||||||
position: relative;
|
|
||||||
padding: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
border-radius: 100%;
|
|
||||||
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
> * {
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.post) {
|
|
||||||
background: var(--panel);
|
|
||||||
color: var(--fg);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: var(--X2);
|
|
||||||
}
|
|
||||||
|
|
||||||
> i {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
color: var(--indicator);
|
|
||||||
font-size: 16px;
|
|
||||||
animation: blink 1s infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
BIN
src/client/assets/sounds/noizenecio/kick_gaba2.mp3
Normal file
BIN
src/client/assets/sounds/noizenecio/kick_gaba2.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/pirori-square-wet.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/pirori-square-wet.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/pirori-wet.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/pirori-wet.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/reverved.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/reverved.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/ryukyu.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/ryukyu.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/square-pico.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/square-pico.mp3
Normal file
Binary file not shown.
85
src/client/components/abuse-report-window.vue
Normal file
85
src/client/components/abuse-report-window.vue
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')">
|
||||||
|
<template #header>
|
||||||
|
<Fa :icon="faExclamationCircle" style="margin-right: 0.5em;"/>
|
||||||
|
<i18n-t keypath="reportAbuseOf" tag="span">
|
||||||
|
<template #name>
|
||||||
|
<b><MkAcct :user="user"/></b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</template>
|
||||||
|
<div class="dpvffvvy">
|
||||||
|
<div class="_section">
|
||||||
|
<div class="_content">
|
||||||
|
<MkTextarea v-model:value="comment">
|
||||||
|
<span>{{ $t('details') }}</span>
|
||||||
|
<template #desc>{{ $t('fillAbuseReportDescription') }}</template>
|
||||||
|
</MkTextarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="_section">
|
||||||
|
<div class="_content">
|
||||||
|
<MkButton @click="send" primary full :disabled="comment.length === 0">{{ $t('send') }}</MkButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</XWindow>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, markRaw } from 'vue';
|
||||||
|
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import XWindow from '@/components/ui/window.vue';
|
||||||
|
import MkTextarea from '@/components/ui/textarea.vue';
|
||||||
|
import MkButton from '@/components/ui/button.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
XWindow,
|
||||||
|
MkTextarea,
|
||||||
|
MkButton,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
initialComment: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['closed'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
comment: this.initialComment || '',
|
||||||
|
faExclamationCircle,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
send() {
|
||||||
|
os.apiWithDialog('users/report-abuse', {
|
||||||
|
userId: this.user.id,
|
||||||
|
comment: this.comment,
|
||||||
|
}, undefined, res => {
|
||||||
|
os.dialog({
|
||||||
|
type: 'success',
|
||||||
|
text: this.$t('abuseReported')
|
||||||
|
});
|
||||||
|
this.$refs.window.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dpvffvvy {
|
||||||
|
--section-padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,11 +6,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { toUnicode } from 'punycode';
|
import { toUnicode } from 'punycode';
|
||||||
import { host } from '../config';
|
import { host } from '@/config';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: ['user', 'detail'],
|
props: ['user', 'detail'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -34,10 +34,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import * as tinycolor from 'tinycolor2';
|
import * as tinycolor from 'tinycolor2';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
now: new Date(),
|
now: new Date(),
|
||||||
@ -127,7 +128,7 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="swhvrteh" @contextmenu.prevent="() => {}">
|
<div class="swhvrteh _popup _shadow" @contextmenu.prevent="() => {}">
|
||||||
<ol class="users" ref="suggests" v-if="type === 'user'">
|
<ol class="users" ref="suggests" v-if="type === 'user'">
|
||||||
<li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1" class="user">
|
<li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1" class="user">
|
||||||
<img class="avatar" :src="user.avatarUrl"/>
|
<img class="avatar" :src="user.avatarUrl"/>
|
||||||
<span class="name">
|
<span class="name">
|
||||||
<mk-user-name :user="user" :key="user.id"/>
|
<MkUserName :user="user" :key="user.id"/>
|
||||||
</span>
|
</span>
|
||||||
<span class="username">@{{ user | acct }}</span>
|
<span class="username">@{{ acct(user) }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li @click="chooseUser()" @keydown="onKeydown" tabindex="-1" class="choose">{{ $t('selectUser') }}</li>
|
<li @click="chooseUser()" @keydown="onKeydown" tabindex="-1" class="choose">{{ $t('selectUser') }}</li>
|
||||||
</ol>
|
</ol>
|
||||||
@ -28,12 +28,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { emojilist } from '../../misc/emojilist';
|
import { emojilist } from '../../misc/emojilist';
|
||||||
import contains from '../scripts/contains';
|
import contains from '@/scripts/contains';
|
||||||
import { twemojiSvgBase } from '../../misc/twemoji-base';
|
import { twemojiSvgBase } from '../../misc/twemoji-base';
|
||||||
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import MkUserSelect from './user-select.vue';
|
import { acct } from '@/filters/user';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
type EmojiDef = {
|
type EmojiDef = {
|
||||||
emoji: string;
|
emoji: string;
|
||||||
@ -74,7 +75,7 @@ for (const x of lib) {
|
|||||||
|
|
||||||
emjdb.sort((a, b) => a.name.length - b.name.length);
|
emjdb.sort((a, b) => a.name.length - b.name.length);
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -91,11 +92,6 @@ export default Vue.extend({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
complete: {
|
|
||||||
type: Function,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
close: {
|
close: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true,
|
required: true,
|
||||||
@ -110,7 +106,14 @@ export default Vue.extend({
|
|||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showing: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['done', 'closed'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -135,6 +138,14 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
showing() {
|
||||||
|
if (!this.showing) {
|
||||||
|
this.$emit('closed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
updated() {
|
updated() {
|
||||||
this.setPosition();
|
this.setPosition();
|
||||||
},
|
},
|
||||||
@ -189,7 +200,7 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.textarea.removeEventListener('keydown', this.onKeydown);
|
this.textarea.removeEventListener('keydown', this.onKeydown);
|
||||||
|
|
||||||
for (const el of Array.from(document.querySelectorAll('body *'))) {
|
for (const el of Array.from(document.querySelectorAll('body *'))) {
|
||||||
@ -198,6 +209,11 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
complete(type, value) {
|
||||||
|
this.$emit('done', { type, value });
|
||||||
|
this.$emit('closed');
|
||||||
|
},
|
||||||
|
|
||||||
setPosition() {
|
setPosition() {
|
||||||
if (this.x + this.$el.offsetWidth > window.innerWidth) {
|
if (this.x + this.$el.offsetWidth > window.innerWidth) {
|
||||||
this.$el.style.left = (window.innerWidth - this.$el.offsetWidth) + 'px';
|
this.$el.style.left = (window.innerWidth - this.$el.offsetWidth) + 'px';
|
||||||
@ -236,8 +252,8 @@ export default Vue.extend({
|
|||||||
this.users = users;
|
this.users = users;
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
} else {
|
} else {
|
||||||
this.$root.api('users/search', {
|
os.api('users/search-by-username-and-host', {
|
||||||
query: this.q,
|
username: this.q,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
detail: false
|
detail: false
|
||||||
}).then(users => {
|
}).then(users => {
|
||||||
@ -260,7 +276,7 @@ export default Vue.extend({
|
|||||||
this.hashtags = hashtags;
|
this.hashtags = hashtags;
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
} else {
|
} else {
|
||||||
this.$root.api('hashtags/search', {
|
os.api('hashtags/search', {
|
||||||
query: this.q,
|
query: this.q,
|
||||||
limit: 30
|
limit: 30
|
||||||
}).then(hashtags => {
|
}).then(hashtags => {
|
||||||
@ -374,14 +390,13 @@ export default Vue.extend({
|
|||||||
|
|
||||||
chooseUser() {
|
chooseUser() {
|
||||||
this.close();
|
this.close();
|
||||||
const vm = this.$root.new(MkUserSelect, {});
|
os.selectUser().then(user => {
|
||||||
vm.$once('selected', user => {
|
|
||||||
this.complete('user', user);
|
this.complete('user', user);
|
||||||
});
|
|
||||||
vm.$once('closed', () => {
|
|
||||||
this.textarea.focus();
|
this.textarea.focus();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
acct
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -393,9 +408,6 @@ export default Vue.extend({
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin-top: calc(1em + 8px);
|
margin-top: calc(1em + 8px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: var(--panel);
|
|
||||||
border: solid 1px rgba(#000, 0.1);
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: top 0.1s ease, left 0.1s ease;
|
transition: top 0.1s ease, left 0.1s ease;
|
||||||
|
|
||||||
> ol {
|
> ol {
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="eiwwqkts" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick">
|
<span class="eiwwqkts" :class="{ cat }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
||||||
<span class="inner" :style="icon"></span>
|
<img class="inner" :src="url"/>
|
||||||
</span>
|
</span>
|
||||||
<span class="eiwwqkts" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick">
|
<MkA class="eiwwqkts" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||||
<span class="inner" :style="icon"></span>
|
<img class="inner" :src="url"/>
|
||||||
</span>
|
</MkA>
|
||||||
<router-link class="eiwwqkts" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id">
|
|
||||||
<span class="inner" :style="icon"></span>
|
|
||||||
</router-link>
|
|
||||||
<router-link class="eiwwqkts" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview">
|
|
||||||
<span class="inner" :style="icon"></span>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
|
import { extractAvgColorFromBlurhash } from '@/scripts/extract-avg-color-from-blurhash';
|
||||||
|
import { acct, userPage } from '../filters/user';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
user: {
|
user: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -36,6 +32,7 @@ export default Vue.extend({
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
emits: ['click'],
|
||||||
computed: {
|
computed: {
|
||||||
cat(): boolean {
|
cat(): boolean {
|
||||||
return this.user.isCat;
|
return this.user.isCat;
|
||||||
@ -45,27 +42,22 @@ export default Vue.extend({
|
|||||||
? getStaticImageUrl(this.user.avatarUrl)
|
? getStaticImageUrl(this.user.avatarUrl)
|
||||||
: this.user.avatarUrl;
|
: this.user.avatarUrl;
|
||||||
},
|
},
|
||||||
icon(): any {
|
|
||||||
return {
|
|
||||||
backgroundColor: this.user.avatarColor,
|
|
||||||
backgroundImage: `url(${this.url})`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'user.avatarColor'() {
|
'user.avatarBlurhash'() {
|
||||||
this.$el.style.color = this.user.avatarColor;
|
if (this.$el == null) return;
|
||||||
|
this.$el.style.color = extractAvgColorFromBlurhash(this.user.avatarBlurhash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.user.avatarColor) {
|
this.$el.style.color = extractAvgColorFromBlurhash(this.user.avatarBlurhash);
|
||||||
this.$el.style.color = this.user.avatarColor;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick(e) {
|
onClick(e) {
|
||||||
this.$emit('click', e);
|
this.$emit('click', e);
|
||||||
}
|
},
|
||||||
|
acct,
|
||||||
|
userPage
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -102,15 +94,17 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
background-position: center center;
|
position: absolute;
|
||||||
background-size: cover;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-for="user in us" :key="user.id" style="display:inline-block;width:32px;height:32px;margin-right:8px;">
|
<div v-for="user in us" :key="user.id" style="display:inline-block;width:32px;height:32px;margin-right:8px;">
|
||||||
<mk-avatar :user="user" style="width:32px;height:32px;"/>
|
<MkAvatar :user="user" style="width:32px;height:32px;"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
userIds: {
|
userIds: {
|
||||||
required: true
|
required: true
|
||||||
@ -21,7 +22,7 @@ export default Vue.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.us = await this.$root.api('users/show', {
|
this.us = await os.api('users/show', {
|
||||||
userIds: this.userIds
|
userIds: this.userIds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span v-if="!available">{{ $t('waiting') }}<mk-ellipsis/></span>
|
<span v-if="!available">{{ $t('waiting') }}<MkEllipsis/></span>
|
||||||
<div ref="captcha"></div>
|
<div ref="captcha"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
type Captcha = {
|
type Captcha = {
|
||||||
render(container: string | Node, options: {
|
render(container: string | Node, options: {
|
||||||
@ -28,8 +28,9 @@ declare global {
|
|||||||
interface Window extends CaptchaContainer {
|
interface Window extends CaptchaContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
provider: {
|
provider: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -88,7 +89,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback(response?: string) {
|
callback(response?: string) {
|
||||||
this.$emit('input', typeof response == 'string' ? response : null);
|
this.$emit('update:value', typeof response == 'string' ? response : null);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
142
src/client/components/channel-follow-button.vue
Normal file
142
src/client/components/channel-follow-button.vue
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<button class="hdcaacmi _button"
|
||||||
|
:class="{ wait, active: isFollowing, full }"
|
||||||
|
@click="onClick"
|
||||||
|
:disabled="wait"
|
||||||
|
>
|
||||||
|
<template v-if="!wait">
|
||||||
|
<template v-if="isFollowing">
|
||||||
|
<span v-if="full">{{ $t('unfollow') }}</span><Fa :icon="faMinus"/>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span v-if="full">{{ $t('follow') }}</span><Fa :icon="faPlus"/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span v-if="full">{{ $t('processing') }}</span><Fa :icon="faSpinner" pulse fixed-width/>
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faSpinner, faPlus, faMinus, } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
channel: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
full: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFollowing: this.channel.isFollowing,
|
||||||
|
wait: false,
|
||||||
|
faSpinner, faPlus, faMinus,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async onClick() {
|
||||||
|
this.wait = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (this.isFollowing) {
|
||||||
|
await os.api('channels/unfollow', {
|
||||||
|
channelId: this.channel.id
|
||||||
|
});
|
||||||
|
this.isFollowing = false;
|
||||||
|
} else {
|
||||||
|
await os.api('channels/follow', {
|
||||||
|
channelId: this.channel.id
|
||||||
|
});
|
||||||
|
this.isFollowing = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
this.wait = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.hdcaacmi {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--accent);
|
||||||
|
background: transparent;
|
||||||
|
border: solid 1px var(--accent);
|
||||||
|
padding: 0;
|
||||||
|
height: 31px;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 32px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&.full {
|
||||||
|
padding: 0 8px 0 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.full) {
|
||||||
|
width: 31px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
pointer-events: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
bottom: -5px;
|
||||||
|
left: -5px;
|
||||||
|
border: 2px solid var(--focus);
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
//background: mix($primary, #fff, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
//background: mix($primary, #fff, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #fff;
|
||||||
|
background: var(--accent);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--accentLighten);
|
||||||
|
border-color: var(--accentLighten);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: var(--accentDarken);
|
||||||
|
border-color: var(--accentDarken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wait {
|
||||||
|
cursor: wait !important;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
157
src/client/components/channel-preview.vue
Normal file
157
src/client/components/channel-preview.vue
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<template>
|
||||||
|
<MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1">
|
||||||
|
<div class="banner" v-if="channel.bannerUrl" :style="`background-image: url('${channel.bannerUrl}')`">
|
||||||
|
<div class="fade"></div>
|
||||||
|
<div class="name"><Fa :icon="faSatelliteDish"/> {{ channel.name }}</div>
|
||||||
|
<div class="status">
|
||||||
|
<div>
|
||||||
|
<Fa :icon="faUsers" fixed-width/>
|
||||||
|
<i18n-t keypath="_channel.usersCount" tag="span" style="margin-left: 4px;">
|
||||||
|
<template #n>
|
||||||
|
<b>{{ channel.usersCount }}</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Fa :icon="faPencilAlt" fixed-width/>
|
||||||
|
<i18n-t keypath="_channel.notesCount" tag="span" style="margin-left: 4px;">
|
||||||
|
<template #n>
|
||||||
|
<b>{{ channel.notesCount }}</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<article v-if="channel.description">
|
||||||
|
<p :title="channel.description">{{ channel.description.length > 85 ? channel.description.slice(0, 85) + '…' : channel.description }}</p>
|
||||||
|
</article>
|
||||||
|
<footer>
|
||||||
|
<span v-if="channel.lastNotedAt">
|
||||||
|
{{ $t('updatedAt') }}: <MkTime :time="channel.lastNotedAt"/>
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
|
</MkA>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faSatelliteDish, faUsers, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
channel: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faSatelliteDish, faUsers, faPencilAlt,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.eftoefju {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .banner {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
|
||||||
|
> .fade {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
background: linear-gradient(0deg, var(--panel), var(--X15));
|
||||||
|
}
|
||||||
|
|
||||||
|
> .name {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
left: 16px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .status {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 16px;
|
||||||
|
right: 16px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 80%;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> article {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> footer {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-top: solid 1px var(--divider);
|
||||||
|
|
||||||
|
> span {
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 550px) {
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
> .banner {
|
||||||
|
height: 80px;
|
||||||
|
|
||||||
|
> .status {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> article {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
font-size: 0.8em;
|
||||||
|
|
||||||
|
> .banner {
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> article {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -1,16 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-prism :inline="inline" :language="prismLang">{{ code }}</x-prism>
|
<code v-if="inline" v-html="html" :class="`language-${prismLang}`"></code>
|
||||||
|
<pre v-else :class="`language-${prismLang}`"><code v-html="html" :class="`language-${prismLang}`"></code></pre>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import 'prismjs';
|
import 'prismjs';
|
||||||
import 'prismjs/themes/prism-okaidia.css';
|
import 'prismjs/themes/prism-okaidia.css';
|
||||||
import XPrism from 'vue-prism-component';
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
|
||||||
XPrism
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
code: {
|
code: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -28,6 +26,9 @@ export default Vue.extend({
|
|||||||
computed: {
|
computed: {
|
||||||
prismLang() {
|
prismLang() {
|
||||||
return Prism.languages[this.lang] ? this.lang : 'js';
|
return Prism.languages[this.lang] ? this.lang : 'js';
|
||||||
|
},
|
||||||
|
html() {
|
||||||
|
return Prism.highlight(this.code, Prism.languages[this.prismLang], this.prismLang);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-code :code="code" :lang="lang" :inline="inline"/>
|
<XCode :code="code" :lang="lang" :inline="inline"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent, defineAsyncComponent } from 'vue';
|
||||||
export default Vue.extend({
|
|
||||||
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XCode: () => import('./code-core.vue').then(m => m.default)
|
XCode: defineAsyncComponent(() => import('./code-core.vue'))
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
code: {
|
code: {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<button class="nrvgflfuaxwgkxoynpnumyookecqrrvh _button" @click="toggle">
|
<button class="nrvgflfu _button" @click="toggle">
|
||||||
<b>{{ value ? this.$t('_cw.hide') : this.$t('_cw.show') }}</b>
|
<b>{{ value ? $t('_cw.hide') : $t('_cw.show') }}</b>
|
||||||
<span v-if="!value">{{ this.label }}</span>
|
<span v-if="!value">{{ label }}</span>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
import { concat } from '../../prelude/array';
|
import { concat } from '../../prelude/array';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -36,14 +36,14 @@ export default Vue.extend({
|
|||||||
length,
|
length,
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
this.$emit('input', !this.value);
|
this.$emit('update:value', !this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.nrvgflfuaxwgkxoynpnumyookecqrrvh {
|
.nrvgflfu {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<component :is="$store.state.device.animation ? 'transition-group' : 'div'" class="sqadhkmv _list_" name="list" tag="div" :data-direction="direction" :data-reversed="reversed ? 'true' : 'false'">
|
<transition-group class="sqadhkmv _list_" name="list" tag="div" :data-direction="direction" :data-reversed="reversed ? 'true' : 'false'">
|
||||||
<template v-for="(item, i) in items">
|
<template v-for="(item, i) in items">
|
||||||
<slot :item="item"></slot>
|
<slot :item="item"></slot>
|
||||||
<div class="separator" v-if="showDate(i, item)" :key="item.id + '_date'">
|
<div class="separator" v-if="showDate(i, item)" :key="item.id + '_date'">
|
||||||
<p class="date">
|
<p class="date">
|
||||||
<span><fa class="icon" :icon="faAngleUp"/>{{ getDateText(item.createdAt) }}</span>
|
<span><Fa class="icon" :icon="faAngleUp"/>{{ getDateText(item.createdAt) }}</span>
|
||||||
<span>{{ getDateText(items[i + 1].createdAt) }}<fa class="icon" :icon="faAngleDown"/></span>
|
<span>{{ getDateText(items[i + 1].createdAt) }}<Fa class="icon" :icon="faAngleDown"/></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</transition-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
|
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@ -82,14 +82,14 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&[data-direction="up"] {
|
&[data-direction="up"] {
|
||||||
> .list-enter {
|
> .list-enter-from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(64px);
|
transform: translateY(64px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-direction="down"] {
|
&[data-direction="down"] {
|
||||||
> .list-enter {
|
> .list-enter-from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(-64px);
|
transform: translateY(-64px);
|
||||||
}
|
}
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-column :menu="menu" :column="column" :is-stacked="isStacked">
|
|
||||||
<template #header>
|
|
||||||
<fa :icon="faSatellite"/><span style="margin-left: 8px;">{{ column.name }}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<x-timeline ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => $emit('loaded')"/>
|
|
||||||
</x-column>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import { faSatellite, faCog } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import XColumn from './column.vue';
|
|
||||||
import XTimeline from '../timeline.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XColumn,
|
|
||||||
XTimeline,
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
column: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isStacked: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: null,
|
|
||||||
faSatellite
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
mediaOnly() {
|
|
||||||
(this.$refs.timeline as any).reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.menu = [{
|
|
||||||
icon: faCog,
|
|
||||||
text: this.$t('antenna'),
|
|
||||||
action: async () => {
|
|
||||||
const antennas = await this.$root.api('antennas/list');
|
|
||||||
this.$root.dialog({
|
|
||||||
title: this.$t('antenna'),
|
|
||||||
type: null,
|
|
||||||
select: {
|
|
||||||
items: antennas.map(x => ({
|
|
||||||
value: x, text: x.name
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
showCancelButton: true
|
|
||||||
}).then(({ canceled, result: antenna }) => {
|
|
||||||
if (canceled) return;
|
|
||||||
this.column.antennaId = antenna.id;
|
|
||||||
this.$store.commit('deviceUser/updateDeckColumn', this.column);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
focus() {
|
|
||||||
(this.$refs.timeline as any).focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
</style>
|
|
@ -1,39 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-column :name="name" :column="column" :is-stacked="isStacked" :menu="menu">
|
|
||||||
<template #header><fa :icon="faEnvelope" style="margin-right: 8px;"/>{{ column.name }}</template>
|
|
||||||
|
|
||||||
<x-direct/>
|
|
||||||
</x-column>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import XColumn from './column.vue';
|
|
||||||
import XDirect from '../../pages/messages.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XColumn,
|
|
||||||
XDirect
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
column: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isStacked: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: null,
|
|
||||||
faEnvelope
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,39 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-column :column="column" :is-stacked="isStacked" :menu="menu">
|
|
||||||
<template #header><fa :icon="faAt" style="margin-right: 8px;"/>{{ column.name }}</template>
|
|
||||||
|
|
||||||
<x-mentions/>
|
|
||||||
</x-column>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import { faAt } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import XColumn from './column.vue';
|
|
||||||
import XMentions from '../../pages/mentions.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XColumn,
|
|
||||||
XMentions
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
column: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isStacked: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: null,
|
|
||||||
faAt
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,69 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-column :column="column" :is-stacked="isStacked" :menu="menu">
|
|
||||||
<template #header><fa :icon="faBell" style="margin-right: 8px;"/>{{ column.name }}</template>
|
|
||||||
|
|
||||||
<x-notifications/>
|
|
||||||
</x-column>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { faBell } from '@fortawesome/free-regular-svg-icons';
|
|
||||||
import XColumn from './column.vue';
|
|
||||||
import XNotifications from '../notifications.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XColumn,
|
|
||||||
XNotifications
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
column: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isStacked: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: null,
|
|
||||||
faBell
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
if (this.column.notificationType == null) {
|
|
||||||
this.column.notificationType = 'all';
|
|
||||||
this.$store.commit('deviceUser/updateDeckColumn', this.column);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.menu = [{
|
|
||||||
icon: faCog,
|
|
||||||
text: this.$t('@.notification-type'),
|
|
||||||
action: () => {
|
|
||||||
this.$root.dialog({
|
|
||||||
title: this.$t('@.notification-type'),
|
|
||||||
type: null,
|
|
||||||
select: {
|
|
||||||
items: ['all', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest'].map(x => ({
|
|
||||||
value: x, text: this.$t('@.notification-types.' + x)
|
|
||||||
}))
|
|
||||||
default: this.column.notificationType,
|
|
||||||
},
|
|
||||||
showCancelButton: true
|
|
||||||
}).then(({ canceled, result: type }) => {
|
|
||||||
if (canceled) return;
|
|
||||||
this.column.notificationType = type;
|
|
||||||
this.$store.commit('deviceUser/updateDeckColumn', this.column);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,31 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-dialog" :class="{ iconOnly }">
|
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
|
||||||
<transition :name="$store.state.device.animation ? 'bg-fade' : ''" appear>
|
<div class="mk-dialog">
|
||||||
<div class="bg _modalBg" ref="bg" @click="onBgClick" v-if="show"></div>
|
|
||||||
</transition>
|
|
||||||
<transition :name="$store.state.device.animation ? 'dialog' : ''" appear @after-leave="() => { destroyDom(); }">
|
|
||||||
<div class="main" ref="main" v-if="show">
|
|
||||||
<template v-if="type == 'signin'">
|
|
||||||
<mk-signin/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="icon" v-if="icon">
|
<div class="icon" v-if="icon">
|
||||||
<fa :icon="icon"/>
|
<Fa :icon="icon"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" v-else-if="!input && !select && !user" :class="type">
|
<div class="icon" v-else-if="!input && !select" :class="type">
|
||||||
<fa :icon="faCheck" v-if="type === 'success'"/>
|
<Fa :icon="faCheck" v-if="type === 'success'"/>
|
||||||
<fa :icon="faTimesCircle" v-if="type === 'error'"/>
|
<Fa :icon="faTimesCircle" v-if="type === 'error'"/>
|
||||||
<fa :icon="faExclamationTriangle" v-if="type === 'warning'"/>
|
<Fa :icon="faExclamationTriangle" v-if="type === 'warning'"/>
|
||||||
<fa :icon="faInfoCircle" v-if="type === 'info'"/>
|
<Fa :icon="faInfoCircle" v-if="type === 'info'"/>
|
||||||
<fa :icon="faQuestionCircle" v-if="type === 'question'"/>
|
<Fa :icon="faQuestionCircle" v-if="type === 'question'"/>
|
||||||
<fa :icon="faSpinner" pulse v-if="type === 'waiting'"/>
|
<Fa :icon="faSpinner" pulse v-if="type === 'waiting'"/>
|
||||||
</div>
|
</div>
|
||||||
<header v-if="title" v-html="title"></header>
|
<header v-if="title"><Mfm :text="title"/></header>
|
||||||
<header v-if="title == null && user">{{ $t('enterUsername') }}</header>
|
<div class="body" v-if="text"><Mfm :text="text"/></div>
|
||||||
<div class="body" v-if="text" v-html="text"></div>
|
<MkInput v-if="input" v-model:value="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></MkInput>
|
||||||
<mk-input v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></mk-input>
|
<MkSelect v-if="select" v-model:value="selectedValue" autofocus>
|
||||||
<mk-input v-if="user" v-model="userInputValue" autofocus @keydown="onInputKeydown"><template #prefix>@</template></mk-input>
|
|
||||||
<mk-select v-if="select" v-model="selectedValue" autofocus>
|
|
||||||
<template v-if="select.items">
|
<template v-if="select.items">
|
||||||
<option v-for="item in select.items" :value="item.value">{{ item.text }}</option>
|
<option v-for="item in select.items" :value="item.value">{{ item.text }}</option>
|
||||||
</template>
|
</template>
|
||||||
@ -34,36 +24,33 @@
|
|||||||
<option v-for="item in groupedItem.items" :value="item.value">{{ item.text }}</option>
|
<option v-for="item in groupedItem.items" :value="item.value">{{ item.text }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</template>
|
</template>
|
||||||
</mk-select>
|
</MkSelect>
|
||||||
<div class="buttons" v-if="!iconOnly && (showOkButton || showCancelButton) && !actions">
|
<div class="buttons" v-if="(showOkButton || showCancelButton) && !actions">
|
||||||
<mk-button inline @click="ok" v-if="showOkButton" primary :autofocus="!input && !select && !user" :disabled="!canOk">{{ (showCancelButton || input || select || user) ? $t('ok') : $t('gotIt') }}</mk-button>
|
<MkButton inline @click="ok" v-if="showOkButton" primary :autofocus="!input && !select">{{ (showCancelButton || input || select) ? $t('ok') : $t('gotIt') }}</MkButton>
|
||||||
<mk-button inline @click="cancel" v-if="showCancelButton || input || select || user">{{ $t('cancel') }}</mk-button>
|
<MkButton inline @click="cancel" v-if="showCancelButton || input || select">{{ $t('cancel') }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons" v-if="actions">
|
<div class="buttons" v-if="actions">
|
||||||
<mk-button v-for="action in actions" inline @click="() => { action.callback(); close(); }" :primary="action.primary" :key="action.text">{{ action.text }}</mk-button>
|
<MkButton v-for="action in actions" inline @click="() => { action.callback(); close(); }" :primary="action.primary" :key="action.text">{{ action.text }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
</div>
|
||||||
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faSpinner, faInfoCircle, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons';
|
import { faSpinner, faInfoCircle, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faTimesCircle, faQuestionCircle } from '@fortawesome/free-regular-svg-icons';
|
import { faTimesCircle, faQuestionCircle } from '@fortawesome/free-regular-svg-icons';
|
||||||
import MkButton from './ui/button.vue';
|
import MkModal from '@/components/ui/modal.vue';
|
||||||
import MkInput from './ui/input.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import MkSelect from './ui/select.vue';
|
import MkInput from '@/components/ui/input.vue';
|
||||||
import MkSignin from './signin.vue';
|
import MkSelect from '@/components/ui/select.vue';
|
||||||
import parseAcct from '../../misc/acct/parse';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
MkModal,
|
||||||
MkButton,
|
MkButton,
|
||||||
MkInput,
|
MkInput,
|
||||||
MkSelect,
|
MkSelect,
|
||||||
MkSignin,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -86,9 +73,6 @@ export default Vue.extend({
|
|||||||
select: {
|
select: {
|
||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
user: {
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
icon: {
|
icon: {
|
||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
@ -107,87 +91,44 @@ export default Vue.extend({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
iconOnly: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
autoClose: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['done', 'closed'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: true,
|
|
||||||
inputValue: this.input && this.input.default ? this.input.default : null,
|
inputValue: this.input && this.input.default ? this.input.default : null,
|
||||||
userInputValue: null,
|
|
||||||
selectedValue: this.select ? this.select.default ? this.select.default : this.select.items ? this.select.items[0].value : this.select.groupedItems[0].items[0].value : null,
|
selectedValue: this.select ? this.select.default ? this.select.default : this.select.items ? this.select.items[0].value : this.select.groupedItems[0].items[0].value : null,
|
||||||
canOk: true,
|
|
||||||
faTimesCircle, faQuestionCircle, faSpinner, faInfoCircle, faExclamationTriangle, faCheck
|
faTimesCircle, faQuestionCircle, faSpinner, faInfoCircle, faExclamationTriangle, faCheck
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
|
||||||
userInputValue() {
|
|
||||||
if (this.user) {
|
|
||||||
this.$root.api('users/show', parseAcct(this.userInputValue)).then(u => {
|
|
||||||
this.canOk = u != null;
|
|
||||||
}).catch(() => {
|
|
||||||
this.canOk = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.user) this.canOk = false;
|
|
||||||
|
|
||||||
if (this.autoClose) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.close();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('keydown', this.onKeydown);
|
document.addEventListener('keydown', this.onKeydown);
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
document.removeEventListener('keydown', this.onKeydown);
|
document.removeEventListener('keydown', this.onKeydown);
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
done(canceled, result?) {
|
||||||
|
this.$emit('done', { canceled, result });
|
||||||
|
this.$refs.modal.close();
|
||||||
|
},
|
||||||
|
|
||||||
async ok() {
|
async ok() {
|
||||||
if (!this.canOk) return;
|
|
||||||
if (!this.showOkButton) return;
|
if (!this.showOkButton) return;
|
||||||
|
|
||||||
if (this.user) {
|
|
||||||
const user = await this.$root.api('users/show', parseAcct(this.userInputValue));
|
|
||||||
if (user) {
|
|
||||||
this.$emit('ok', user);
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const result =
|
const result =
|
||||||
this.input ? this.inputValue :
|
this.input ? this.inputValue :
|
||||||
this.select ? this.selectedValue :
|
this.select ? this.selectedValue :
|
||||||
true;
|
true;
|
||||||
this.$emit('ok', result);
|
this.done(false, result);
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.$emit('cancel');
|
this.done(true);
|
||||||
this.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
close() {
|
|
||||||
if (!this.show) return;
|
|
||||||
this.show = false;
|
|
||||||
this.$el.style.pointerEvents = 'none';
|
|
||||||
(this.$refs.bg as any).style.pointerEvents = 'none';
|
|
||||||
(this.$refs.main as any).style.pointerEvents = 'none';
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onBgClick() {
|
onBgClick() {
|
||||||
@ -214,46 +155,12 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.dialog-enter-active, .dialog-leave-active {
|
|
||||||
transition: opacity 0.3s, transform 0.3s !important;
|
|
||||||
}
|
|
||||||
.dialog-enter, .dialog-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-fade-enter-active, .bg-fade-leave-active {
|
|
||||||
transition: opacity 0.3s !important;
|
|
||||||
}
|
|
||||||
.bg-fade-enter, .bg-fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mk-dialog {
|
.mk-dialog {
|
||||||
display: flex;
|
position: relative;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 30000;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
&.iconOnly > .main {
|
|
||||||
min-width: 0;
|
|
||||||
width: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .main {
|
|
||||||
display: block;
|
|
||||||
position: fixed;
|
|
||||||
margin: auto;
|
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: calc(100% - 32px);
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
@ -305,5 +212,4 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,41 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="zdjebgpv" :class="{ detail }" ref="thumbnail" :style="`background-color: ${ background }`">
|
<div class="zdjebgpv" ref="thumbnail">
|
||||||
<img
|
<ImgWithBlurhash v-if="isThumbnailAvailable" :hash="file.blurhash" :src="file.thumbnailUrl" :alt="file.name" :title="file.name" :style="`object-fit: ${ fit }`"/>
|
||||||
:src="file.url"
|
<Fa :icon="faFileImage" class="icon" v-else-if="is === 'image'"/>
|
||||||
:alt="file.name"
|
<Fa :icon="faFileVideo" class="icon" v-else-if="is === 'video'"/>
|
||||||
:title="file.name"
|
<Fa :icon="faMusic" class="icon" v-else-if="is === 'audio' || is === 'midi'"/>
|
||||||
@load="onThumbnailLoaded"
|
<Fa :icon="faFileCsv" class="icon" v-else-if="is === 'csv'"/>
|
||||||
v-if="detail && is === 'image'"/>
|
<Fa :icon="faFilePdf" class="icon" v-else-if="is === 'pdf'"/>
|
||||||
<video
|
<Fa :icon="faFileAlt" class="icon" v-else-if="is === 'textfile'"/>
|
||||||
:src="file.url"
|
<Fa :icon="faFileArchive" class="icon" v-else-if="is === 'archive'"/>
|
||||||
ref="volumectrl"
|
<Fa :icon="faFile" class="icon" v-else/>
|
||||||
preload="metadata"
|
<Fa :icon="faFilm" class="icon-sub" v-if="isThumbnailAvailable && is === 'video'"/>
|
||||||
controls
|
|
||||||
v-else-if="detail && is === 'video'"/>
|
|
||||||
<img :src="file.thumbnailUrl" @load="onThumbnailLoaded" :style="`object-fit: ${ fit }`" v-else-if="isThumbnailAvailable"/>
|
|
||||||
<fa :icon="faFileImage" class="icon" v-else-if="is === 'image'"/>
|
|
||||||
<fa :icon="faFileVideo" class="icon" v-else-if="is === 'video'"/>
|
|
||||||
|
|
||||||
<audio
|
|
||||||
:src="file.url"
|
|
||||||
ref="volumectrl"
|
|
||||||
preload="metadata"
|
|
||||||
controls
|
|
||||||
v-else-if="detail && is === 'audio'"/>
|
|
||||||
<fa :icon="faMusic" class="icon" v-else-if="is === 'audio' || is === 'midi'"/>
|
|
||||||
|
|
||||||
<fa :icon="faFileCsv" class="icon" v-else-if="is === 'csv'"/>
|
|
||||||
<fa :icon="faFilePdf" class="icon" v-else-if="is === 'pdf'"/>
|
|
||||||
<fa :icon="faFileAlt" class="icon" v-else-if="is === 'textfile'"/>
|
|
||||||
<fa :icon="faFileArchive" class="icon" v-else-if="is === 'archive'"/>
|
|
||||||
<fa :icon="faFile" class="icon" v-else/>
|
|
||||||
|
|
||||||
<fa :icon="faFilm" class="icon-sub" v-if="!detail && isThumbnailAvailable && is === 'video'"/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import {
|
import {
|
||||||
faFile,
|
faFile,
|
||||||
faFileAlt,
|
faFileAlt,
|
||||||
@ -47,8 +26,12 @@ import {
|
|||||||
faFileArchive,
|
faFileArchive,
|
||||||
faFilm
|
faFilm
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import ImgWithBlurhash from './img-with-blurhash.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
ImgWithBlurhash
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
file: {
|
file: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -59,11 +42,6 @@ export default Vue.extend({
|
|||||||
required: false,
|
required: false,
|
||||||
default: 'cover'
|
default: 'cover'
|
||||||
},
|
},
|
||||||
detail: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -108,20 +86,12 @@ export default Vue.extend({
|
|||||||
? (this.is === 'image' || this.is === 'video')
|
? (this.is === 'image' || this.is === 'video')
|
||||||
: false;
|
: false;
|
||||||
},
|
},
|
||||||
background(): string {
|
|
||||||
return this.file.properties.avgColor || 'transparent';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
||||||
if (audioTag) audioTag.volume = this.$store.state.device.mediaVolume;
|
if (audioTag) audioTag.volume = this.$store.state.device.mediaVolume;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onThumbnailLoaded() {
|
|
||||||
if (this.file.properties.avgColor) {
|
|
||||||
this.$refs.thumbnail.style.backgroundColor = 'transparent';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
volumechange() {
|
volumechange() {
|
||||||
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
||||||
this.$store.commit('device/set', { key: 'mediaVolume', value: audioTag.volume });
|
this.$store.commit('device/set', { key: 'mediaVolume', value: audioTag.volume });
|
||||||
@ -132,14 +102,8 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.zdjebgpv {
|
.zdjebgpv {
|
||||||
display: flex;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> img,
|
|
||||||
> .icon {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .icon-sub {
|
> .icon-sub {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
@ -153,37 +117,10 @@ export default Vue.extend({
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.detail) {
|
|
||||||
> img {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
|
pointer-events: none;
|
||||||
height: 65%;
|
height: 65%;
|
||||||
width: 65%;
|
width: 65%;
|
||||||
}
|
}
|
||||||
|
|
||||||
> video,
|
|
||||||
> audio {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.detail {
|
|
||||||
> .icon {
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
margin: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> *:not(.icon) {
|
|
||||||
max-height: 300px;
|
|
||||||
max-width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-window ref="window" :width="800" :height="500" @closed="() => { $emit('closed'); destroyDom(); }" :with-ok-button="true" :ok-button-disabled="(type === 'file') && (selected.length === 0)" @ok="ok()">
|
<XModalWindow ref="dialog"
|
||||||
|
:width="800"
|
||||||
|
:height="500"
|
||||||
|
:with-ok-button="true"
|
||||||
|
:ok-button-disabled="(type === 'file') && (selected.length === 0)"
|
||||||
|
@click="cancel()"
|
||||||
|
@close="cancel()"
|
||||||
|
@ok="ok()"
|
||||||
|
@closed="$emit('closed')"
|
||||||
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
{{ multiple ? ((type === 'file') ? $t('selectFiles') : $t('selectFolders')) : ((type === 'file') ? $t('selectFile') : $t('selectFolder')) }}
|
{{ multiple ? ((type === 'file') ? $t('selectFiles') : $t('selectFolders')) : ((type === 'file') ? $t('selectFile') : $t('selectFolder')) }}
|
||||||
<span v-if="selected.length > 0" style="margin-left: 8px; opacity: 0.5;">({{ selected.length | number }})</span>
|
<span v-if="selected.length > 0" style="margin-left: 8px; opacity: 0.5;">({{ number(selected.length) }})</span>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div>
|
||||||
<x-drive :multiple="multiple" @change-selection="onChangeSelection" :select="type"/>
|
<XDrive :multiple="multiple" @changeSelection="onChangeSelection" @selected="ok()" :select="type"/>
|
||||||
</div>
|
</div>
|
||||||
</x-window>
|
</XModalWindow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XDrive from './drive.vue';
|
import XDrive from './drive.vue';
|
||||||
import XWindow from './window.vue';
|
import XModalWindow from '@/components/ui/modal-window.vue';
|
||||||
|
import number from '@/filters/number';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XDrive,
|
XDrive,
|
||||||
XWindow,
|
XModalWindow,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -33,6 +43,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['done', 'closed'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selected: []
|
selected: []
|
||||||
@ -41,13 +53,20 @@ export default Vue.extend({
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
ok() {
|
ok() {
|
||||||
this.$emit('selected', this.selected);
|
this.$emit('done', this.selected);
|
||||||
this.$refs.window.close();
|
this.$refs.dialog.close();
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.$emit('done');
|
||||||
|
this.$refs.dialog.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
onChangeSelection(xs) {
|
onChangeSelection(xs) {
|
||||||
this.selected = xs;
|
this.selected = xs;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
number
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ncvczrfv"
|
<div class="ncvczrfv"
|
||||||
:data-is-selected="isSelected"
|
:class="{ isSelected }"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
|
@contextmenu.stop="onContextmenu"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
@dragstart="onDragstart"
|
@dragstart="onDragstart"
|
||||||
@dragend="onDragend"
|
@dragend="onDragend"
|
||||||
@ -20,7 +21,7 @@
|
|||||||
<p>{{ $t('nsfw') }}</p>
|
<p>{{ $t('nsfw') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-file-thumbnail class="thumbnail" :file="file" fit="contain"/>
|
<MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/>
|
||||||
|
|
||||||
<p class="name">
|
<p class="name">
|
||||||
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
|
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
|
||||||
@ -30,17 +31,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
|
import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
|
||||||
import copyToClipboard from '../scripts/copy-to-clipboard';
|
|
||||||
//import updateAvatar from '../api/update-avatar';
|
|
||||||
//import updateBanner from '../api/update-banner';
|
|
||||||
import XFileThumbnail from './drive-file-thumbnail.vue';
|
|
||||||
import { faDownload, faLink, faICursor, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faDownload, faLink, faICursor, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||||
|
import MkDriveFileThumbnail from './drive-file-thumbnail.vue';
|
||||||
|
import bytes from '../filters/bytes';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XFileThumbnail
|
MkDriveFileThumbnail
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -60,6 +61,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['chosen'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isDragging: false
|
isDragging: false
|
||||||
@ -72,17 +75,13 @@ export default Vue.extend({
|
|||||||
return this.$parent;
|
return this.$parent;
|
||||||
},
|
},
|
||||||
title(): string {
|
title(): string {
|
||||||
return `${this.file.name}\n${this.file.type} ${Vue.filter('bytes')(this.file.size)}`;
|
return `${this.file.name}\n${this.file.type} ${bytes(this.file.size)}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onClick(ev) {
|
getMenu() {
|
||||||
if (this.selectMode) {
|
return [{
|
||||||
this.$emit('chosen', this.file);
|
|
||||||
} else {
|
|
||||||
this.$root.menu({
|
|
||||||
items: [{
|
|
||||||
text: this.$t('rename'),
|
text: this.$t('rename'),
|
||||||
icon: faICursor,
|
icon: faICursor,
|
||||||
action: this.rename
|
action: this.rename
|
||||||
@ -104,16 +103,26 @@ export default Vue.extend({
|
|||||||
}, null, {
|
}, null, {
|
||||||
text: this.$t('delete'),
|
text: this.$t('delete'),
|
||||||
icon: faTrashAlt,
|
icon: faTrashAlt,
|
||||||
|
danger: true,
|
||||||
action: this.deleteFile
|
action: this.deleteFile
|
||||||
}],
|
}];
|
||||||
source: ev.currentTarget || ev.target,
|
},
|
||||||
});
|
|
||||||
|
onClick(ev) {
|
||||||
|
if (this.selectMode) {
|
||||||
|
this.$emit('chosen', this.file);
|
||||||
|
} else {
|
||||||
|
os.modalMenu(this.getMenu(), ev.currentTarget || ev.target);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onContextmenu(e) {
|
||||||
|
os.contextMenu(this.getMenu(), e);
|
||||||
|
},
|
||||||
|
|
||||||
onDragstart(e) {
|
onDragstart(e) {
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('mk_drive_file', JSON.stringify(this.file));
|
e.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FILE_, JSON.stringify(this.file));
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
||||||
@ -126,19 +135,8 @@ export default Vue.extend({
|
|||||||
this.browser.isDragSource = false;
|
this.browser.isDragSource = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
onThumbnailLoaded() {
|
|
||||||
if (this.file.properties.avgColor) {
|
|
||||||
anime({
|
|
||||||
targets: this.$refs.thumbnail,
|
|
||||||
backgroundColor: 'transparent', // TODO fade
|
|
||||||
duration: 100,
|
|
||||||
easing: 'linear'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
rename() {
|
rename() {
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('renameFile'),
|
title: this.$t('renameFile'),
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$t('inputNewFileName'),
|
placeholder: this.$t('inputNewFileName'),
|
||||||
@ -147,7 +145,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}).then(({ canceled, result: name }) => {
|
}).then(({ canceled, result: name }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
this.$root.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: this.file.id,
|
fileId: this.file.id,
|
||||||
name: name
|
name: name
|
||||||
});
|
});
|
||||||
@ -155,7 +153,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
toggleSensitive() {
|
toggleSensitive() {
|
||||||
this.$root.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: this.file.id,
|
fileId: this.file.id,
|
||||||
isSensitive: !this.file.isSensitive
|
isSensitive: !this.file.isSensitive
|
||||||
});
|
});
|
||||||
@ -163,18 +161,15 @@ export default Vue.extend({
|
|||||||
|
|
||||||
copyUrl() {
|
copyUrl() {
|
||||||
copyToClipboard(this.file.url);
|
copyToClipboard(this.file.url);
|
||||||
this.$root.dialog({
|
os.success();
|
||||||
type: 'success',
|
|
||||||
iconOnly: true, autoClose: true
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setAsAvatar() {
|
setAsAvatar() {
|
||||||
updateAvatar(this.$root)(this.file);
|
os.updateAvatar(this.file);
|
||||||
},
|
},
|
||||||
|
|
||||||
setAsBanner() {
|
setAsBanner() {
|
||||||
updateBanner(this.$root)(this.file);
|
os.updateBanner(this.file);
|
||||||
},
|
},
|
||||||
|
|
||||||
addApp() {
|
addApp() {
|
||||||
@ -182,17 +177,19 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async deleteFile() {
|
async deleteFile() {
|
||||||
const { canceled } = await this.$root.dialog({
|
const { canceled } = await os.dialog({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
text: this.$t('driveFileDeleteConfirm', { name: this.file.name }),
|
text: this.$t('driveFileDeleteConfirm', { name: this.file.name }),
|
||||||
showCancelButton: true
|
showCancelButton: true
|
||||||
});
|
});
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
this.$root.api('drive/files/delete', {
|
os.api('drive/files/delete', {
|
||||||
fileId: this.file.id
|
fileId: this.file.id
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
bytes
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -208,6 +205,10 @@ export default Vue.extend({
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(#000, 0.05);
|
background: rgba(#000, 0.05);
|
||||||
|
|
||||||
@ -244,7 +245,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-is-selected] {
|
&.isSelected {
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -332,7 +333,6 @@ export default Vue.extend({
|
|||||||
width: 128px;
|
width: 128px;
|
||||||
height: 128px;
|
height: 128px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
color: var(--driveFileIcon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .name {
|
> .name {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="rghtznwe"
|
<div class="rghtznwe"
|
||||||
:data-draghover="draghover"
|
:class="{ draghover }"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
@mouseover="onMouseover"
|
@mouseover="onMouseover"
|
||||||
@mouseout="onMouseout"
|
@mouseout="onMouseout"
|
||||||
@ -14,8 +14,8 @@
|
|||||||
:title="title"
|
:title="title"
|
||||||
>
|
>
|
||||||
<p class="name">
|
<p class="name">
|
||||||
<template v-if="hover"><fa :icon="faFolderOpen" fixed-width/></template>
|
<template v-if="hover"><Fa :icon="faFolderOpen" fixed-width/></template>
|
||||||
<template v-if="!hover"><fa :icon="faFolder" fixed-width/></template>
|
<template v-if="!hover"><Fa :icon="faFolder" fixed-width/></template>
|
||||||
{{ folder.name }}
|
{{ folder.name }}
|
||||||
</p>
|
</p>
|
||||||
<p class="upload" v-if="$store.state.settings.uploadFolder == folder.id">
|
<p class="upload" v-if="$store.state.settings.uploadFolder == folder.id">
|
||||||
@ -26,10 +26,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faFolder, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
|
import { faFolder, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
folder: {
|
folder: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -47,6 +48,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['chosen'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hover: false,
|
hover: false,
|
||||||
@ -91,8 +94,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isFile = e.dataTransfer.items[0].kind == 'file';
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_;
|
||||||
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
const isDriveFolder = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_;
|
||||||
|
|
||||||
if (isFile || isDriveFile || isDriveFolder) {
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
@ -121,11 +124,11 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#region ドライブのファイル
|
//#region ドライブのファイル
|
||||||
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
|
||||||
if (driveFile != null && driveFile != '') {
|
if (driveFile != null && driveFile != '') {
|
||||||
const file = JSON.parse(driveFile);
|
const file = JSON.parse(driveFile);
|
||||||
this.browser.removeFile(file.id);
|
this.browser.removeFile(file.id);
|
||||||
this.$root.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
folderId: this.folder.id
|
folderId: this.folder.id
|
||||||
});
|
});
|
||||||
@ -133,7 +136,7 @@ export default Vue.extend({
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region ドライブのフォルダ
|
//#region ドライブのフォルダ
|
||||||
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
const driveFolder = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_);
|
||||||
if (driveFolder != null && driveFolder != '') {
|
if (driveFolder != null && driveFolder != '') {
|
||||||
const folder = JSON.parse(driveFolder);
|
const folder = JSON.parse(driveFolder);
|
||||||
|
|
||||||
@ -141,7 +144,7 @@ export default Vue.extend({
|
|||||||
if (folder.id == this.folder.id) return;
|
if (folder.id == this.folder.id) return;
|
||||||
|
|
||||||
this.browser.removeFolder(folder.id);
|
this.browser.removeFolder(folder.id);
|
||||||
this.$root.api('drive/folders/update', {
|
os.api('drive/folders/update', {
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
parentId: this.folder.id
|
parentId: this.folder.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@ -149,15 +152,15 @@ export default Vue.extend({
|
|||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'detected-circular-definition':
|
case 'detected-circular-definition':
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('unableToProcess'),
|
title: this.$t('unableToProcess'),
|
||||||
text: this.$t('circularReferenceFolder')
|
text: this.$t('circularReferenceFolder')
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('error')
|
text: this.$t('somethingHappened')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -167,7 +170,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
onDragstart(e) {
|
onDragstart(e) {
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('mk_drive_folder', JSON.stringify(this.folder));
|
e.dataTransfer.setData(_DATA_TRANSFER_DRIVE_FOLDER_, JSON.stringify(this.folder));
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
|
||||||
@ -189,7 +192,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
rename() {
|
rename() {
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('renameFolder'),
|
title: this.$t('renameFolder'),
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$t('inputNewFolderName'),
|
placeholder: this.$t('inputNewFolderName'),
|
||||||
@ -197,7 +200,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}).then(({ canceled, result: name }) => {
|
}).then(({ canceled, result: name }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
this.$root.api('drive/folders/update', {
|
os.api('drive/folders/update', {
|
||||||
folderId: this.folder.id,
|
folderId: this.folder.id,
|
||||||
name: name
|
name: name
|
||||||
});
|
});
|
||||||
@ -205,7 +208,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
deleteFolder() {
|
deleteFolder() {
|
||||||
this.$root.api('drive/folders/delete', {
|
os.api('drive/folders/delete', {
|
||||||
folderId: this.folder.id
|
folderId: this.folder.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
if (this.$store.state.settings.uploadFolder === this.folder.id) {
|
if (this.$store.state.settings.uploadFolder === this.folder.id) {
|
||||||
@ -217,14 +220,14 @@ export default Vue.extend({
|
|||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch(err.id) {
|
switch(err.id) {
|
||||||
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: this.$t('unableToDelete'),
|
title: this.$t('unableToDelete'),
|
||||||
text: this.$t('hasChildFilesOrFolders')
|
text: this.$t('hasChildFilesOrFolders')
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('unableToDelete')
|
text: this.$t('unableToDelete')
|
||||||
});
|
});
|
||||||
@ -272,7 +275,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-draghover] {
|
&.draghover {
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="drylbebk"
|
<div class="drylbebk"
|
||||||
:data-draghover="draghover"
|
:class="{ draghover }"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
@dragover.prevent.stop="onDragover"
|
@dragover.prevent.stop="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
@dragleave="onDragleave"
|
@dragleave="onDragleave"
|
||||||
@drop.stop="onDrop"
|
@drop.stop="onDrop"
|
||||||
>
|
>
|
||||||
<i v-if="folder == null"><fa :icon="faCloud"/></i>
|
<i v-if="folder == null"><Fa :icon="faCloud"/></i>
|
||||||
<span>{{ folder == null ? $t('drive') : folder.name }}</span>
|
<span>{{ folder == null ? $t('drive') : folder.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faCloud } from '@fortawesome/free-solid-svg-icons';
|
import { faCloud } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
folder: {
|
folder: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -58,8 +59,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isFile = e.dataTransfer.items[0].kind == 'file';
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_;
|
||||||
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
const isDriveFolder = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_;
|
||||||
|
|
||||||
if (isFile || isDriveFile || isDriveFolder) {
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
@ -90,11 +91,11 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#region ドライブのファイル
|
//#region ドライブのファイル
|
||||||
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
|
||||||
if (driveFile != null && driveFile != '') {
|
if (driveFile != null && driveFile != '') {
|
||||||
const file = JSON.parse(driveFile);
|
const file = JSON.parse(driveFile);
|
||||||
this.browser.removeFile(file.id);
|
this.browser.removeFile(file.id);
|
||||||
this.$root.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
folderId: this.folder ? this.folder.id : null
|
folderId: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
@ -102,13 +103,13 @@ export default Vue.extend({
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region ドライブのフォルダ
|
//#region ドライブのフォルダ
|
||||||
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
const driveFolder = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_);
|
||||||
if (driveFolder != null && driveFolder != '') {
|
if (driveFolder != null && driveFolder != '') {
|
||||||
const folder = JSON.parse(driveFolder);
|
const folder = JSON.parse(driveFolder);
|
||||||
// 移動先が自分自身ならreject
|
// 移動先が自分自身ならreject
|
||||||
if (this.folder && folder.id == this.folder.id) return;
|
if (this.folder && folder.id == this.folder.id) return;
|
||||||
this.browser.removeFolder(folder.id);
|
this.browser.removeFolder(folder.id);
|
||||||
this.$root.api('drive/folders/update', {
|
os.api('drive/folders/update', {
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
parentId: this.folder ? this.folder.id : null
|
parentId: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
@ -125,7 +126,7 @@ export default Vue.extend({
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-draghover] {
|
&.draghover {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,34 +2,35 @@
|
|||||||
<div class="yfudmmck">
|
<div class="yfudmmck">
|
||||||
<nav>
|
<nav>
|
||||||
<div class="path" @contextmenu.prevent.stop="() => {}">
|
<div class="path" @contextmenu.prevent.stop="() => {}">
|
||||||
<x-nav-folder :class="{ current: folder == null }"/>
|
<XNavFolder :class="{ current: folder == null }"/>
|
||||||
<template v-for="f in hierarchyFolders">
|
<template v-for="f in hierarchyFolders">
|
||||||
<span class="separator" :key="f.id + ':separator'"><fa :icon="faAngleRight"/></span>
|
<span class="separator"><Fa :icon="faAngleRight"/></span>
|
||||||
<x-nav-folder :folder="f" :key="f.id"/>
|
<XNavFolder :folder="f"/>
|
||||||
</template>
|
</template>
|
||||||
<span class="separator" v-if="folder != null"><fa :icon="faAngleRight"/></span>
|
<span class="separator" v-if="folder != null"><Fa :icon="faAngleRight"/></span>
|
||||||
<span class="folder current" v-if="folder != null">{{ folder.name }}</span>
|
<span class="folder current" v-if="folder != null">{{ folder.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="main" :class="{ uploading: uploadings.length > 0, fetching }"
|
<div class="main _section" :class="{ uploading: uploadings.length > 0, fetching }"
|
||||||
ref="main"
|
ref="main"
|
||||||
@dragover.prevent.stop="onDragover"
|
@dragover.prevent.stop="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
@dragleave="onDragleave"
|
@dragleave="onDragleave"
|
||||||
@drop.prevent.stop="onDrop"
|
@drop.prevent.stop="onDrop"
|
||||||
|
@contextmenu="onContextmenu"
|
||||||
>
|
>
|
||||||
<div class="contents" ref="contents">
|
<div class="contents" ref="contents">
|
||||||
<div class="folders" ref="foldersContainer" v-show="folders.length > 0">
|
<div class="folders" ref="foldersContainer" v-show="folders.length > 0">
|
||||||
<x-folder v-for="f in folders" :key="f.id" class="folder" :folder="f" :select-mode="select === 'folder'" :is-selected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder"/>
|
<XFolder v-for="f in folders" :key="f.id" class="folder" :folder="f" :select-mode="select === 'folder'" :is-selected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder"/>
|
||||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||||
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
||||||
<mk-button ref="moreFolders" v-if="moreFolders">{{ $t('loadMore') }}</mk-button>
|
<MkButton ref="moreFolders" v-if="moreFolders">{{ $t('loadMore') }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="files" ref="filesContainer" v-show="files.length > 0">
|
<div class="files" ref="filesContainer" v-show="files.length > 0">
|
||||||
<x-file v-for="file in files" :key="file.id" class="file" :file="file" :select-mode="select === 'file'" :is-selected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile"/>
|
<XFile v-for="file in files" :key="file.id" class="file" :file="file" :select-mode="select === 'file'" :is-selected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile"/>
|
||||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||||
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
||||||
<mk-button ref="loadMoreFiles" @click="fetchMoreFiles" v-show="moreFiles">{{ $t('loadMore') }}</mk-button>
|
<MkButton ref="loadMoreFiles" @click="fetchMoreFiles" v-show="moreFiles">{{ $t('loadMore') }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching">
|
<div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching">
|
||||||
<p v-if="draghover">{{ $t('empty-draghover') }}</p>
|
<p v-if="draghover">{{ $t('empty-draghover') }}</p>
|
||||||
@ -37,29 +38,28 @@
|
|||||||
<p v-if="!draghover && folder != null">{{ $t('emptyFolder') }}</p>
|
<p v-if="!draghover && folder != null">{{ $t('emptyFolder') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mk-loading v-if="fetching"/>
|
<MkLoading v-if="fetching"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropzone" v-if="draghover"></div>
|
<div class="dropzone" v-if="draghover"></div>
|
||||||
<x-uploader ref="uploader" @change="onChangeUploaderUploads" @uploaded="onUploaderUploaded"/>
|
|
||||||
<input ref="fileInput" type="file" accept="*/*" multiple="multiple" tabindex="-1" @change="onChangeFileInput"/>
|
<input ref="fileInput" type="file" accept="*/*" multiple="multiple" tabindex="-1" @change="onChangeFileInput"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faAngleRight } from '@fortawesome/free-solid-svg-icons';
|
import { faAngleRight, faFolderPlus, faICursor, faLink, faUpload } from '@fortawesome/free-solid-svg-icons';
|
||||||
import XNavFolder from './drive.nav-folder.vue';
|
import XNavFolder from './drive.nav-folder.vue';
|
||||||
import XFolder from './drive.folder.vue';
|
import XFolder from './drive.folder.vue';
|
||||||
import XFile from './drive.file.vue';
|
import XFile from './drive.file.vue';
|
||||||
import XUploader from './uploader.vue';
|
|
||||||
import MkButton from './ui/button.vue';
|
import MkButton from './ui/button.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XNavFolder,
|
XNavFolder,
|
||||||
XFolder,
|
XFolder,
|
||||||
XFile,
|
XFile,
|
||||||
XUploader,
|
|
||||||
MkButton,
|
MkButton,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -85,6 +85,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['selected', 'change-selection', 'move-root', 'cd', 'open-folder'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
@ -100,7 +102,7 @@ export default Vue.extend({
|
|||||||
hierarchyFolders: [],
|
hierarchyFolders: [],
|
||||||
selectedFiles: [],
|
selectedFiles: [],
|
||||||
selectedFolders: [],
|
selectedFolders: [],
|
||||||
uploadings: [],
|
uploadings: os.uploads,
|
||||||
connection: null,
|
connection: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,7 +142,7 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connection = this.$root.stream.useSharedConnection('drive');
|
this.connection = os.stream.useSharedConnection('drive');
|
||||||
|
|
||||||
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
|
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
|
||||||
this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
|
this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
|
||||||
@ -164,7 +166,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.connection.dispose();
|
this.connection.dispose();
|
||||||
this.ilFilesObserver.disconnect();
|
this.ilFilesObserver.disconnect();
|
||||||
},
|
},
|
||||||
@ -204,14 +206,6 @@ export default Vue.extend({
|
|||||||
this.removeFolder(folderId);
|
this.removeFolder(folderId);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChangeUploaderUploads(uploads) {
|
|
||||||
this.uploadings = uploads;
|
|
||||||
},
|
|
||||||
|
|
||||||
onUploaderUploaded(file) {
|
|
||||||
this.addFile(file, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onDragover(e): any {
|
onDragover(e): any {
|
||||||
// ドラッグ元が自分自身の所有するアイテムだったら
|
// ドラッグ元が自分自身の所有するアイテムだったら
|
||||||
if (this.isDragSource) {
|
if (this.isDragSource) {
|
||||||
@ -221,8 +215,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isFile = e.dataTransfer.items[0].kind == 'file';
|
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||||
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_;
|
||||||
const isDriveFolder = e.dataTransfer.types[0] == 'mk_drive_folder';
|
const isDriveFolder = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FOLDER_;
|
||||||
|
|
||||||
if (isFile || isDriveFile || isDriveFolder) {
|
if (isFile || isDriveFile || isDriveFolder) {
|
||||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||||
@ -253,12 +247,12 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#region ドライブのファイル
|
//#region ドライブのファイル
|
||||||
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
|
||||||
if (driveFile != null && driveFile != '') {
|
if (driveFile != null && driveFile != '') {
|
||||||
const file = JSON.parse(driveFile);
|
const file = JSON.parse(driveFile);
|
||||||
if (this.files.some(f => f.id == file.id)) return;
|
if (this.files.some(f => f.id == file.id)) return;
|
||||||
this.removeFile(file.id);
|
this.removeFile(file.id);
|
||||||
this.$root.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
folderId: this.folder ? this.folder.id : null
|
folderId: this.folder ? this.folder.id : null
|
||||||
});
|
});
|
||||||
@ -266,7 +260,7 @@ export default Vue.extend({
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region ドライブのフォルダ
|
//#region ドライブのフォルダ
|
||||||
const driveFolder = e.dataTransfer.getData('mk_drive_folder');
|
const driveFolder = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_);
|
||||||
if (driveFolder != null && driveFolder != '') {
|
if (driveFolder != null && driveFolder != '') {
|
||||||
const folder = JSON.parse(driveFolder);
|
const folder = JSON.parse(driveFolder);
|
||||||
|
|
||||||
@ -274,7 +268,7 @@ export default Vue.extend({
|
|||||||
if (this.folder && folder.id == this.folder.id) return false;
|
if (this.folder && folder.id == this.folder.id) return false;
|
||||||
if (this.folders.some(f => f.id == folder.id)) return false;
|
if (this.folders.some(f => f.id == folder.id)) return false;
|
||||||
this.removeFolder(folder.id);
|
this.removeFolder(folder.id);
|
||||||
this.$root.api('drive/folders/update', {
|
os.api('drive/folders/update', {
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
parentId: this.folder ? this.folder.id : null
|
parentId: this.folder ? this.folder.id : null
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@ -282,15 +276,15 @@ export default Vue.extend({
|
|||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 'detected-circular-definition':
|
case 'detected-circular-definition':
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('unableToProcess'),
|
title: this.$t('unableToProcess'),
|
||||||
text: this.$t('circularReferenceFolder')
|
text: this.$t('circularReferenceFolder')
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('error')
|
text: this.$t('somethingHappened')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -303,19 +297,19 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
urlUpload() {
|
urlUpload() {
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('uploadFromUrl'),
|
title: this.$t('uploadFromUrl'),
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$t('uploadFromUrlDescription')
|
placeholder: this.$t('uploadFromUrlDescription')
|
||||||
}
|
}
|
||||||
}).then(({ canceled, result: url }) => {
|
}).then(({ canceled, result: url }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
this.$root.api('drive/files/upload_from_url', {
|
os.api('drive/files/upload_from_url', {
|
||||||
url: url,
|
url: url,
|
||||||
folderId: this.folder ? this.folder.id : undefined
|
folderId: this.folder ? this.folder.id : undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('uploadFromUrlRequested'),
|
title: this.$t('uploadFromUrlRequested'),
|
||||||
text: this.$t('uploadFromUrlMayTakeTime')
|
text: this.$t('uploadFromUrlMayTakeTime')
|
||||||
});
|
});
|
||||||
@ -323,14 +317,14 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
createFolder() {
|
createFolder() {
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('createFolder'),
|
title: this.$t('createFolder'),
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$t('folderName')
|
placeholder: this.$t('folderName')
|
||||||
}
|
}
|
||||||
}).then(({ canceled, result: name }) => {
|
}).then(({ canceled, result: name }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
this.$root.api('drive/folders/create', {
|
os.api('drive/folders/create', {
|
||||||
name: name,
|
name: name,
|
||||||
parentId: this.folder ? this.folder.id : undefined
|
parentId: this.folder ? this.folder.id : undefined
|
||||||
}).then(folder => {
|
}).then(folder => {
|
||||||
@ -340,7 +334,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
renameFolder(folder) {
|
renameFolder(folder) {
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
title: this.$t('renameFolder'),
|
title: this.$t('renameFolder'),
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$t('inputNewFolderName'),
|
placeholder: this.$t('inputNewFolderName'),
|
||||||
@ -348,7 +342,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}).then(({ canceled, result: name }) => {
|
}).then(({ canceled, result: name }) => {
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
this.$root.api('drive/folders/update', {
|
os.api('drive/folders/update', {
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
name: name
|
name: name
|
||||||
}).then(folder => {
|
}).then(folder => {
|
||||||
@ -359,7 +353,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
deleteFolder(folder) {
|
deleteFolder(folder) {
|
||||||
this.$root.api('drive/folders/delete', {
|
os.api('drive/folders/delete', {
|
||||||
folderId: folder.id
|
folderId: folder.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// 削除時に親フォルダに移動
|
// 削除時に親フォルダに移動
|
||||||
@ -367,14 +361,14 @@ export default Vue.extend({
|
|||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
switch(err.id) {
|
switch(err.id) {
|
||||||
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: this.$t('unableToDelete'),
|
title: this.$t('unableToDelete'),
|
||||||
text: this.$t('hasChildFilesOrFolders')
|
text: this.$t('hasChildFilesOrFolders')
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.$root.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('unableToDelete')
|
text: this.$t('unableToDelete')
|
||||||
});
|
});
|
||||||
@ -390,7 +384,9 @@ export default Vue.extend({
|
|||||||
|
|
||||||
upload(file, folder) {
|
upload(file, folder) {
|
||||||
if (folder && typeof folder == 'object') folder = folder.id;
|
if (folder && typeof folder == 'object') folder = folder.id;
|
||||||
(this.$refs.uploader as any).upload(file, folder);
|
os.upload(file, folder).then(res => {
|
||||||
|
this.addFile(res, true);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
chooseFile(file) {
|
chooseFile(file) {
|
||||||
@ -441,7 +437,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
this.fetching = true;
|
this.fetching = true;
|
||||||
|
|
||||||
this.$root.api('drive/folders/show', {
|
os.api('drive/folders/show', {
|
||||||
folderId: target
|
folderId: target
|
||||||
}).then(folder => {
|
}).then(folder => {
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
@ -465,7 +461,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
if (this.folders.some(f => f.id == folder.id)) {
|
if (this.folders.some(f => f.id == folder.id)) {
|
||||||
const exist = this.folders.map(f => f.id).indexOf(folder.id);
|
const exist = this.folders.map(f => f.id).indexOf(folder.id);
|
||||||
Vue.set(this.folders, exist, folder);
|
this.folders[exist] = folder;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +478,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
if (this.files.some(f => f.id == file.id)) {
|
if (this.files.some(f => f.id == file.id)) {
|
||||||
const exist = this.files.map(f => f.id).indexOf(file.id);
|
const exist = this.files.map(f => f.id).indexOf(file.id);
|
||||||
Vue.set(this.files, exist, file);
|
this.files[exist] = file;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +539,7 @@ export default Vue.extend({
|
|||||||
const filesMax = 30;
|
const filesMax = 30;
|
||||||
|
|
||||||
// フォルダ一覧取得
|
// フォルダ一覧取得
|
||||||
this.$root.api('drive/folders', {
|
os.api('drive/folders', {
|
||||||
folderId: this.folder ? this.folder.id : null,
|
folderId: this.folder ? this.folder.id : null,
|
||||||
limit: foldersMax + 1
|
limit: foldersMax + 1
|
||||||
}).then(folders => {
|
}).then(folders => {
|
||||||
@ -556,7 +552,7 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ファイル一覧取得
|
// ファイル一覧取得
|
||||||
this.$root.api('drive/files', {
|
os.api('drive/files', {
|
||||||
folderId: this.folder ? this.folder.id : null,
|
folderId: this.folder ? this.folder.id : null,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
limit: filesMax + 1
|
limit: filesMax + 1
|
||||||
@ -587,7 +583,7 @@ export default Vue.extend({
|
|||||||
const max = 30;
|
const max = 30;
|
||||||
|
|
||||||
// ファイル一覧取得
|
// ファイル一覧取得
|
||||||
this.$root.api('drive/files', {
|
os.api('drive/files', {
|
||||||
folderId: this.folder ? this.folder.id : null,
|
folderId: this.folder ? this.folder.id : null,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
untilId: this.files[this.files.length - 1].id,
|
untilId: this.files[this.files.length - 1].id,
|
||||||
@ -602,7 +598,41 @@ export default Vue.extend({
|
|||||||
for (const x of files) this.appendFile(x);
|
for (const x of files) this.appendFile(x);
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
getMenu() {
|
||||||
|
return [{
|
||||||
|
text: this.$t('addFile'),
|
||||||
|
type: 'label'
|
||||||
|
}, {
|
||||||
|
text: this.$t('upload'),
|
||||||
|
icon: faUpload,
|
||||||
|
action: () => { this.selectLocalFile(); }
|
||||||
|
}, {
|
||||||
|
text: this.$t('fromUrl'),
|
||||||
|
icon: faLink,
|
||||||
|
action: () => { this.urlUpload(); }
|
||||||
|
}, null, {
|
||||||
|
text: this.folder ? this.folder.name : this.$t('drive'),
|
||||||
|
type: 'label'
|
||||||
|
}, this.folder ? {
|
||||||
|
text: this.$t('renameFolder'),
|
||||||
|
icon: faICursor,
|
||||||
|
action: () => { this.renameFolder(this.folder); }
|
||||||
|
} : undefined, this.folder ? {
|
||||||
|
text: this.$t('deleteFolder'),
|
||||||
|
icon: faTrashAlt,
|
||||||
|
action: () => { this.deleteFolder(this.folder); }
|
||||||
|
} : undefined, {
|
||||||
|
text: this.$t('createFolder'),
|
||||||
|
icon: faFolderPlus,
|
||||||
|
action: () => { this.createFolder(); }
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
|
||||||
|
onContextmenu(e) {
|
||||||
|
os.contextMenu(this.getMenu(), e);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -613,6 +643,8 @@ export default Vue.extend({
|
|||||||
display: block;
|
display: block;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding: 0 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
box-shadow: 0 1px 0 var(--divider);
|
box-shadow: 0 1px 0 var(--divider);
|
||||||
@ -666,7 +698,6 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .main {
|
> .main {
|
||||||
padding: 8px 0;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
&, * {
|
&, * {
|
||||||
@ -734,11 +765,6 @@ export default Vue.extend({
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .mk-uploader {
|
|
||||||
height: 100px;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> input {
|
> input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-popup :source="source" ref="popup" @closed="() => { $emit('closed'); destroyDom(); }">
|
<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
|
||||||
<div class="omfetrab">
|
<div class="omfetrab _popup">
|
||||||
<header>
|
<header>
|
||||||
<button v-for="(category, i) in categories"
|
<button v-for="(category, i) in categories"
|
||||||
class="_button"
|
class="_button"
|
||||||
@ -8,26 +8,26 @@
|
|||||||
:class="{ active: category.isActive }"
|
:class="{ active: category.isActive }"
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<fa :icon="category.icon" fixed-width/>
|
<Fa :icon="category.icon" fixed-width/>
|
||||||
</button>
|
</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="emojis">
|
<div class="emojis">
|
||||||
<template v-if="categories[0].isActive">
|
<template v-if="categories[0].isActive">
|
||||||
<header class="category"><fa :icon="faHistory" fixed-width/> {{ $t('recentUsed') }}</header>
|
<header class="category"><Fa :icon="faHistory" fixed-width/> {{ $t('recentUsed') }}</header>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<button v-for="(emoji, i) in ($store.state.device.recentEmojis || [])"
|
<button v-for="emoji in ($store.state.device.recentEmojis || [])"
|
||||||
class="_button"
|
class="_button"
|
||||||
:title="emoji.name"
|
:title="emoji.name"
|
||||||
@click="chosen(emoji)"
|
@click="chosen(emoji)"
|
||||||
:key="i"
|
:key="emoji"
|
||||||
>
|
>
|
||||||
<mk-emoji v-if="emoji.char != null" :emoji="emoji.char"/>
|
<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>
|
||||||
<img v-else :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
<img v-else :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<header class="category"><fa :icon="faAsterisk" fixed-width/> {{ $t('customEmojis') }}</header>
|
<header class="category"><Fa :icon="faAsterisk" fixed-width/> {{ $t('customEmojis') }}</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="categories.find(x => x.isActive).name">
|
<template v-if="categories.find(x => x.isActive).name">
|
||||||
@ -38,7 +38,7 @@
|
|||||||
@click="chosen(emoji)"
|
@click="chosen(emoji)"
|
||||||
:key="emoji.name"
|
:key="emoji.name"
|
||||||
>
|
>
|
||||||
<mk-emoji :emoji="emoji.char"/>
|
<MkEmoji :emoji="emoji.char"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -59,29 +59,31 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-popup>
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { emojilist } from '../../misc/emojilist';
|
import { emojilist } from '../../misc/emojilist';
|
||||||
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory, faUser } from '@fortawesome/free-solid-svg-icons';
|
import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory, faUser } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons';
|
import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { groupByX } from '../../prelude/array';
|
import { groupByX } from '../../prelude/array';
|
||||||
import XPopup from './popup.vue';
|
import MkModal from '@/components/ui/modal.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XPopup,
|
MkModal,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
source: {
|
src: {
|
||||||
required: true
|
required: false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['done', 'closed'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
emojilist,
|
emojilist,
|
||||||
@ -162,12 +164,9 @@ export default Vue.extend({
|
|||||||
recents = recents.filter((e: any) => getKey(e) !== getKey(emoji));
|
recents = recents.filter((e: any) => getKey(e) !== getKey(emoji));
|
||||||
recents.unshift(emoji)
|
recents.unshift(emoji)
|
||||||
this.$store.commit('device/set', { key: 'recentEmojis', value: recents.splice(0, 16) });
|
this.$store.commit('device/set', { key: 'recentEmojis', value: recents.splice(0, 16) });
|
||||||
this.$emit('chosen', getKey(emoji));
|
this.$emit('done', getKey(emoji));
|
||||||
|
this.$refs.modal.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
close() {
|
|
||||||
this.$refs.popup.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -186,7 +185,7 @@ export default Vue.extend({
|
|||||||
transition: color 0.2s ease;
|
transition: color 0.2s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--textHighlighted);
|
color: var(--fgHighlighted);
|
||||||
transition: color 0s;
|
transition: color 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import { twemojiSvgBase } from '../../misc/twemoji-base';
|
import { twemojiSvgBase } from '../../misc/twemoji-base';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition :name="$store.state.device.animation ? 'zoom' : ''" appear>
|
<transition :name="$store.state.device.animation ? 'zoom' : ''" appear>
|
||||||
<div class="mjndxjcg _panel">
|
<div class="mjndxjcg">
|
||||||
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/>
|
||||||
<p><fa :icon="faExclamationTriangle"/> {{ $t('error') }}</p>
|
<p><Fa :icon="faExclamationTriangle"/> {{ $t('somethingHappened') }}</p>
|
||||||
<mk-button @click="() => $emit('retry')" class="button">{{ $t('retry') }}</mk-button>
|
<MkButton @click="() => $emit('retry')" class="button">{{ $t('retry') }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from './ui/button.vue';
|
import MkButton from './ui/button.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
MkButton,
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="mk-file-type-icon">
|
<span class="mk-file-type-icon">
|
||||||
<template v-if="kind == 'image'"><fa :icon="faFileImage"/></template>
|
<template v-if="kind == 'image'"><Fa :icon="faFileImage"/></template>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faFileImage } from '@fortawesome/free-solid-svg-icons';
|
import { faFileImage } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -7,32 +7,33 @@
|
|||||||
>
|
>
|
||||||
<template v-if="!wait">
|
<template v-if="!wait">
|
||||||
<template v-if="hasPendingFollowRequestFromYou && user.isLocked">
|
<template v-if="hasPendingFollowRequestFromYou && user.isLocked">
|
||||||
<span v-if="full">{{ $t('followRequestPending') }}</span><fa :icon="faHourglassHalf"/>
|
<span v-if="full">{{ $t('followRequestPending') }}</span><Fa :icon="faHourglassHalf"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"> <!-- つまりリモートフォローの場合。 -->
|
<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"> <!-- つまりリモートフォローの場合。 -->
|
||||||
<span v-if="full">{{ $t('processing') }}</span><fa :icon="faSpinner" pulse/>
|
<span v-if="full">{{ $t('processing') }}</span><Fa :icon="faSpinner" pulse/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="isFollowing">
|
<template v-else-if="isFollowing">
|
||||||
<span v-if="full">{{ $t('unfollow') }}</span><fa :icon="faMinus"/>
|
<span v-if="full">{{ $t('unfollow') }}</span><Fa :icon="faMinus"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!isFollowing && user.isLocked">
|
<template v-else-if="!isFollowing && user.isLocked">
|
||||||
<span v-if="full">{{ $t('followRequest') }}</span><fa :icon="faPlus"/>
|
<span v-if="full">{{ $t('followRequest') }}</span><Fa :icon="faPlus"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!isFollowing && !user.isLocked">
|
<template v-else-if="!isFollowing && !user.isLocked">
|
||||||
<span v-if="full">{{ $t('follow') }}</span><fa :icon="faPlus"/>
|
<span v-if="full">{{ $t('follow') }}</span><Fa :icon="faPlus"/>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span v-if="full">{{ $t('processing') }}</span><fa :icon="faSpinner" pulse fixed-width/>
|
<span v-if="full">{{ $t('processing') }}</span><Fa :icon="faSpinner" pulse fixed-width/>
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons';
|
import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
user: {
|
user: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -58,7 +59,7 @@ export default Vue.extend({
|
|||||||
created() {
|
created() {
|
||||||
// 渡されたユーザー情報が不完全な場合
|
// 渡されたユーザー情報が不完全な場合
|
||||||
if (this.user.isFollowing == null) {
|
if (this.user.isFollowing == null) {
|
||||||
this.$root.api('users/show', {
|
os.api('users/show', {
|
||||||
userId: this.user.id
|
userId: this.user.id
|
||||||
}).then(u => {
|
}).then(u => {
|
||||||
this.isFollowing = u.isFollowing;
|
this.isFollowing = u.isFollowing;
|
||||||
@ -68,13 +69,13 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
this.connection = os.stream.useSharedConnection('main');
|
||||||
|
|
||||||
this.connection.on('follow', this.onFollowChange);
|
this.connection.on('follow', this.onFollowChange);
|
||||||
this.connection.on('unfollow', this.onFollowChange);
|
this.connection.on('unfollow', this.onFollowChange);
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.connection.dispose();
|
this.connection.dispose();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.isFollowing) {
|
if (this.isFollowing) {
|
||||||
const { canceled } = await this.$root.dialog({
|
const { canceled } = await os.dialog({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
text: this.$t('unfollowConfirm', { name: this.user.name || this.user.username }),
|
text: this.$t('unfollowConfirm', { name: this.user.name || this.user.username }),
|
||||||
showCancelButton: true
|
showCancelButton: true
|
||||||
@ -99,21 +100,21 @@ export default Vue.extend({
|
|||||||
|
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
|
|
||||||
await this.$root.api('following/delete', {
|
await os.api('following/delete', {
|
||||||
userId: this.user.id
|
userId: this.user.id
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (this.hasPendingFollowRequestFromYou) {
|
if (this.hasPendingFollowRequestFromYou) {
|
||||||
await this.$root.api('following/requests/cancel', {
|
await os.api('following/requests/cancel', {
|
||||||
userId: this.user.id
|
userId: this.user.id
|
||||||
});
|
});
|
||||||
} else if (this.user.isLocked) {
|
} else if (this.user.isLocked) {
|
||||||
await this.$root.api('following/create', {
|
await os.api('following/create', {
|
||||||
userId: this.user.id
|
userId: this.user.id
|
||||||
});
|
});
|
||||||
this.hasPendingFollowRequestFromYou = true;
|
this.hasPendingFollowRequestFromYou = true;
|
||||||
} else {
|
} else {
|
||||||
await this.$root.api('following/create', {
|
await os.api('following/create', {
|
||||||
userId: this.user.id
|
userId: this.user.id
|
||||||
});
|
});
|
||||||
this.hasPendingFollowRequestFromYou = true;
|
this.hasPendingFollowRequestFromYou = true;
|
||||||
|
106
src/client/components/form-dialog.vue
Normal file
106
src/client/components/form-dialog.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<XModalWindow ref="dialog"
|
||||||
|
:width="400"
|
||||||
|
:can-close="false"
|
||||||
|
:with-ok-button="true"
|
||||||
|
:ok-button-disabled="false"
|
||||||
|
@click="cancel()"
|
||||||
|
@ok="ok()"
|
||||||
|
@close="cancel()"
|
||||||
|
@closed="$emit('closed')"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
{{ title }}
|
||||||
|
</template>
|
||||||
|
<div class="xkpnjxcv _section">
|
||||||
|
<label v-for="item in Object.keys(form).filter(item => !form[item].hidden)" :key="item">
|
||||||
|
<MkInput v-if="form[item].type === 'number'" v-model:value="values[item]" type="number" :step="form[item].step || 1">
|
||||||
|
<span v-text="form[item].label || item"></span>
|
||||||
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
|
</MkInput>
|
||||||
|
<MkInput v-else-if="form[item].type === 'string' && !item.multiline" v-model:value="values[item]" type="text">
|
||||||
|
<span v-text="form[item].label || item"></span>
|
||||||
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
|
</MkInput>
|
||||||
|
<MkTextarea v-else-if="form[item].type === 'string' && item.multiline" v-model:value="values[item]">
|
||||||
|
<span v-text="form[item].label || item"></span>
|
||||||
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
|
</MkTextarea>
|
||||||
|
<MkSwitch v-else-if="form[item].type === 'boolean'" v-model:value="values[item]">
|
||||||
|
<span v-text="form[item].label || item"></span>
|
||||||
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</XModalWindow>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import XModalWindow from '@/components/ui/modal-window.vue';
|
||||||
|
import MkInput from './ui/input.vue';
|
||||||
|
import MkTextarea from './ui/textarea.vue';
|
||||||
|
import MkSwitch from './ui/switch.vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
XModalWindow,
|
||||||
|
MkInput,
|
||||||
|
MkTextarea,
|
||||||
|
MkSwitch,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['done'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
values: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
for (const item in this.form) {
|
||||||
|
this.values[item] = this.form[item].hasOwnProperty('default') ? this.form[item].default : null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
ok() {
|
||||||
|
this.$emit('done', {
|
||||||
|
result: this.values
|
||||||
|
});
|
||||||
|
this.$refs.dialog.close();
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.$emit('done', {
|
||||||
|
canceled: true
|
||||||
|
});
|
||||||
|
this.$refs.dialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xkpnjxcv {
|
||||||
|
> label {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,71 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-window ref="window" :width="400" :height="450" :no-padding="true" @closed="() => { $emit('closed'); destroyDom(); }" :with-ok-button="true" :ok-button-disabled="false" @ok="ok()" :can-close="false">
|
|
||||||
<template #header>
|
|
||||||
{{ title }}
|
|
||||||
</template>
|
|
||||||
<div class="xkpnjxcv">
|
|
||||||
<label v-for="item in Object.keys(form).filter(item => !form[item].hidden)" :key="item">
|
|
||||||
<mk-input v-if="form[item].type === 'number'" v-model="values[item]" type="number" :step="form[item].step || 1"><span v-text="form[item].label || item"></span></mk-input>
|
|
||||||
<mk-input v-else-if="form[item].type === 'string' && !item.multiline" v-model="values[item]" type="text"><span v-text="form[item].label || item"></span></mk-input>
|
|
||||||
<mk-textarea v-else-if="form[item].type === 'string' && item.multiline" v-model="values[item]"><span v-text="form[item].label || item"></span></mk-textarea>
|
|
||||||
<mk-switch v-else-if="form[item].type === 'boolean'" v-model="values[item]"><span v-text="form[item].label || item"></span></mk-switch>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</x-window>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import XWindow from './window.vue';
|
|
||||||
import MkInput from './ui/input.vue';
|
|
||||||
import MkTextarea from './ui/textarea.vue';
|
|
||||||
import MkSwitch from './ui/switch.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
XWindow,
|
|
||||||
MkInput,
|
|
||||||
MkTextarea,
|
|
||||||
MkSwitch,
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
values: {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
for (const item in this.form) {
|
|
||||||
Vue.set(this.values, item, this.form[item].default || null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
ok() {
|
|
||||||
this.$emit('ok', this.values);
|
|
||||||
this.$refs.window.close();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.xkpnjxcv {
|
|
||||||
> label {
|
|
||||||
display: block;
|
|
||||||
padding: 16px 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -5,9 +5,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import * as katex from 'katex';
|
import * as katex from 'katex';import * as os from '@/os';
|
||||||
export default Vue.extend({
|
|
||||||
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
formula: {
|
formula: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-formula :formula="formula" :block="block" />
|
<XFormula :formula="formula" :block="block" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent, defineAsyncComponent } from 'vue';import * as os from '@/os';
|
||||||
export default Vue.extend({
|
|
||||||
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XFormula: () => import('./formula-core.vue').then(m => m.default)
|
XFormula: defineAsyncComponent(() => import('./formula-core.vue'))
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
formula: {
|
formula: {
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-google">
|
<div class="mk-google">
|
||||||
<input type="search" v-model="query" :placeholder="q">
|
<input type="search" v-model="query" :placeholder="q">
|
||||||
<button @click="search"><fa :icon="faSearch"/> {{ $t('search') }}</button>
|
<button @click="search"><Fa :icon="faSearch"/> {{ $t('search') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faSearch } from '@fortawesome/free-solid-svg-icons';
|
import { faSearch } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
props: ['q'],
|
props: ['q'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -23,7 +24,7 @@ export default Vue.extend({
|
|||||||
methods: {
|
methods: {
|
||||||
search() {
|
search() {
|
||||||
const engine = this.$store.state.settings.webSearchEngine ||
|
const engine = this.$store.state.settings.webSearchEngine ||
|
||||||
'https://www.google.com/?#q={{query}}';
|
'https://www.google.com/search?q={{query}}';
|
||||||
const url = engine.replace('{{query}}', this.query)
|
const url = engine.replace('{{query}}', this.query)
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
}
|
}
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="eqryymyo">
|
|
||||||
<div class="header">
|
|
||||||
<time ref="time" class="_ghost">
|
|
||||||
<span class="yyyymmdd">{{ yyyy }}/{{ mm }}/{{ dd }}</span>
|
|
||||||
<br>
|
|
||||||
<span class="hhnn">{{ hh }}<span :style="{ visibility: now.getSeconds() % 2 == 0 ? 'visible' : 'hidden' }">:</span>{{ nn }}</span>
|
|
||||||
</time>
|
|
||||||
</div>
|
|
||||||
<div class="content _panel _ghost">
|
|
||||||
<mk-clock/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import MkClock from './analog-clock.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: {
|
|
||||||
MkClock
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
now: new Date(),
|
|
||||||
clock: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
yyyy(): number {
|
|
||||||
return this.now.getFullYear();
|
|
||||||
},
|
|
||||||
mm(): string {
|
|
||||||
return ('0' + (this.now.getMonth() + 1)).slice(-2);
|
|
||||||
},
|
|
||||||
dd(): string {
|
|
||||||
return ('0' + this.now.getDate()).slice(-2);
|
|
||||||
},
|
|
||||||
hh(): string {
|
|
||||||
return ('0' + this.now.getHours()).slice(-2);
|
|
||||||
},
|
|
||||||
nn(): string {
|
|
||||||
return ('0' + this.now.getMinutes()).slice(-2);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.tick();
|
|
||||||
this.clock = setInterval(this.tick, 1000);
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
clearInterval(this.clock);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
tick() {
|
|
||||||
this.now = new Date();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.eqryymyo {
|
|
||||||
display: inline-block;
|
|
||||||
overflow: visible;
|
|
||||||
|
|
||||||
> .header {
|
|
||||||
padding: 0 12px;
|
|
||||||
padding-top: 4px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: Lucida Console, Courier, monospace;
|
|
||||||
|
|
||||||
&:hover + .content {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
> time {
|
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
height: 48px;
|
|
||||||
|
|
||||||
> .yyyymmdd {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .content {
|
|
||||||
opacity: 0;
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: auto;
|
|
||||||
right: 0;
|
|
||||||
margin: 16px 0 0 0;
|
|
||||||
padding: 16px;
|
|
||||||
width: 230px;
|
|
||||||
transition: opacity 0.2s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,16 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-modal ref="modal" @closed="() => { $emit('closed'); destroyDom(); }">
|
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
|
||||||
<img class="xubzgfga" ref="img" :src="image.url" :alt="image.name" :title="image.name" @click="close" tabindex="-1"/>
|
<div class="xubzgfga">
|
||||||
</x-modal>
|
<header>{{ image.name }}</header>
|
||||||
|
<img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/>
|
||||||
|
<footer>
|
||||||
|
<span>{{ image.type }}</span>
|
||||||
|
<span>{{ bytes(image.size) }}</span>
|
||||||
|
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</MkModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XModal from './modal.vue';
|
import bytes from '@/filters/bytes';
|
||||||
|
import number from '@/filters/number';
|
||||||
|
import MkModal from '@/components/ui/modal.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XModal,
|
MkModal,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -20,32 +30,50 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
emits: ['closed'],
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.img.focus();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
bytes,
|
||||||
this.$refs.modal.close();
|
number,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.xubzgfga {
|
.xubzgfga {
|
||||||
position: fixed;
|
max-width: 1024px;
|
||||||
z-index: 2;
|
|
||||||
top: 0;
|
> header,
|
||||||
right: 0;
|
> footer {
|
||||||
bottom: 0;
|
display: inline-block;
|
||||||
left: 0;
|
padding: 6px 9px;
|
||||||
|
font-size: 90%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
> header {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
display: block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
|
||||||
margin: auto;
|
|
||||||
cursor: zoom-out;
|
cursor: zoom-out;
|
||||||
image-orientation: from-image;
|
image-orientation: from-image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> footer {
|
||||||
|
margin-top: 8px;
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
> span + span {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
border-left: solid 1px rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
98
src/client/components/img-with-blurhash.vue
Normal file
98
src/client/components/img-with-blurhash.vue
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<div class="xubzgfgb" :class="{ cover }" :title="title">
|
||||||
|
<canvas ref="canvas" :width="size" :height="size" :title="title" v-if="!loaded"/>
|
||||||
|
<img v-if="src" :src="src" :title="title" :alt="alt" @load="onLoad"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { decode } from 'blurhash';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
hash: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
alt: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 64
|
||||||
|
},
|
||||||
|
cover: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loaded: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.draw();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
draw() {
|
||||||
|
if (this.hash == null) return;
|
||||||
|
const pixels = decode(this.hash, this.size, this.size);
|
||||||
|
const ctx = (this.$refs.canvas as HTMLCanvasElement).getContext('2d');
|
||||||
|
const imageData = ctx!.createImageData(this.size, this.size);
|
||||||
|
imageData.data.set(pixels);
|
||||||
|
ctx!.putImageData(imageData, 0, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this.loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xubzgfgb {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> canvas,
|
||||||
|
> img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
> canvas {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cover {
|
||||||
|
> img {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,7 @@
|
|||||||
import Vue from 'vue';
|
import { App } from 'vue';
|
||||||
|
|
||||||
import mfm from './misskey-flavored-markdown.vue';
|
import mfm from './misskey-flavored-markdown.vue';
|
||||||
|
import a from './ui/a.vue';
|
||||||
import acct from './acct.vue';
|
import acct from './acct.vue';
|
||||||
import avatar from './avatar.vue';
|
import avatar from './avatar.vue';
|
||||||
import emoji from './emoji.vue';
|
import emoji from './emoji.vue';
|
||||||
@ -10,16 +11,17 @@ import time from './time.vue';
|
|||||||
import url from './url.vue';
|
import url from './url.vue';
|
||||||
import loading from './loading.vue';
|
import loading from './loading.vue';
|
||||||
import error from './error.vue';
|
import error from './error.vue';
|
||||||
import streamIndicator from './stream-indicator.vue';
|
|
||||||
|
|
||||||
Vue.component('mfm', mfm);
|
export default function(app: App) {
|
||||||
Vue.component('mk-acct', acct);
|
app.component('Mfm', mfm);
|
||||||
Vue.component('mk-avatar', avatar);
|
app.component('MkA', a);
|
||||||
Vue.component('mk-emoji', emoji);
|
app.component('MkAcct', acct);
|
||||||
Vue.component('mk-user-name', userName);
|
app.component('MkAvatar', avatar);
|
||||||
Vue.component('mk-ellipsis', ellipsis);
|
app.component('MkEmoji', emoji);
|
||||||
Vue.component('mk-time', time);
|
app.component('MkUserName', userName);
|
||||||
Vue.component('mk-url', url);
|
app.component('MkEllipsis', ellipsis);
|
||||||
Vue.component('mk-loading', loading);
|
app.component('MkTime', time);
|
||||||
Vue.component('mk-error', error);
|
app.component('MkUrl', url);
|
||||||
Vue.component('stream-indicator', streamIndicator);
|
app.component('MkLoading', loading);
|
||||||
|
app.component('MkError', error);
|
||||||
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user