Compare commits
188 Commits
Author | SHA1 | Date | |
---|---|---|---|
e22a296dc7 | |||
ac19ebc850 | |||
1e0060193a | |||
72271d905d | |||
8d39283d46 | |||
4364122804 | |||
3b6dbd6dc3 | |||
7c61fc37c5 | |||
f530b5237d | |||
9b9b6ade64 | |||
e184c1cdfb | |||
e0e4b43707 | |||
1d70b33894 | |||
44ea1be930 | |||
a1bf54fe16 | |||
88c57359b3 | |||
050564f717 | |||
75d59a9c9b | |||
9139c863bf | |||
84a1ec01bc | |||
36e59c5b5f | |||
5389b16c59 | |||
da3008af1c | |||
6637766554 | |||
2bc63631a4 | |||
5215721942 | |||
d02e14cb94 | |||
fa75b40dfd | |||
f32d8b7069 | |||
90e8527556 | |||
66377d3f27 | |||
c6ae93df80 | |||
55e9099091 | |||
c6ace29446 | |||
b0b885aacd | |||
3615b5d353 | |||
74c71e6283 | |||
9b07c5af05 | |||
cda1803e59 | |||
96eab7e12b | |||
916512fd47 | |||
58d3a37908 | |||
a19e252c9e | |||
63225ed0fd | |||
11cc9cbc7c | |||
36b9a0d42f | |||
e7da10ae58 | |||
f07047d1e8 | |||
c62aff76af | |||
1c20de4e9c | |||
4903eb4a4a | |||
b5981ab544 | |||
00e1dbfdfb | |||
df69ca4d56 | |||
cb631d4abb | |||
3c351d8300 | |||
ca66acac2b | |||
9fcf94b197 | |||
aa34000f0b | |||
d3c0f3c251 | |||
bb7edfee04 | |||
caa14c70ef | |||
3a0f72867f | |||
10d72742f5 | |||
1b9f8a87d3 | |||
d4a630902d | |||
fef5ec874b | |||
f2e347fec1 | |||
cd3c2484ee | |||
6a396ef5e3 | |||
eec1af1f52 | |||
99fc77b678 | |||
8bb311df51 | |||
a77df249c2 | |||
2883bca257 | |||
dd3af6886b | |||
33bcf2d1ea | |||
795fb0eb60 | |||
9e9d378bf1 | |||
4a6b0edce6 | |||
356225af14 | |||
331305e6c7 | |||
917b9475a5 | |||
e895fc954b | |||
6d3e18a6a1 | |||
79354f4faf | |||
28f8933c3c | |||
10356b4041 | |||
6a732ab1cd | |||
47322b35ff | |||
4c6d0386b9 | |||
a448172952 | |||
244ef0cb8f | |||
cc66a1f9c7 | |||
e2183400e5 | |||
afc531bd26 | |||
02cc1891f2 | |||
09e3ddbd57 | |||
d0fff562ea | |||
8ce5366e80 | |||
bfcda7cc02 | |||
c52aeb6618 | |||
f5ebfdca61 | |||
db93838729 | |||
bb835a6e8a | |||
52feba0e3a | |||
a1076c3108 | |||
bad068b20e | |||
ec41d461c0 | |||
a826cd6845 | |||
a950b6193a | |||
2cc4de2b23 | |||
03ef6996ff | |||
d1e5def30e | |||
02fbda2154 | |||
c21694a24a | |||
cb98336b0a | |||
97d25bc6a3 | |||
b36a1a9d0e | |||
cd44ff0aaa | |||
032571c326 | |||
6b890e3f82 | |||
9998845b21 | |||
7ee4385deb | |||
695277c9eb | |||
f014a79f8d | |||
1a6d47a633 | |||
12eed8f859 | |||
549092d9aa | |||
b245393bc4 | |||
dcd43a17ba | |||
b8088dc01a | |||
8e1b90ab43 | |||
614a1d74dd | |||
9ea1ed8559 | |||
3e1e234799 | |||
62f5ecd278 | |||
27733e2119 | |||
6be127e18b | |||
4bf1c23b3c | |||
608b8bb741 | |||
ef01eec36e | |||
5dbdd0e685 | |||
5273050ab3 | |||
fae3b02e5a | |||
3489e4af1e | |||
8e9bd0bbd5 | |||
3725b5bc34 | |||
998a59aa5e | |||
86c017674a | |||
cbae87cd11 | |||
5bc1f8d468 | |||
d3a355e164 | |||
45413c9d28 | |||
082ee8836f | |||
2f5bd5e6d7 | |||
639e0137cc | |||
2f898aa037 | |||
a43a225740 | |||
833c39969b | |||
e25dea27e7 | |||
dac962580b | |||
b12bf78c6d | |||
a44b005f7c | |||
4ea65dbe41 | |||
90ba51ee9c | |||
ecf44084dc | |||
9f49c663f8 | |||
c8c9a67485 | |||
837358df66 | |||
498bc7cebe | |||
9c3a4eb947 | |||
de1ecbaef4 | |||
4eb05efa7c | |||
ffa40227ec | |||
b44e1820a2 | |||
eb461481ed | |||
92f47cc9cb | |||
f82c6f7ab4 | |||
9f32e46921 | |||
eba96282d6 | |||
dd8423fbb5 | |||
76f992906d | |||
402d6de02d | |||
43e3ce1ed5 | |||
15050018f2 | |||
71d6394bc8 | |||
1d6791e4c2 |
@ -142,6 +142,11 @@ id: 'aid'
|
|||||||
# Proxy for HTTP/HTTPS
|
# Proxy for HTTP/HTTPS
|
||||||
#proxy: http://127.0.0.1:3128
|
#proxy: http://127.0.0.1:3128
|
||||||
|
|
||||||
|
#proxyBypassHosts: [
|
||||||
|
# 'example.com',
|
||||||
|
# '192.0.2.8'
|
||||||
|
#]
|
||||||
|
|
||||||
# Proxy for SMTP/SMTPS
|
# Proxy for SMTP/SMTPS
|
||||||
#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT
|
#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT
|
||||||
#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4
|
#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4
|
||||||
|
169
CHANGELOG.md
@ -1,7 +1,174 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
12.22.0 (2020/02/23)
|
12.35.0 (2020/4/19)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* Pagesでチャートを描画できるように
|
||||||
|
* Pagesでキャンバスの画像を投稿フォームで添付できるように
|
||||||
|
* AiScriptのバージョンアップ
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* タイムラインウィジェットの数が多ければ多いほど、リアクションが多く付いて見える問題を修正
|
||||||
|
* カスタム絵文字リアクションがプレビューされない不具合を修正
|
||||||
|
|
||||||
|
12.34.0 (2020/4/17)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* Pagesでrectメソッドを追加
|
||||||
|
* AiScriptのバージョンアップ
|
||||||
|
|
||||||
|
12.33.0 (2020/4/16)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* Pagesで円を書くメソッドを追加
|
||||||
|
* AiScriptのバージョンアップ
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* PagesでAiScript変数があると編集が機能しなくなる問題を修正
|
||||||
|
|
||||||
|
12.32.0 (2020/4/16)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* Pagesで画像を描画できるように
|
||||||
|
* AiScriptのバージョンアップ
|
||||||
|
* 0以下のリアクションは送らないように
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* リアクションの修正
|
||||||
|
* Fix Media List in CW Content
|
||||||
|
|
||||||
|
12.31.0 (2020/4/14)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* プロキシの除外ホスト指定とオブジェクトストレージへの適用を除外するオプション
|
||||||
|
* AiScript
|
||||||
|
* モデレーション関連機能
|
||||||
|
* sensitiveではないメディアも非表示にできるように
|
||||||
|
* 投稿のURLプレビューポップアップを改良
|
||||||
|
* リモートのカスタム絵文字リアクションを表示できるように
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* リアクションカウントがおかしくなることがあるのを修正
|
||||||
|
|
||||||
|
12.30.0 (2020/4/11)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* リクエストライブラリをrequestからnode-fetchに変更
|
||||||
|
* オブジェクトストレージのhttpスキーマリクエストでもProxyが適用されるように
|
||||||
|
* DNSキャッシュとKeep-Alive適用箇所を増やす
|
||||||
|
* ドイツ語と中国語(繁体)を有効に
|
||||||
|
* NSFWを再度隠せるように
|
||||||
|
* Implement AiScript scratchpad (/scratchpad)
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* APのurl処理の修正
|
||||||
|
|
||||||
|
12.29.0 (2020/4/5)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* トークン系の乱数ソースではcryptoを使うように
|
||||||
|
* broadcast stream が追加され emojiAdded イベントをサポート
|
||||||
|
* APIリファレンスの高速化等
|
||||||
|
* Ability to set header image for a Page
|
||||||
|
* ログの改善
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* アプリ一覧に1回も使用していないアプリが表示されないのを修正
|
||||||
|
* admin/accounts/createで一般ユーザーがアカウントを作成し放題なのを修正
|
||||||
|
* 翻訳の未適用箇所を修正
|
||||||
|
* APIの権限設定漏れを修正
|
||||||
|
* インストール直後にアクティビティが飛んで来たりするともう初期管理者セットアップがができなくなるのを修正
|
||||||
|
* リモート投稿でurlがあればそちらをリンクするように修正
|
||||||
|
|
||||||
|
12.28.0 (2020/3/29)
|
||||||
|
-------------------
|
||||||
|
### ✨Improvements
|
||||||
|
* インストールされたアプリのページでアプリの権限を確認できるように
|
||||||
|
* API: api/meta.features.miauthを追加
|
||||||
|
MiAuthに対応しているかどうかを確認するために利用できます。
|
||||||
|
値はつねにtrueを取ります。
|
||||||
|
* インスタンス一覧でソートできるように
|
||||||
|
|
||||||
|
12.27.1 (2020/03/28)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* MiAuthのバグを修正
|
||||||
|
|
||||||
|
12.27.0 (2020/03/28)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* サードパーティーアプリケーションの認証方法にMiAuthを追加 ([Misskey API ドキュメント](https://github.com/syuilo/misskey/blob/b8088dc01a0c53b264c0697082ff5b16b06c4cda/src/docs/api.ja-JP.md#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%97%E3%81%A6%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B))
|
||||||
|
従来の、API `app/create` => `auth/session/generate` => `auth/session/userkey` を使用する方法は依然として使用可能です。
|
||||||
|
UIからアプリを作成する画面 (`/dev/apps`) は廃止されました、同等の操作を行いたい場合は API `app/create` で可能です。
|
||||||
|
MiAuthに対応しているかどうかは`api/meta.features.miauth`で確認できます(12.28.0~)。
|
||||||
|
* テーマをインポートする前にプレビューできるように
|
||||||
|
* アプリから通知を作成できるように
|
||||||
|
* インストールしたアプリを見たり削除したりできるように
|
||||||
|
|
||||||
|
12.26.0 (2020/03/25)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* ロゴが新しく
|
||||||
|
* インスタンス設定の「ユーザー」が登録の逆順で表示されるように
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* 新規登録フォームの「利用規約」のリンク色が通常の文字と同じだった問題を修正
|
||||||
|
* ダークモードの同期の問題を修正
|
||||||
|
|
||||||
|
12.25.0 (2020/03/24)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* テーマインポート機能を実装
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* 誰もフォローしていないときにタイムラインの読み込みが遅い問題を修正
|
||||||
|
|
||||||
|
|
||||||
|
12.24.2 (2020/03/22)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* ダークモードの同期を修正
|
||||||
|
|
||||||
|
12.24.1 (2020/03/22)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* SVG形式のアイコンファイルを追加
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* iOSで起動できない問題を修正
|
||||||
|
* Pages画面にタイトルがない問題を修正
|
||||||
|
|
||||||
|
12.24.0 (2020/03/22)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* クライアント設定にアカウント設定へのリンクを追加
|
||||||
|
* ダークモードの同期を強化
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* 画面が小さいとメニューがすべて見えない問題を修正
|
||||||
|
|
||||||
|
12.23.0 (2020/03/22)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
### ✨Improvements
|
||||||
|
* 削除して編集できるように
|
||||||
|
* 基底テーマ分離
|
||||||
|
* 端末がダークモードか否かでテーマを切り替えられるように
|
||||||
|
|
||||||
|
### 🐛Fixes
|
||||||
|
* ユーザー名のサジェストをアクティブであるユーザー順に表示するのがうまくいっていないのを修正
|
||||||
|
* 招待コードが発行できない問題を修正
|
||||||
|
* CIが通らない問題を修正
|
||||||
|
|
||||||
|
12.22.0 (2020/03/21)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
### ✨Improvements
|
### ✨Improvements
|
||||||
|
@ -131,6 +131,7 @@ 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/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61 " width="100"></td>
|
||||||
@ -141,6 +142,7 @@ 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/Yuzulia">YuzuRyo61 </a></td>
|
||||||
@ -156,7 +158,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<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/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>
|
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<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>
|
||||||
@ -167,9 +168,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=5827393">motcha </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>
|
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<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/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>
|
||||||
@ -180,6 +181,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<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/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>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<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=28295158">012 </a></td>
|
||||||
<td><a href="https://www.patreon.com/nijimiss">nafuchoco </a></td>
|
<td><a href="https://www.patreon.com/nijimiss">nafuchoco </a></td>
|
||||||
@ -202,7 +204,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
**Last updated:** Tue, 17 Mar 2020 18:57:08 UTC
|
**Last updated:** Fri, 03 Apr 2020 11:52:08 UTC
|
||||||
<!-- PATREON_END -->
|
<!-- PATREON_END -->
|
||||||
|
|
||||||
[backer-url]: #backers
|
[backer-url]: #backers
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.2 KiB |
27
assets/icon.svg
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<g transform="matrix(0.413372,0,0,0.469741,64.564,40.5821)">
|
||||||
|
<rect x="-156.189" y="-86.393" width="619.297" height="544.981" style="fill:rgb(27,30,31);"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.898356,0,0,0.898356,-130.722,-120.968)">
|
||||||
|
<g transform="matrix(0.5,0.866025,-0.866025,0.5,288,-166.277)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1,0,0,1,-96,166.277)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.5,-0.866025,0.866025,0.5,-96,498.831)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1,0,0,1,-95.9902,55.4086)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653ZM385.681,139.653C385.332,139.049 384.688,138.677 383.99,138.677C383.293,138.677 382.648,139.049 382.299,139.653C378.289,146.599 373.342,155.168 369.8,161.303C368.017,164.391 368.017,168.196 369.8,171.285C373.339,177.414 378.28,185.972 382.288,192.915C382.639,193.523 383.288,193.898 383.99,193.898C384.692,193.898 385.341,193.523 385.692,192.915C389.701,185.972 394.642,177.414 398.181,171.284C399.964,168.196 399.964,164.391 398.181,161.303L385.681,139.653Z" style="fill:rgb(150,208,74);"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.5,-0.866025,0.866025,0.5,-2.64322e-11,554.256)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653ZM385.681,139.653C385.332,139.049 384.688,138.677 383.99,138.677C383.293,138.677 382.648,139.049 382.299,139.653C378.289,146.599 373.342,155.168 369.8,161.303C368.017,164.391 368.017,168.196 369.8,171.285C373.339,177.414 378.28,185.972 382.288,192.915C382.639,193.523 383.288,193.898 383.99,193.898C384.692,193.898 385.341,193.523 385.692,192.915C389.701,185.972 394.642,177.414 398.181,171.284C399.964,168.196 399.964,164.391 398.181,161.303L385.681,139.653Z" style="fill:rgb(150,208,74);"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.5,0.866025,-0.866025,0.5,192,-110.851)">
|
||||||
|
<path d="M390.877,136.653C389.457,134.193 386.831,132.677 383.99,132.677C381.149,132.677 378.524,134.193 377.103,136.653C373.093,143.599 368.146,152.168 364.604,158.303C361.749,163.248 361.749,169.34 364.604,174.285C368.142,180.414 373.084,188.972 377.092,195.915C378.515,198.379 381.144,199.898 383.99,199.898C386.836,199.898 389.466,198.379 390.889,195.915C394.897,188.972 399.838,180.414 403.377,174.284C406.232,169.34 406.232,163.248 403.377,158.303C399.835,152.168 394.888,143.599 390.877,136.653ZM385.681,139.653C385.332,139.049 384.688,138.677 383.99,138.677C383.293,138.677 382.648,139.049 382.299,139.653C378.289,146.599 373.342,155.168 369.8,161.303C368.017,164.391 368.017,168.196 369.8,171.285C373.339,177.414 378.28,185.972 382.288,192.915C382.639,193.523 383.288,193.898 383.99,193.898C384.692,193.898 385.341,193.523 385.692,192.915C389.701,185.972 394.642,177.414 398.181,171.284C399.964,168.196 399.964,164.391 398.181,161.303L385.681,139.653Z" style="fill:rgb(150,208,74);"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 18 KiB |
@ -1,11 +1,12 @@
|
|||||||
---
|
---
|
||||||
_lang_: "Deutsch"
|
_lang_: "Deutsch"
|
||||||
|
introMisskey: "Willkommen! Misskey ist eine dezentralisierte Open-Source Microblogging-Platform.\nVerfasse \"Notizen\" um mitzuteilen, was gerade passiert oder um Ereignisse mit Anderen zu teilen. 📡\nMit \"Reaktionen\" kannst du außerdem schnell deine Gefühle über Notizen anderer Benutzer zum Ausdruck bringen. 👍\nLass uns eine neue Welt erforschen! 🚀"
|
||||||
monthAndDay: "{day}/{month}"
|
monthAndDay: "{day}/{month}"
|
||||||
search: "Suchen"
|
search: "Suchen"
|
||||||
notifications: "Benachrichtigungen"
|
notifications: "Benachrichtigungen"
|
||||||
username: "Benutzername"
|
username: "Benutzername"
|
||||||
password: "Passwort"
|
password: "Passwort"
|
||||||
fetchingAsApObject: "Aus Fediverse holen"
|
fetchingAsApObject: "Wird aus dem Fediverse angefragt..."
|
||||||
ok: "OK"
|
ok: "OK"
|
||||||
gotIt: "Verstanden!"
|
gotIt: "Verstanden!"
|
||||||
cancel: "Abbrechen"
|
cancel: "Abbrechen"
|
||||||
@ -16,17 +17,17 @@ noNotifications: "Keine Benachrichtigungen"
|
|||||||
instance: "Instanz"
|
instance: "Instanz"
|
||||||
settings: "Einstellungen"
|
settings: "Einstellungen"
|
||||||
profile: "Profil"
|
profile: "Profil"
|
||||||
timeline: "Zeitleiste"
|
timeline: "Chronik"
|
||||||
noAccountDescription: "Keine Selbsteinführung"
|
noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt."
|
||||||
login: "Einloggen"
|
login: "Einloggen"
|
||||||
loggingIn: "Einloggen in bearbeitung"
|
loggingIn: "Du wirst eingeloggt..."
|
||||||
logout: "Ausloggen"
|
logout: "Ausloggen"
|
||||||
signup: "Registrieren"
|
signup: "Registrieren"
|
||||||
uploading: "Upload läuft"
|
uploading: "Upload läuft"
|
||||||
save: "Speichern"
|
save: "Speichern"
|
||||||
users: "Benutzer"
|
users: "Benutzer"
|
||||||
addUser: "Benutzer hinzufügen"
|
addUser: "Benutzer hinzufügen"
|
||||||
favorite: "Favoriten"
|
favorite: "Favorit"
|
||||||
favorites: "Favoriten"
|
favorites: "Favoriten"
|
||||||
unfavorite: "Aus Favoriten entfernen"
|
unfavorite: "Aus Favoriten entfernen"
|
||||||
pin: "Anheften"
|
pin: "Anheften"
|
||||||
@ -34,14 +35,16 @@ unpin: "Lösen"
|
|||||||
copyContent: "Inhalt kopieren"
|
copyContent: "Inhalt kopieren"
|
||||||
copyLink: "Link kopieren"
|
copyLink: "Link kopieren"
|
||||||
delete: "Löschen"
|
delete: "Löschen"
|
||||||
|
deleteAndEdit: "Löschen und Bearbeiten"
|
||||||
|
deleteAndEditConfirm: "Möchtest du diese Notiz wirklich löschen und bearbeiten? Alle Reaktionen, Renotes und Antworten dieser Notiz werden verloren gehen."
|
||||||
addToList: "Zur Liste hinzufügen"
|
addToList: "Zur Liste hinzufügen"
|
||||||
sendMessage: "Nachricht senden"
|
sendMessage: "Nachricht senden"
|
||||||
copyUsername: "Benutzernamen kopieren"
|
copyUsername: "Benutzernamen kopieren"
|
||||||
reply: "Antworten"
|
reply: "Antworten"
|
||||||
loadMore: "Zeige mehr"
|
loadMore: "Mehr anzeigen"
|
||||||
youGotNewFollower: "Sie haben einen neuen Follower"
|
youGotNewFollower: "Du hast einen neuen Follower"
|
||||||
receiveFollowRequest: "Follow Request erhalten."
|
receiveFollowRequest: "Follow-Anfrage erhalten."
|
||||||
followRequestAccepted: "FollowRequestAkzeptiert"
|
followRequestAccepted: "Follow-Anfrage akzeptiert"
|
||||||
mentions: "Erwähnungen"
|
mentions: "Erwähnungen"
|
||||||
directNotes: "Direktnachrichten"
|
directNotes: "Direktnachrichten"
|
||||||
importAndExport: "Importieren und Exportieren"
|
importAndExport: "Importieren und Exportieren"
|
||||||
@ -51,39 +54,40 @@ files: "Dateien"
|
|||||||
download: "Download"
|
download: "Download"
|
||||||
driveFileDeleteConfirm: "Möchtest du die Datei \"{name}\" löschen? Die zugehörige Notiz wird ebenso verschwinden."
|
driveFileDeleteConfirm: "Möchtest du die Datei \"{name}\" löschen? Die zugehörige Notiz wird ebenso verschwinden."
|
||||||
unfollowConfirm: "Möchtest du {name} nicht mehr folgen?"
|
unfollowConfirm: "Möchtest du {name} nicht mehr folgen?"
|
||||||
|
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
||||||
|
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
||||||
lists: "Listen"
|
lists: "Listen"
|
||||||
noLists: "Keine Liste!"
|
noLists: "Du hast keine Listen"
|
||||||
note: "Notiz"
|
note: "Notiz"
|
||||||
notes: "Notizen"
|
notes: "Notizen"
|
||||||
following: "Folgen"
|
following: "Folgen"
|
||||||
followers: "Folgende"
|
followers: "Folgende"
|
||||||
followsYou: "Folgt dir"
|
followsYou: "Folgt dir"
|
||||||
createList: "Liste erstellen"
|
createList: "Liste erstellen"
|
||||||
manageLists: "Liste verwalten"
|
manageLists: "Listen verwalten"
|
||||||
error: "Ein Problem ist aufgetreten"
|
error: "Ein Problem ist aufgetreten"
|
||||||
retry: "Wiederholen"
|
retry: "Wiederholen"
|
||||||
enterListName: "Listennamen eingeben"
|
enterListName: "Listennamen eingeben"
|
||||||
privacy: "Privatsphäre"
|
privacy: "Privatsphäre"
|
||||||
makeFollowManuallyApprove: "Folgeanfragen benötigen Bestätigung"
|
makeFollowManuallyApprove: "Follow-Anfragen benötigen Bestätigung"
|
||||||
defaultNoteVisibility: "Die Standardsichtbarkeit"
|
defaultNoteVisibility: "Standardsichtbarkeit"
|
||||||
follow: "Folgen"
|
follow: "Folgen"
|
||||||
followRequest: "Follower-Anfragen"
|
followRequest: "Follow-Anfrage"
|
||||||
followRequests: "Follower-Anfragen"
|
followRequests: "Follow-Anfragen"
|
||||||
unfollow: "Nicht mehr folgen"
|
unfollow: "Nicht mehr folgen"
|
||||||
followRequestPending: "Ausstehend"
|
followRequestPending: "Ausstehende Follow-Anfrage"
|
||||||
enterEmoji: "Gib ein Emoji ein"
|
enterEmoji: "Gib ein Emoji ein"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
unrenote: "Renote zurücknehmen"
|
unrenote: "Renote zurücknehmen"
|
||||||
quote: "Zitieren"
|
quote: "Zitieren"
|
||||||
pinnedNote: "Angepinnte Notiz"
|
pinnedNote: "Angepinnte Notiz"
|
||||||
you: "Du"
|
you: "Du"
|
||||||
clickToShow: "Klicke zum den Inhalt anzusehen"
|
clickToShow: "Klicke um diesen Inhalt anzusehen"
|
||||||
sensitive: "Dieser Inhalt ist NSFW"
|
sensitive: "Dieser Inhalt ist NSFW"
|
||||||
add: "Hinzufügen"
|
add: "Hinzufügen"
|
||||||
reaction: "Reaktionen"
|
reaction: "Reaktionen"
|
||||||
reactionSettingDescription: "Weisen Sie Ihre lieblings reaktionen zu, die Sie in den Reaktionenswähler stecken möchten."
|
reactionSettingDescription: "Gib deine Lieblingsreaktionen ein, um sie der Reaktionsauswahl hinzuzufügen."
|
||||||
rememberNoteVisibility: "Notizsichtbarkeit merken"
|
rememberNoteVisibility: "Notizsichtbarkeit merken"
|
||||||
renameFile: "Datei umbenennen"
|
|
||||||
attachCancel: "Anhängen abbrechen"
|
attachCancel: "Anhängen abbrechen"
|
||||||
markAsSensitive: "Als sensitiv markieren"
|
markAsSensitive: "Als sensitiv markieren"
|
||||||
unmarkAsSensitive: "Markierung als sensitiv zurücknehmen"
|
unmarkAsSensitive: "Markierung als sensitiv zurücknehmen"
|
||||||
@ -94,40 +98,54 @@ block: "Blockieren"
|
|||||||
unblock: "Blockierung aufheben"
|
unblock: "Blockierung aufheben"
|
||||||
suspend: "Sperren"
|
suspend: "Sperren"
|
||||||
unsuspend: "Sperrung aufheben"
|
unsuspend: "Sperrung aufheben"
|
||||||
blockConfirm: "Möchtest du diesen Account wirklich blockieren?"
|
blockConfirm: "Möchtest du diesen Benutzer wirklich blockieren?"
|
||||||
unblockConfirm: "Möchtest du diese Blockierung wirklich aufheben?"
|
unblockConfirm: "Möchtest du diese Blockierung wirklich aufheben?"
|
||||||
suspendConfirm: "Möchtest du diesen Account wirklich sperren?"
|
suspendConfirm: "Möchtest du diesen Benutzer wirklich sperren?"
|
||||||
unsuspendConfirm: "Möchtest du die Sperrung dieses Accounts wirklich aufheben?"
|
unsuspendConfirm: "Möchtest du die Sperrung dieses Benutzers wirklich aufheben?"
|
||||||
selectList: "Wähle eine Liste aus"
|
selectList: "Wähle eine Liste aus"
|
||||||
customEmojis: "Benutzerdefinierte Emojis"
|
customEmojis: "Benutzerdefinierte Emojis"
|
||||||
emojiName: "Emojiname"
|
emojiName: "Emojiname"
|
||||||
emojiUrl: "Emoji-URL"
|
emojiUrl: "Emoji-URL"
|
||||||
addEmoji: "Emoji hinzufügen"
|
addEmoji: "Emoji hinzufügen"
|
||||||
|
cacheRemoteFiles: "Dateien von anderen Instanzen im Cache speichern"
|
||||||
|
cacheRemoteFilesDescription: "Wenn diese Einstellung deaktiviert ist, werden Dateien anderer Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz gespart, aber mehr Bandbreite verbraucht, da keine Vorschaubilder generiert werden."
|
||||||
flagAsBot: "Als Bot markieren"
|
flagAsBot: "Als Bot markieren"
|
||||||
flagAsCat: "Als Katze markieren"
|
flagAsCat: "Als Katze markieren"
|
||||||
autoAcceptFollowed: "Folgeanfragen automatisch akzeptieren"
|
autoAcceptFollowed: "Follow-Anfragen automatisch akzeptieren"
|
||||||
addAcount: "Benutzerkonto hinzufügen"
|
addAcount: "Benutzerkonto hinzufügen"
|
||||||
loginFailed: "Login fehlgeschlagen"
|
loginFailed: "Login fehlgeschlagen"
|
||||||
|
showOnRemote: "Auf Ursprungsinstanz ansehen"
|
||||||
general: "Allgemein"
|
general: "Allgemein"
|
||||||
wallpaper: "Hintergrund"
|
wallpaper: "Hintergrund"
|
||||||
|
setWallpaper: "Hintergrund festlegen"
|
||||||
removeWallpaper: "Hintergrund entfernen"
|
removeWallpaper: "Hintergrund entfernen"
|
||||||
searchWith: "Suche: {q}"
|
searchWith: "Suche: {q}"
|
||||||
youHaveNoLists: "Du hast keine Listen"
|
youHaveNoLists: "Du hast keine Listen"
|
||||||
followConfirm: "Möchtest du {name} wirklich folgen?"
|
followConfirm: "Möchtest du {name} wirklich folgen?"
|
||||||
|
proxyAccount: "Proxy-Benutzerkonto"
|
||||||
|
proxyAccountDescription: "Ein Proxy-Benutzerkonto ist ein Benutzerkonto, das sich für Nutzer unter bestimmten Konditionen wie ein Follower aus einer fremden Instanz verhält. Zum Beispiel wird die Aktivität eines Nutzers aus einer fremden Instanz nicht an diese Instanz übermittelt, falls es keinen Benutzer dieser Instanz gibt, der diesem Nutzer aus fremder Instanz folgt. In diesem Fall folgt stattdessen das Proxy-Benutzerkonto."
|
||||||
|
host: "Host"
|
||||||
selectUser: "Benutzer wählen"
|
selectUser: "Benutzer wählen"
|
||||||
recipient: "Empfänger"
|
recipient: "Empfänger"
|
||||||
annotation: "Anmerkung"
|
annotation: "Anmerkung"
|
||||||
federation: "Föderation"
|
federation: "Föderation"
|
||||||
instances: "Instanz"
|
instances: "Instanz"
|
||||||
|
registeredAt: "Registriert am"
|
||||||
|
latestRequestSentAt: "Letzte Anfrage gesendet am"
|
||||||
|
latestRequestReceivedAt: "Letzte Anfrage erhalten am"
|
||||||
latestStatus: "Neuester Status"
|
latestStatus: "Neuester Status"
|
||||||
storageUsage: "Speicherplatzverbrauch"
|
storageUsage: "Speicherplatzverbrauch"
|
||||||
charts: "Charts"
|
charts: "Diagramme"
|
||||||
perHour: "Pro Stunde"
|
perHour: "Pro Stunde"
|
||||||
perDay: "Pro Tag"
|
perDay: "Pro Tag"
|
||||||
|
stopActivityDelivery: "Senden von Aktivitäten einstellen"
|
||||||
blockThisInstance: "Diese Instanz blockieren"
|
blockThisInstance: "Diese Instanz blockieren"
|
||||||
|
operations: "Aktionen"
|
||||||
|
software: "Software"
|
||||||
version: "Version"
|
version: "Version"
|
||||||
metadata: "Metadaten"
|
metadata: "Metadaten"
|
||||||
withNFiles: "{n} Datei(en)"
|
withNFiles: "{n} Datei(en)"
|
||||||
|
monitor: "Beobachten"
|
||||||
jobQueue: "Job-Warteschlange"
|
jobQueue: "Job-Warteschlange"
|
||||||
cpuAndMemory: "CPU und Arbeitsspeicher"
|
cpuAndMemory: "CPU und Arbeitsspeicher"
|
||||||
network: "Netzwerk"
|
network: "Netzwerk"
|
||||||
@ -138,6 +156,7 @@ clearQueue: "Warteschlange leeren"
|
|||||||
clearQueueConfirmTitle: "Möchtest du die Warteschlange wirklich leeren?"
|
clearQueueConfirmTitle: "Möchtest du die Warteschlange wirklich leeren?"
|
||||||
clearQueueConfirmText: "Jegliche Notizen, die sich noch in der Warteschlange befinden, werden hierdurch nicht föderiert. Diese Aktion wird normalerweise NICHT benötigt."
|
clearQueueConfirmText: "Jegliche Notizen, die sich noch in der Warteschlange befinden, werden hierdurch nicht föderiert. Diese Aktion wird normalerweise NICHT benötigt."
|
||||||
clearCachedFiles: "Cache leeren"
|
clearCachedFiles: "Cache leeren"
|
||||||
|
clearCachedFilesConfirm: "Sollen alle im Cache gespeicherten Dateien von anderen Instanzen wirklich gelöscht werden?"
|
||||||
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"
|
||||||
@ -153,11 +172,18 @@ 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"
|
||||||
suspended: "Gesperrt"
|
suspended: "Gesperrt"
|
||||||
all: "Alles"
|
all: "Alles"
|
||||||
|
subscribing: "Abonnieren"
|
||||||
|
publishing: "Veröffentlichen"
|
||||||
|
notResponding: "Antwortet nicht"
|
||||||
|
instanceFollowing: "Gefolgt auf der Instanz"
|
||||||
|
instanceFollowers: "Follower der Instanz"
|
||||||
|
instanceUsers: "Benutzer dieser Instanz"
|
||||||
changePassword: "Passwort ändern"
|
changePassword: "Passwort ändern"
|
||||||
security: "Sicherheit"
|
security: "Sicherheit"
|
||||||
retypedNotMatch: "Eingaben stimmen nicht überein."
|
retypedNotMatch: "Eingaben stimmen nicht überein."
|
||||||
@ -169,44 +195,63 @@ more: "Mehr!"
|
|||||||
featured: "Hervorgehoben"
|
featured: "Hervorgehoben"
|
||||||
usernameOrUserId: "Benutzername oder Benutzer-ID"
|
usernameOrUserId: "Benutzername oder Benutzer-ID"
|
||||||
noSuchUser: "Benutzer nicht gefunden"
|
noSuchUser: "Benutzer nicht gefunden"
|
||||||
|
lookup: "Abfragen"
|
||||||
announcements: "Ankündigungen"
|
announcements: "Ankündigungen"
|
||||||
imageUrl: "Bild-URL"
|
imageUrl: "Bild-URL"
|
||||||
remove: "Löschen"
|
remove: "Löschen"
|
||||||
removed: "Erfolgreich gelöscht"
|
removed: "Erfolgreich gelöscht"
|
||||||
removeAreYouSure: "Möchtest du \"{x}\" wirklich löschen?"
|
removeAreYouSure: "Möchtest du \"{x}\" wirklich löschen?"
|
||||||
saved: "Gespeichert"
|
saved: "Gespeichert"
|
||||||
messaging: "Nachrichten"
|
messaging: "Privatnachrichten"
|
||||||
upload: "Hochladen"
|
upload: "Hochladen"
|
||||||
fromDrive: "Aus Drive"
|
fromDrive: "Aus Drive"
|
||||||
fromUrl: "Von einer URL"
|
fromUrl: "Von einer URL"
|
||||||
|
uploadFromUrl: "Von einer URL hochladen"
|
||||||
|
uploadFromUrlDescription: "URL der hochzuladenden Datei"
|
||||||
|
uploadFromUrlRequested: "Upload angefordert"
|
||||||
|
uploadFromUrlMayTakeTime: "Es kann eine Weile dauern, bis der Upload abgeschlossen ist."
|
||||||
explore: "Erkunden"
|
explore: "Erkunden"
|
||||||
games: "Misskey Spiele"
|
games: "Misskey Spiele"
|
||||||
messageRead: "Gelesen"
|
messageRead: "Gelesen"
|
||||||
recentUsedEmojis: "Kürzlich genutzte Emojis"
|
|
||||||
noMoreHistory: "Kein weiterer Verlauf vorhanden"
|
noMoreHistory: "Kein weiterer Verlauf vorhanden"
|
||||||
|
startMessaging: "Neue Privatnachricht erstellen"
|
||||||
nUsersRead: "Von {n} gelesen"
|
nUsersRead: "Von {n} gelesen"
|
||||||
agreeTo: "Ich stimme {0} zu"
|
agreeTo: "Ich stimme {0} zu"
|
||||||
tos: "Nutzungsbedingungen"
|
tos: "Nutzungsbedingungen"
|
||||||
start: "Anfangen"
|
start: "Anfangen"
|
||||||
home: "Startseite"
|
home: "Startseite"
|
||||||
|
remoteUserCaution: "Diese Informationen sind möglicherweise veraltet, da der Benutzer von einer anderen Instanz stammt."
|
||||||
activity: "Aktivität"
|
activity: "Aktivität"
|
||||||
images: "Bilder"
|
images: "Bilder"
|
||||||
birthday: "Geburtstag"
|
birthday: "Geburtstag"
|
||||||
yearsOld: "{age} Jahre alt"
|
yearsOld: "{age} Jahre alt"
|
||||||
registeredDate: "Registierdatum"
|
registeredDate: "Registrationsdatum"
|
||||||
location: "Ort"
|
location: "Ort"
|
||||||
theme: "Farbthemen"
|
theme: "Farbthemen"
|
||||||
|
themeForLightMode: "Farbthema, das im Hellmodus genutzt wird"
|
||||||
|
themeForDarkMode: "Farbthema, das im Dunkelmodus genutzt wird"
|
||||||
|
light: "Hell"
|
||||||
|
dark: "Dunkel"
|
||||||
lightThemes: "Helle Farbthemen"
|
lightThemes: "Helle Farbthemen"
|
||||||
darkThemes: "Dunkle Farbthemen"
|
darkThemes: "Dunkle Farbthemen"
|
||||||
|
syncDeviceDarkMode: "Dunkelmodus mit den Einstellungen deines Gerätes synchronisieren"
|
||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
|
fileName: "Dateiname"
|
||||||
selectFile: "Datei auswählen"
|
selectFile: "Datei auswählen"
|
||||||
selectFiles: "Dateien auswählen"
|
selectFiles: "Dateien auswählen"
|
||||||
renameFolder: "Ordner umbenennen"
|
renameFile: "Datei umbenennen"
|
||||||
|
folderName: "Ordnername"
|
||||||
createFolder: "Ordner erstellen"
|
createFolder: "Ordner erstellen"
|
||||||
|
renameFolder: "Ordner umbenennen"
|
||||||
deleteFolder: "Ordner löschen"
|
deleteFolder: "Ordner löschen"
|
||||||
addFile: "Datei hinzufügen"
|
addFile: "Datei hinzufügen"
|
||||||
emptyDrive: "Drive ist leer"
|
emptyDrive: "Drive ist leer"
|
||||||
emptyFolder: "Der Ordner ist leer"
|
emptyFolder: "Der Ordner ist leer"
|
||||||
|
unableToDelete: "Nicht löschbar"
|
||||||
|
inputNewFileName: "Gib einen neuen Dateinamen ein"
|
||||||
|
inputNewFolderName: "Gib einen neuen Ordnernamen ein"
|
||||||
|
circularReferenceFolder: "Der Zielordner ist ein Unterorder des Ordners, den du verschieben möchtest."
|
||||||
|
hasChildFilesOrFolders: "Dieser Ordner kann nicht gelöscht werden, da er nicht leer ist."
|
||||||
copyUrl: "URL kopieren"
|
copyUrl: "URL kopieren"
|
||||||
rename: "Umbenennen"
|
rename: "Umbenennen"
|
||||||
avatar: "Profilbild"
|
avatar: "Profilbild"
|
||||||
@ -215,26 +260,37 @@ nsfw: "Dieser Inhalt ist NSFW"
|
|||||||
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
|
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
|
||||||
reload: "Aktualisieren"
|
reload: "Aktualisieren"
|
||||||
doNothing: "Ignorieren"
|
doNothing: "Ignorieren"
|
||||||
|
reloadConfirm: "Möchtest du die Chronik aktualisieren?"
|
||||||
watch: "Beobachten"
|
watch: "Beobachten"
|
||||||
unwatch: "Nicht mehr beobachten"
|
unwatch: "Nicht mehr beobachten"
|
||||||
accept: "Akzeptieren"
|
accept: "Akzeptieren"
|
||||||
reject: "Ablehnen"
|
reject: "Ablehnen"
|
||||||
|
normal: "Normal"
|
||||||
instanceName: "Name der Instanz"
|
instanceName: "Name der Instanz"
|
||||||
instanceDescription: "Beschreibung der Instanz"
|
instanceDescription: "Beschreibung der Instanz"
|
||||||
maintainerName: "Betreiber"
|
maintainerName: "Betreiber"
|
||||||
maintainerEmail: "Betreiberemail"
|
maintainerEmail: "Betreiber-Email"
|
||||||
tosUrl: "URL der Nutzungsbedingungen"
|
tosUrl: "URL der Nutzungsbedingungen"
|
||||||
thisYear: "Dieses Jahr"
|
thisYear: "Dieses Jahr"
|
||||||
thisMonth: "Dieser Monat"
|
thisMonth: "Dieser Monat"
|
||||||
today: "Heute"
|
today: "Heute"
|
||||||
|
dayX: "{day}"
|
||||||
|
monthX: "{month}"
|
||||||
|
yearX: "{year}"
|
||||||
pages: "Seiten"
|
pages: "Seiten"
|
||||||
integration: "Integration"
|
integration: "Integration"
|
||||||
connectSerice: "Verbinden"
|
connectSerice: "Verbinden"
|
||||||
disconnectSerice: "Trennen"
|
disconnectSerice: "Trennen"
|
||||||
|
enableLocalTimeline: "Lokale Chronik aktivieren"
|
||||||
|
enableGlobalTimeline: "Globale Chronik aktivieren"
|
||||||
|
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
|
||||||
registration: "Registrieren"
|
registration: "Registrieren"
|
||||||
enableRegistration: "Registration neuer Benutzer erlauben"
|
enableRegistration: "Registration neuer Benutzer erlauben"
|
||||||
invite: "Einladen"
|
invite: "Einladen"
|
||||||
|
proxyRemoteFiles: "Dateien anderer Instanzen durch Proxy leiten"
|
||||||
|
proxyRemoteFilesDescription: "Wenn diese Einstellung aktiviert ist, dann werden Dateien von anderen Instanzen, welche entweder nicht lokal gespeichert sind oder durch Überschreiten des Speicherlimits gelöscht wurden, durch einen Proxy geleitet. Hierbei wird auch ein Vorschaubild generiert. \n Dies hat keinen Effekt auf den Speicherplatz des Servers."
|
||||||
driveCapacityPerLocalAccount: "Drivekapazität pro lokales Benutzerkonto"
|
driveCapacityPerLocalAccount: "Drivekapazität pro lokales Benutzerkonto"
|
||||||
|
driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer anderer Instanzen"
|
||||||
inMb: "In Megabytes"
|
inMb: "In Megabytes"
|
||||||
iconUrl: "Icon-URL"
|
iconUrl: "Icon-URL"
|
||||||
bannerUrl: "Banner-URL"
|
bannerUrl: "Banner-URL"
|
||||||
@ -243,6 +299,8 @@ pinnedUsers: "Angepinnte Benutzer"
|
|||||||
pinnedUsersDescription: "Gib einen Benutzernamen pro Zeile ein. Diese werden im \"Erkunden\" Tab angezeigt."
|
pinnedUsersDescription: "Gib einen Benutzernamen pro Zeile ein. Diese werden im \"Erkunden\" Tab angezeigt."
|
||||||
recaptcha: "reCAPTCHA"
|
recaptcha: "reCAPTCHA"
|
||||||
enableRecaptcha: "reCAPTCHA aktivieren"
|
enableRecaptcha: "reCAPTCHA aktivieren"
|
||||||
|
recaptchaSiteKey: "Site key"
|
||||||
|
recaptchaSecretKey: "Secret key"
|
||||||
antennas: "Antennen"
|
antennas: "Antennen"
|
||||||
manageAntennas: "Antennen verwalten"
|
manageAntennas: "Antennen verwalten"
|
||||||
name: "Name"
|
name: "Name"
|
||||||
@ -250,6 +308,8 @@ antennaSource: "Antennenquelle"
|
|||||||
antennaKeywords: "Schlüsselwörter, die beobachtet werden sollen"
|
antennaKeywords: "Schlüsselwörter, die beobachtet werden sollen"
|
||||||
antennaExcludeKeywords: "Schlüsselwörter, die ignoriert werden sollen"
|
antennaExcludeKeywords: "Schlüsselwörter, die ignoriert werden sollen"
|
||||||
antennaKeywordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen."
|
antennaKeywordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen."
|
||||||
|
notifyAntenna: "Über neue Notizen benachrichtigen"
|
||||||
|
withFileAntenna: "Nur Notizen mit Dateien"
|
||||||
serviceworker: "ServiceWorker"
|
serviceworker: "ServiceWorker"
|
||||||
enableServiceworker: "ServiceWorker aktivieren"
|
enableServiceworker: "ServiceWorker aktivieren"
|
||||||
antennaUsersDescription: "Benutzernamen getrennt durch Zeilenumbrüche angeben"
|
antennaUsersDescription: "Benutzernamen getrennt durch Zeilenumbrüche angeben"
|
||||||
@ -258,19 +318,44 @@ withReplies: "Antworten beinhalten"
|
|||||||
connectedTo: "Mit folgenden Benutzerkonten verknüpft"
|
connectedTo: "Mit folgenden Benutzerkonten verknüpft"
|
||||||
notesAndReplies: "Notizen und Antworten"
|
notesAndReplies: "Notizen und Antworten"
|
||||||
withFiles: "Dateien beinhalten"
|
withFiles: "Dateien beinhalten"
|
||||||
|
silence: "Instanzweit stummschalten"
|
||||||
|
silenceConfirm: "Möchtest du diesen Benutzer wirklich instanzweit stummschalten?"
|
||||||
|
unsilence: "Instanzweite Stummschaltung aufheben"
|
||||||
|
unsilenceConfirm: "Möchtest du die instanzweite Stummschaltung dieses Benutzers wirklich aufheben?"
|
||||||
popularUsers: "Beliebte Benutzer"
|
popularUsers: "Beliebte Benutzer"
|
||||||
recentlyUpdatedUsers: "Vor kurzem aktive Benutzer"
|
recentlyUpdatedUsers: "Vor kurzem aktive Benutzer"
|
||||||
recentlyRegisteredUsers: "Vor kurzem registrierte Benutzer"
|
recentlyRegisteredUsers: "Vor kurzem registrierte Benutzer"
|
||||||
recentlyDiscoveredUsers: "Vor kurzem gefundene Benutzer"
|
recentlyDiscoveredUsers: "Vor kurzem gefundene Benutzer"
|
||||||
exploreUsersCount: "Es gibt {count} Benutzer"
|
exploreUsersCount: "Es gibt {count} Benutzer"
|
||||||
exploreFediverse: "Das Fediverse erkunden"
|
exploreFediverse: "Das Fediverse erkunden"
|
||||||
|
popularTags: "Beliebte Schlagwörter"
|
||||||
userList: "Listen"
|
userList: "Listen"
|
||||||
|
about: "Über"
|
||||||
aboutMisskey: "Über Misskey"
|
aboutMisskey: "Über Misskey"
|
||||||
|
aboutMisskeyText: "Misskey ist Open-Source-Software die von syuilo seit 2014 entwickelt wird."
|
||||||
|
misskeyMembers: "Misskey wird momentan von den unten aufgelisteten Mitgliedern weiterentwickelt und instand gehalten:"
|
||||||
|
misskeySource: "Der Quelltext ist hier verfügbar:"
|
||||||
|
misskeyTranslation: "Hilf dabei, Misskey zu übersetzen:"
|
||||||
|
misskeyDonate: "Spende an Misskey, um die Weiterentwicklung zu unterstützen:"
|
||||||
|
morePatrons: "Wir schätzen ebenso die Unterstützung vieler anderer hier nicht gelisteter Personen sehr. Danke! 🥰"
|
||||||
|
patrons: "UnterstützerInnen"
|
||||||
|
administrator: "Administrator"
|
||||||
|
token: "Token"
|
||||||
|
twoStepAuthentication: "Zwei-Faktor-Authentifizierung"
|
||||||
|
moderator: "Moderator"
|
||||||
|
nUsersMentioned: "{n} Benutzer reden darüber"
|
||||||
|
securityKey: "Sicherheitsschlüssel"
|
||||||
|
securityKeyName: "Schlüsselname"
|
||||||
|
registerSecurityKey: "Sicherheitsschlüssel registrieren"
|
||||||
|
lastUsed: "Zuletzt benutzt"
|
||||||
|
unregister: "Deaktivieren"
|
||||||
|
passwordLessLogin: "Passwortloses Anmelden einrichten"
|
||||||
resetPassword: "Passwort zurücksetzen"
|
resetPassword: "Passwort zurücksetzen"
|
||||||
newPasswordIs: "Das neue Passwort ist \"{password}\""
|
newPasswordIs: "Das neue Passwort ist \"{password}\""
|
||||||
|
post: "Beitrag"
|
||||||
posted: "Gesendet"
|
posted: "Gesendet"
|
||||||
autoReloadWhenDisconnected: "Automatisch aktualisieren wenn die Serververbindung getrennt wird"
|
autoReloadWhenDisconnected: "Automatisch aktualisieren wenn die Serververbindung getrennt wird"
|
||||||
autoNoteWatch: "Notiz 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"
|
||||||
share: "Teilen"
|
share: "Teilen"
|
||||||
@ -280,7 +365,21 @@ uploadFolder: "Standardordner für Uploads"
|
|||||||
cacheClear: "Cache leeren"
|
cacheClear: "Cache leeren"
|
||||||
markAsReadAllNotifications: "Alle Benachrichtigungen als gelesen markieren"
|
markAsReadAllNotifications: "Alle Benachrichtigungen als gelesen markieren"
|
||||||
markAsReadAllUnreadNotes: "Alle Notizen als gelesen markieren"
|
markAsReadAllUnreadNotes: "Alle Notizen als gelesen markieren"
|
||||||
invites: "Einladen"
|
markAsReadAllTalkMessages: "Alle Nachrichten als gelesen markieren"
|
||||||
|
help: "Hilfe"
|
||||||
|
inputMessageHere: "Hier Nachricht eingeben"
|
||||||
|
close: "Schließen"
|
||||||
|
group: "Gruppe"
|
||||||
|
groups: "Gruppen"
|
||||||
|
createGroup: "Gruppe erstellen"
|
||||||
|
ownedGroups: "Eigene Gruppen"
|
||||||
|
joinedGroups: "Beigetretene Gruppen"
|
||||||
|
invites: "Einladungen"
|
||||||
|
groupName: "Gruppenname"
|
||||||
|
members: "Mitglieder"
|
||||||
|
transfer: "Übertragen"
|
||||||
|
messagingWithUser: "Privatnachrichten mit einem Benutzer"
|
||||||
|
messagingWithGroup: "Privatnachrichten mit einer Gruppe"
|
||||||
title: "Betreff"
|
title: "Betreff"
|
||||||
text: "Text"
|
text: "Text"
|
||||||
enable: "Aktivieren"
|
enable: "Aktivieren"
|
||||||
@ -289,13 +388,40 @@ retype: "Erneut eingeben"
|
|||||||
noteOf: "Notiz von {user}"
|
noteOf: "Notiz von {user}"
|
||||||
inviteToGroup: "Zu Gruppe einladen"
|
inviteToGroup: "Zu Gruppe einladen"
|
||||||
maxNoteTextLength: "Maximale Länge von Notizen"
|
maxNoteTextLength: "Maximale Länge von Notizen"
|
||||||
|
quoteAttached: "Zitiert"
|
||||||
|
quoteQuestion: "Als Zitat anfügen?"
|
||||||
|
noMessagesYet: "Noch keine Nachrichten"
|
||||||
|
newMessageExists: "Du hast eine neue Nachricht"
|
||||||
|
onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden"
|
||||||
|
signinRequired: "Anmeldung erforderlich"
|
||||||
|
invitationCode: "Einladungscode"
|
||||||
|
checking: "Wird überprüft..."
|
||||||
|
available: "Verfügbar"
|
||||||
|
unavailable: "Unverfügbar"
|
||||||
|
usernameInvalidFormat: "Buchstaben, Zahlen und Unterstriche sind verwendbar."
|
||||||
|
tooShort: "Zu kurz"
|
||||||
|
tooLong: "Zu lang"
|
||||||
|
weakPassword: "Schwaches Passwort"
|
||||||
|
normalPassword: "Standardpasswort"
|
||||||
|
strongPassword: "Starkes Passwort"
|
||||||
|
passwordMatched: "Stimmt überein"
|
||||||
|
passwordNotMatched: "Stimmt nicht überein"
|
||||||
|
signinWith: "Mit {x} anmelden"
|
||||||
|
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
|
||||||
|
tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
|
||||||
|
or: "Oder"
|
||||||
|
uiLanguage: "Sprache der Benutzeroberfläche"
|
||||||
|
groupInvited: "Du wurdest in eine Gruppe eingeladen"
|
||||||
|
aboutX: "Über {x}"
|
||||||
useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen"
|
useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen"
|
||||||
noGroups: "Keine Gruppen vorhanden"
|
youHaveNoGroups: "Keine Gruppen vorhanden"
|
||||||
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
|
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
|
||||||
noHistory: "Kein Verlauf"
|
noHistory: "Kein Verlauf"
|
||||||
disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren"
|
disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren"
|
||||||
|
doing: "In Bearbeitung"
|
||||||
category: "Kategorie"
|
category: "Kategorie"
|
||||||
tags: "Schlagwörter"
|
tags: "Schlagwörter"
|
||||||
|
docSource: "Quelle dieses Dokuments"
|
||||||
createAccount: "Benutzerkonto erstellen"
|
createAccount: "Benutzerkonto erstellen"
|
||||||
existingAcount: "Bestehendes Benutzerkonto"
|
existingAcount: "Bestehendes Benutzerkonto"
|
||||||
regenerate: "Regenerieren"
|
regenerate: "Regenerieren"
|
||||||
@ -304,29 +430,81 @@ noFollowRequests: "Du hast keine Follow-Anfragen"
|
|||||||
openImageInNewTab: "Bilder in neuem Tab öffnen"
|
openImageInNewTab: "Bilder in neuem Tab öffnen"
|
||||||
dashboard: "Dashboard"
|
dashboard: "Dashboard"
|
||||||
local: "Lokal"
|
local: "Lokal"
|
||||||
|
remote: "Fremd"
|
||||||
total: "Gesamt"
|
total: "Gesamt"
|
||||||
weekOverWeekChanges: "Wöchentlich"
|
weekOverWeekChanges: "Wöchentlich"
|
||||||
dayOverDayChanges: "Täglich"
|
dayOverDayChanges: "Täglich"
|
||||||
accessibility: "Barrierefreiheit"
|
accessibility: "Barrierefreiheit"
|
||||||
clinetSettings: "Client-Einstellungen"
|
clinetSettings: "Client-Einstellungen"
|
||||||
accountSettings: "Benutzerkontoeinstellungen"
|
accountSettings: "Benutzerkonto-Einstellungen"
|
||||||
promotion: "Hervorgehoben"
|
promotion: "Hervorgehoben"
|
||||||
promote: "Hervorheben"
|
promote: "Hervorheben"
|
||||||
numberOfDays: "Anzahl der Tage"
|
numberOfDays: "Anzahl der Tage"
|
||||||
hideThisNote: "Diese Notiz verstecken"
|
hideThisNote: "Diese Notiz verstecken"
|
||||||
|
showFeaturedNotesInTimeline: "Beliebte Notizen in Chronik anzeigen"
|
||||||
|
objectStorage: "Objektspeicher"
|
||||||
|
useObjectStorage: "Objektspeicher verwenden"
|
||||||
|
objectStorageBaseUrl: "Basis-URL"
|
||||||
|
objectStorageBaseUrlDesc: "URL-Prefix, der zum Konstruieren der Objekt- bzw. Mediareferenz-URL genutzt wird. Falls du ein CDN- oder einen Proxy nutzt, gib dessen URL ein. Ansonsten gib die Adresse, der dir von deinem Anbieter z.B. in dessen Servicehandbuch gegeben wurde, an. Beispielsweise 'https://<bucket>.s3.amazonaws.com' für AWS S3 oder 'https://storage.googleapis.com/<bucket>' für GCS."
|
||||||
|
objectStorageBucket: "Bucket"
|
||||||
|
objectStorageBucketDesc: "Bitte gib den Bucket-Namen an, der bei deinem Anbieter verwendet wird."
|
||||||
|
objectStoragePrefix: "Prefix"
|
||||||
|
objectStoragePrefixDesc: "Dateien werden im Ordner dieses Prefixes gespeichert."
|
||||||
|
objectStorageEndpoint: "Endpoint"
|
||||||
|
objectStorageEndpointDesc: "Dieses Feld leerlassen, falls du AWS S3 verwendest. Ansonsten trage den Endpoint im Format \"<host>\" oder \"<host>:<port>\" an, den Angaben deines Anbieters entsprechend."
|
||||||
|
objectStorageRegion: "Region"
|
||||||
|
objectStorageRegionDesc: "Gib eine Region (wie z.B. \"xx-east-1\") an. Falls dein Anbieter nicht zwischen Regionen unterscheidet, lass dieses Feld leer oder gib \"us-east-1\" an."
|
||||||
|
objectStorageUseSSL: "SSL verwenden"
|
||||||
|
objectStorageUseSSLDesc: "Deaktiviere dies falls du für die API-Verbindungen kein HTTPS verwenden wirst"
|
||||||
|
objectStorageUseProxy: "Über Proxy verbinden"
|
||||||
|
objectStorageUseProxyDesc: "Deaktiviere dies falls du keinen Proxy für den Objektspeicher verwenden wirst"
|
||||||
serverLogs: "Serverprotokolle"
|
serverLogs: "Serverprotokolle"
|
||||||
deleteAll: "Alle löschen"
|
deleteAll: "Alle löschen"
|
||||||
|
showFixedPostForm: "Bereich zum Schreiben neuer Notizen am Anfang der Chronik anzeigen"
|
||||||
|
newNoteRecived: "Es gibt neue Notizen"
|
||||||
sounds: "Töne"
|
sounds: "Töne"
|
||||||
listen: "Anhören"
|
listen: "Anhören"
|
||||||
none: "Keine"
|
none: "Keine"
|
||||||
volume: "Lautstärke"
|
volume: "Lautstärke"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Wähle ein Emoji"
|
chooseEmoji: "Wähle ein Emoji"
|
||||||
|
unableToProcess: "Der Vorgang konnte nicht abgeschlossen werden."
|
||||||
|
recentUsed: "Vor kurzem verwendet"
|
||||||
|
install: "Installieren"
|
||||||
|
uninstall: "Uninstallieren"
|
||||||
|
installedApps: "Authorisierte Anwendungen"
|
||||||
|
nothing: "Hier gibt es nichts zu sehen"
|
||||||
|
installedDate: "Authorisiert"
|
||||||
|
lastUsedDate: "Zuletzt verwendet"
|
||||||
|
state: "Status"
|
||||||
|
sort: "Sortieren"
|
||||||
|
ascendingOrder: "Aufsteigende Reihenfolge"
|
||||||
|
descendingOrder: "Absteigende Reihenfolge"
|
||||||
|
scratchpad: "Testumgebung"
|
||||||
|
scratchpadDescription: "Die Testumgebung bietet eine experimentale Umgebung für AiScript. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Misskey überprüfen."
|
||||||
|
output: "Ausgabe"
|
||||||
|
script: "Skript"
|
||||||
|
disablePagesScript: "AiScript auf Seiten deaktivieren"
|
||||||
|
updateRemoteUser: "Informationen über den Benutzer der fremder Instanz aktualisieren"
|
||||||
|
deleteAllFiles: "Alle Dateien löschen"
|
||||||
|
deleteAllFilesConfirm: "Möchtest du wirklich alle Dateien löschen?"
|
||||||
|
removeAllFollowing: "Allen gefolgten Benutzern entfolgen"
|
||||||
|
removeAllFollowingDescription: "Allen Benutzerkonten von {host} entfolgen. Bitte führe dies durch, falls diese Instanz nicht mehr existiert."
|
||||||
|
userSuspended: "Dieser Benutzer wurde gesperrt."
|
||||||
|
userSilenced: "Dieser Benutzer wurde instanzweit stummgeschaltet."
|
||||||
|
_theme:
|
||||||
|
explore: "Themen erforschen"
|
||||||
|
install: "Thema installieren"
|
||||||
|
manage: "Themaverwaltung"
|
||||||
|
code: "Themencode"
|
||||||
|
installed: "{name} wurde installiert"
|
||||||
|
alreadyInstalled: "Dieses Thema ist bereits installiert"
|
||||||
|
invalid: "Themenformat ist ungültig"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Notizen"
|
note: "Notizen"
|
||||||
noteMy: "Meine Notizen"
|
noteMy: "Meine Notizen"
|
||||||
notification: "Benachrichtigungen"
|
notification: "Benachrichtigungen"
|
||||||
chat: "Nachrichten"
|
chat: "Privatnachrichten"
|
||||||
chatBg: "Nachrichten (Hintergrund)"
|
chatBg: "Nachrichten (Hintergrund)"
|
||||||
antenna: "Antennen"
|
antenna: "Antennen"
|
||||||
_ago:
|
_ago:
|
||||||
@ -344,11 +522,79 @@ _time:
|
|||||||
second: "Sekunde"
|
second: "Sekunde"
|
||||||
minute: "Minute"
|
minute: "Minute"
|
||||||
hour: "Stunde"
|
hour: "Stunde"
|
||||||
|
day: "t"
|
||||||
|
_tutorial:
|
||||||
|
title: "Wie du Misskey verwendest"
|
||||||
|
step1_1: "Willkommen!"
|
||||||
|
step1_2: "Diese Seite ist die \"Chronik\". Sie zeigt dir deine geschrieben \"Notizen\" sowie die aller Benutzer, denen du \"folgst\" in chronologischer Reihenfolge."
|
||||||
|
step1_3: "Deine Chronik sollte momentan leer sein, da du bis jetzt nocht keine Notizen geschrieben hast und auch noch keinen Benutzern folgst."
|
||||||
|
step2_1: "Lass uns zuerst dein Profil vervollständigen, bevor du Notizen schreibst oder jemandem folgst."
|
||||||
|
step2_2: "Informationen darüber, wer du bist, macht es anderen leichter zu wissen, ob sie deine Notizen sehen wollen und ob sie dir folgen möchten."
|
||||||
|
step3_1: "Mit dem Einrichten deines Profils fertig?"
|
||||||
|
step3_2: "Der nächste Schritt ist das Schreiben einer Notiz. Dies kannst du tun, indem du auf das Stift-Icon auf dem Bildschirm drückst."
|
||||||
|
step3_3: "Fülle das Fenster aus und drücke auf den Knopf oben rechts zum Senden."
|
||||||
|
step3_4: "Gibt es nichts, das du momentan sagen möchtest? Versuch's mit \"Hallo Misskey!\""
|
||||||
|
step4_1: "Fertig mit dem Senden deiner ersten Notiz?"
|
||||||
|
step4_2: "Falls deine Notiz nun auf deiner Chronik auftaucht, hast du alles richtig gemacht."
|
||||||
|
step5_1: "Lass uns nun deiner Chronik etwas mehr Leben einhauchen, indem du einigen anderen Benutzern folgst."
|
||||||
|
step5_2: "{featured} zeigt dir beliebte Notizen dieser Instanz. In {explore} kannst du beliebte Benutzer finden. Schau dort, ob du Benutzer findest, die dich interessieren."
|
||||||
|
step5_3: "Um anderen Benutzern zu folgen, klicke auf ihr Profilbild und klicke dann auf den \"Folgen\" Knopf in ihrem Profil."
|
||||||
|
step5_4: "Wenn der Benutzer neben seinem Namen ein Schloss hat, dann muss er deine Follow-Anfrage manuell bestätigen."
|
||||||
|
step6_1: "Wenn du nun auch die Notizen anderer Benutzer auf deiner Chronik siehst, hast du alles richtig gemacht."
|
||||||
|
step6_2: "Du kannst ebenso \"Reaktionen\" verwenden, um schnell auf Notizen anderer Benutzer zu antworten."
|
||||||
|
step6_3: "Um eine \"Reaktion\" anzufügen, klicke auf das \"+\"-Symbol in der Notiz eines anderen Benutzers und wähle ein Emoji, mit dem du reagieren möchtest."
|
||||||
|
step7_1: "Glückwunsch! Du hast die Misskey-Einführung abgeschlossen."
|
||||||
|
step7_2: "Wenn du mehr über Misskey lernen möchtest, schau dich im {help}-Bereich um."
|
||||||
|
step7_3: "Und nun, viel Spaß mit Misskey! 🚀"
|
||||||
|
_2fa:
|
||||||
|
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert"
|
||||||
|
registerDevice: "Neues Gerät registrieren"
|
||||||
|
registerKey: "Neuen Sicherheitsschlüssel registrieren"
|
||||||
|
step1: "Als Erstes, installiere eine Authentifizierungsapp (z.B. {a} oder {b}) auf deinem Gerät."
|
||||||
|
step2: "Dann, scanne den angezeigten QR-Code mit deinem Gerät."
|
||||||
|
step3: "Um die Einrichtung abzuschließen, gib den Token ein, der von deiner Authentifizierungsapp angezeigt wird."
|
||||||
|
step4: "Ab jetzt benötigen alle Loginversuche auch einen Login-Token."
|
||||||
|
securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Authentifizierung mit FIDO2-kompatiblen Hardware-Sicherheitsschlüsseln einrichten."
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:messaging": "Nachrichten lesen"
|
"read:account": "Deine Benutzerkontoinformationen lesen"
|
||||||
"write:messaging": "Nachrichten schicken oder löschen"
|
"write:account": "Deine Benutzerkontoinformationen bearbeiten"
|
||||||
"read:reactions": "Reaktionen sehen"
|
"read:blocks": "Die Liste deiner blockierten Benutzer lesen"
|
||||||
|
"write:blocks": "Die Liste deiner blockierten Benutzer bearbeiten"
|
||||||
|
"read:drive": "Deine Drive-Dateien und Ordner lesen"
|
||||||
|
"write:drive": "Deine Drive-Dateien und Ordner bearbeiten oder löschen"
|
||||||
|
"read:favorites": "Deine Favoriten-Liste lesen"
|
||||||
|
"write:favorites": "Deine Favoriten-Liste bearbeiten"
|
||||||
|
"read:following": "Deine Follower-Liste lesen"
|
||||||
|
"write:following": "Anderen Benutzern folgen oder entfolgen"
|
||||||
|
"read:messaging": "Privatnachrichten lesen"
|
||||||
|
"write:messaging": "Privatnachrichten schicken oder löschen"
|
||||||
|
"read:mutes": "Stummschaltungen lesen"
|
||||||
|
"write:mutes": "Stummschaltungen bearbeiten"
|
||||||
|
"write:notes": "Notizen schreiben oder löschen"
|
||||||
|
"read:notifications": "Benachrichtigungen lesen"
|
||||||
|
"write:notifications": "Mit Benachrichtigungen arbeiten"
|
||||||
|
"read:reactions": "Reaktionen lesen"
|
||||||
"write:reactions": "Reaktionen hinzufügen und bearbeiten"
|
"write:reactions": "Reaktionen hinzufügen und bearbeiten"
|
||||||
|
"write:votes": "In Umfragen abstimmen"
|
||||||
|
"read:pages": "Deine Seiten lesen"
|
||||||
|
"write:pages": "Deine Seiten bearbeiten oder löschen"
|
||||||
|
"read:page-likes": "Liste der Seiten, die mir gefallen, lesen"
|
||||||
|
"write:page-likes": "Liste der Seiten, die mir gefallen, bearbeiten"
|
||||||
|
"read:user-groups": "Benutzergruppen lesen"
|
||||||
|
"write:user-groups": "Benutzergruppen bearbeiten oder löschen"
|
||||||
|
_auth:
|
||||||
|
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?"
|
||||||
|
permissionAsk: "Diese Anwendung erfordert folgende Berechtigungen:"
|
||||||
|
pleaseGoBack: "Bitte gehe zurück zur Anwendung"
|
||||||
|
callback: "Rückkehr zur Anwendung"
|
||||||
|
denied: "Zugriff verweigert"
|
||||||
|
_antennaSources:
|
||||||
|
all: "Alle Notizen"
|
||||||
|
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
|
||||||
|
users: "Notizen von konkreten Benutzern"
|
||||||
|
userList: "Notizen von allen Benutzern aus einer Liste"
|
||||||
|
userGroup: "Notizen von allen Benutzern aus einer Gruppe"
|
||||||
_weekday:
|
_weekday:
|
||||||
sunday: "Sonntag"
|
sunday: "Sonntag"
|
||||||
monday: "Montag"
|
monday: "Montag"
|
||||||
@ -360,7 +606,7 @@ _weekday:
|
|||||||
_widgets:
|
_widgets:
|
||||||
memo: "Memo"
|
memo: "Memo"
|
||||||
notifications: "Benachrichtigungen"
|
notifications: "Benachrichtigungen"
|
||||||
timeline: "Zeitleiste"
|
timeline: "Chronik"
|
||||||
calendar: "Kalender"
|
calendar: "Kalender"
|
||||||
trends: "Trends"
|
trends: "Trends"
|
||||||
clock: "Uhr"
|
clock: "Uhr"
|
||||||
@ -369,20 +615,20 @@ _widgets:
|
|||||||
photos: "Fotos"
|
photos: "Fotos"
|
||||||
_cw:
|
_cw:
|
||||||
hide: "Ausblenden"
|
hide: "Ausblenden"
|
||||||
show: "Zeige mehr"
|
show: "Mehr anzeigen"
|
||||||
chars: "{count} Zeichen"
|
chars: "{count} Zeichen"
|
||||||
files: "{count} Dateien"
|
files: "{count} Dateien"
|
||||||
poll: "Umfrage"
|
poll: "Umfrage"
|
||||||
_poll:
|
_poll:
|
||||||
noOnlyOneChoice: "Mindestens zwei Antwortmöglichkeiten werden benötigt."
|
noOnlyOneChoice: "Mindestens zwei Antwortmöglichkeiten werden benötigt."
|
||||||
choiceN: "Auswahl {n}"
|
choiceN: "Auswahl {n}"
|
||||||
noMore: "Du kannst keine weiteren Auswahlen hinzufügen"
|
noMore: "Du kannst keine weiteren Auswahlmöglichkeiten hinzufügen"
|
||||||
canMultipleVote: "Mehrfachantworten erlauben"
|
canMultipleVote: "Mehrfachantworten erlauben"
|
||||||
expiration: "Abstimmung endet am"
|
expiration: "Abstimmung endet am"
|
||||||
infinite: "Nie"
|
infinite: "Nie"
|
||||||
at: "Beenden am..."
|
at: "Beenden am..."
|
||||||
after: "Beenden nach..."
|
after: "Beenden nach..."
|
||||||
deadlineDate: "Enddatum"
|
deadlineDate: "Abstimmungsende"
|
||||||
deadlineTime: "Stunde"
|
deadlineTime: "Stunde"
|
||||||
duration: "Laufzeit"
|
duration: "Laufzeit"
|
||||||
votesCount: "{n} Stimmen"
|
votesCount: "{n} Stimmen"
|
||||||
@ -399,10 +645,11 @@ _visibility:
|
|||||||
public: "Öffentlich"
|
public: "Öffentlich"
|
||||||
publicDescription: "Deine Notiz wird global sichtbar sein"
|
publicDescription: "Deine Notiz wird global sichtbar sein"
|
||||||
home: "Startseite"
|
home: "Startseite"
|
||||||
followers: "Folgende"
|
homeDescription: "Deine Notiz wird nur in der Chronik deiner Instanz angezeigt."
|
||||||
|
followers: "Follower"
|
||||||
followersDescription: "Nur für Follower sichtbar"
|
followersDescription: "Nur für Follower sichtbar"
|
||||||
specified: "Direkt"
|
specified: "Direkt"
|
||||||
specifiedDescription: "Nur für erwähnte Benutzer sichtbar"
|
specifiedDescription: "Nur für bestimmte Benutzer sichtbar"
|
||||||
localOnly: "Nur Lokal"
|
localOnly: "Nur Lokal"
|
||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Dieser Notiz antworten..."
|
replyPlaceholder: "Dieser Notiz antworten..."
|
||||||
@ -424,9 +671,9 @@ _profile:
|
|||||||
metadataContent: "Inhalt"
|
metadataContent: "Inhalt"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
allNotes: "Alle Notizen"
|
allNotes: "Alle Notizen"
|
||||||
followingList: "Folgen"
|
followingList: "Gefolgte Benutzer"
|
||||||
muteList: "Stummschalten"
|
muteList: "Stummschaltungen"
|
||||||
blockingList: "Blockieren"
|
blockingList: "Blockierungen"
|
||||||
userLists: "Listen"
|
userLists: "Listen"
|
||||||
_charts:
|
_charts:
|
||||||
federationInstancesIncDec: "Unterschied in der Anzahl von förderierenden Instanzen"
|
federationInstancesIncDec: "Unterschied in der Anzahl von förderierenden Instanzen"
|
||||||
@ -436,6 +683,7 @@ _charts:
|
|||||||
activeUsers: "Aktive Benutzer"
|
activeUsers: "Aktive Benutzer"
|
||||||
notesIncDec: "Unterschied in der Anzahl von Notizen"
|
notesIncDec: "Unterschied in der Anzahl von Notizen"
|
||||||
localNotesIncDec: "Unterschied in der Anzahl von lokalen Notizen"
|
localNotesIncDec: "Unterschied in der Anzahl von lokalen Notizen"
|
||||||
|
remoteNotesIncDec: "Differenz in Anzahl der Notizen von anderen Instanzen"
|
||||||
notesTotal: "Anzahl aller Notizen"
|
notesTotal: "Anzahl aller Notizen"
|
||||||
filesIncDec: "Unterschied in der Anzahl von Dateien"
|
filesIncDec: "Unterschied in der Anzahl von Dateien"
|
||||||
filesTotal: "Anzahl aller Dateien"
|
filesTotal: "Anzahl aller Dateien"
|
||||||
@ -444,39 +692,57 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "Anfragen"
|
requests: "Anfragen"
|
||||||
users: "Unterschied in der Anzahl von Benutzern"
|
users: "Unterschied in der Anzahl von Benutzern"
|
||||||
usersTotal: "Anzahl aller Benutzer"
|
usersTotal: "Gesamtanzahl an Benutzern"
|
||||||
notes: "Unterschied in der Anzahl von Notizen"
|
notes: "Unterschied in der Anzahl von Notizen"
|
||||||
notesTotal: "Anzahl aller Notizen"
|
notesTotal: "Gesamtanzahl an Notizen"
|
||||||
ff: "Unterschied in der Anzahl von Followern"
|
ff: "Unterschied in der Anzahl von Followern"
|
||||||
ffTotal: "Gesamtanzahl der Follower"
|
ffTotal: "Gesamtanzahl an Followern"
|
||||||
cacheSize: "Unterschied in der Größe des Caches"
|
cacheSize: "Unterschied in der Größe des Caches"
|
||||||
cacheSizeTotal: "Gesamtgröße des Caches"
|
cacheSizeTotal: "Gesamtgröße des Caches"
|
||||||
files: "Unterschied in der Anzahl der Dateien"
|
files: "Unterschied in der Anzahl der Dateien"
|
||||||
filesTotal: "Gesamtanzahl der Dateien"
|
filesTotal: "Gesamtanzahl an Dateien"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Startseite"
|
home: "Startseite"
|
||||||
local: "Lokal"
|
local: "Lokal"
|
||||||
|
social: "Sozial"
|
||||||
global: "Global"
|
global: "Global"
|
||||||
_pages:
|
_pages:
|
||||||
|
newPage: "Seite erstellen"
|
||||||
|
editPage: "Diese Seite bearbeiten"
|
||||||
|
readPage: "Quelltext-Ansicht"
|
||||||
|
created: "Seite erfolgreich erstellt"
|
||||||
|
updated: "Seite erfolgreich aktualisiert"
|
||||||
|
deleted: "Seite erfolgreich gelöscht"
|
||||||
|
nameAlreadyExists: "Die angegebene Seiten-URL existiert bereits"
|
||||||
|
invalidNameTitle: "Die angegebene Seiten-URL ist ungültig"
|
||||||
|
invalidNameText: "Überprüfe, ob der Seitentitel nicht leer ist"
|
||||||
|
editThisPage: "Diese Seite bearbeiten"
|
||||||
|
viewSource: "Quelltext anzeigen"
|
||||||
|
viewPage: "Seite anschauen"
|
||||||
|
like: "Gefällt mir"
|
||||||
|
unlike: "\"Gefällt mir\" entfernen"
|
||||||
|
my: "Meine Seiten"
|
||||||
|
liked: "Seiten, die mir gefallen"
|
||||||
|
inspector: "Inspektor"
|
||||||
content: "Inhalt"
|
content: "Inhalt"
|
||||||
more-details: "Mehr Informationen"
|
variables: "Variablen"
|
||||||
title: "Titel"
|
title: "Titel"
|
||||||
url: "Seiten-URL"
|
url: "Seiten-URL"
|
||||||
summary: "Zusammenfassung"
|
summary: "Zusammenfassung"
|
||||||
alignCenter: "Mittig ausrichten"
|
alignCenter: "Bestandteile zentrieren"
|
||||||
hide-title-when-pinned: "Seitentitel wenn angepinnt ausblenden"
|
hideTitleWhenPinned: "Seitentitel ausblenden, wenn an dein Profil angepinnt "
|
||||||
font: "Schriftart"
|
font: "Schriftart"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans Serif"
|
fontSansSerif: "Sans Serif"
|
||||||
|
eyeCatchingImageSet: "Vorschaubild festlegen"
|
||||||
|
eyeCatchingImageRemove: "Vorschaubild entfernen"
|
||||||
chooseBlock: "Block hinzufügen"
|
chooseBlock: "Block hinzufügen"
|
||||||
selectType: "Wähle einen Typ"
|
selectType: "Wähle einen Typ"
|
||||||
enterVariableName: "Gib einen Namen für deine Variable ein"
|
enterVariableName: "Gib einen Namen für deine Variable ein"
|
||||||
the-variable-name-is-already-used: "Der Variablenname wird bereits verwendet"
|
variableNameIsAlreadyUsed: "Dieser Name wird bereits von einer anderen Variable verwendet"
|
||||||
content-blocks: "Inhalt"
|
contentBlocks: "Inhalt"
|
||||||
input-blocks: "Eingabe"
|
inputBlocks: "Eingabe"
|
||||||
special-blocks: "Speziell"
|
specialBlocks: "Spezial"
|
||||||
post-from-post-form: "Diesen Inhalt senden"
|
|
||||||
posted-from-post-form: "Erfolgreich gesendet!"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "Text"
|
text: "Text"
|
||||||
textarea: "Textfeld"
|
textarea: "Textfeld"
|
||||||
@ -489,24 +755,35 @@ _pages:
|
|||||||
post: "Neue Notiz anfertigen"
|
post: "Neue Notiz anfertigen"
|
||||||
_post:
|
_post:
|
||||||
text: "Inhalt"
|
text: "Inhalt"
|
||||||
|
canvasId: "Leinwand-ID"
|
||||||
textInput: "Texteingabe"
|
textInput: "Texteingabe"
|
||||||
_textInput:
|
_textInput:
|
||||||
|
name: "Variablenname"
|
||||||
text: "Titel"
|
text: "Titel"
|
||||||
default: "Standardwert"
|
default: "Standardwert"
|
||||||
textareaInput: "Eingabe des mehrzeiligen Textfelds"
|
textareaInput: "Eingabe des mehrzeiligen Textfelds"
|
||||||
_textareaInput:
|
_textareaInput:
|
||||||
|
name: "Variablenname"
|
||||||
text: "Titel"
|
text: "Titel"
|
||||||
default: "Standardwert"
|
default: "Standardwert"
|
||||||
numberInput: "Nummereingabe"
|
numberInput: "Nummereingabe"
|
||||||
_numberInput:
|
_numberInput:
|
||||||
|
name: "Variablenname"
|
||||||
text: "Titel"
|
text: "Titel"
|
||||||
default: "Standardwert"
|
default: "Standardwert"
|
||||||
|
canvas: "Leinwand"
|
||||||
|
_canvas:
|
||||||
|
id: "Leinwand-ID"
|
||||||
|
width: "Breite"
|
||||||
|
height: "Höhe"
|
||||||
switch: "Fallunterscheidung"
|
switch: "Fallunterscheidung"
|
||||||
_switch:
|
_switch:
|
||||||
|
name: "Variablenname"
|
||||||
text: "Titel"
|
text: "Titel"
|
||||||
default: "Standardwert"
|
default: "Standardwert"
|
||||||
counter: "Zähler"
|
counter: "Zähler"
|
||||||
_counter:
|
_counter:
|
||||||
|
name: "Variablenname"
|
||||||
text: "Titel"
|
text: "Titel"
|
||||||
inc: "Erhöhen um"
|
inc: "Erhöhen um"
|
||||||
_button:
|
_button:
|
||||||
@ -524,13 +801,18 @@ _pages:
|
|||||||
message: "Nachricht, die bei Aktivierung gezeigt werden soll"
|
message: "Nachricht, die bei Aktivierung gezeigt werden soll"
|
||||||
variable: "Variable, die gesendet werden soll"
|
variable: "Variable, die gesendet werden soll"
|
||||||
no-variable: "Keine"
|
no-variable: "Keine"
|
||||||
|
callAiScript: "AiScript ausführen"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "Funktionsname"
|
||||||
radioButton: "Optionsfeld"
|
radioButton: "Optionsfeld"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
|
name: "Variablenname"
|
||||||
title: "Titel"
|
title: "Titel"
|
||||||
values: "Auswahlmöglichkeiten (getrennt durch Zeilenumbrüche)"
|
values: "Auswahlmöglichkeiten (getrennt durch Zeilenumbrüche)"
|
||||||
default: "Standardwert"
|
default: "Standardwert"
|
||||||
script:
|
script:
|
||||||
categories:
|
categories:
|
||||||
|
flow: "Steuerung"
|
||||||
logical: "Logische Operationen"
|
logical: "Logische Operationen"
|
||||||
operation: "Berechnungen"
|
operation: "Berechnungen"
|
||||||
comparison: "Vergleiche"
|
comparison: "Vergleiche"
|
||||||
@ -681,17 +963,26 @@ _pages:
|
|||||||
splitStrByLine: "Text nach Zeilenumbrüchen aufteilen"
|
splitStrByLine: "Text nach Zeilenumbrüchen aufteilen"
|
||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "Text"
|
arg1: "Text"
|
||||||
|
ref: "Variablen"
|
||||||
|
aiScriptVar: "AiScript Variablen"
|
||||||
fn: "Funktionen"
|
fn: "Funktionen"
|
||||||
_fn:
|
_fn:
|
||||||
|
slots: "Slots"
|
||||||
|
slots-info: "Trenne jeden Slot mit einem Zeilenumbruch"
|
||||||
arg1: "Ausgabe"
|
arg1: "Ausgabe"
|
||||||
for: "Wiederholen"
|
for: "Wiederholen"
|
||||||
_for:
|
_for:
|
||||||
arg1: "Anzahl der Wiederholungen"
|
arg1: "Anzahl der Wiederholungen"
|
||||||
arg2: "Aktion"
|
arg2: "Aktion"
|
||||||
|
typeError: "Slot {slot} akzeptiert Werte vom Typ \"{expect}\", aber es wurde ein \"{actual}\" Wert angegeben!"
|
||||||
|
thereIsEmptySlot: "Slot {slot} ist leer!"
|
||||||
types:
|
types:
|
||||||
string: "Text"
|
string: "Text"
|
||||||
number: "Nummer"
|
number: "Nummer"
|
||||||
|
boolean: "Flag"
|
||||||
array: "Listen"
|
array: "Listen"
|
||||||
stringArray: "Textliste"
|
stringArray: "Textliste"
|
||||||
|
emptySlot: "Leerer Slot"
|
||||||
enviromentVariables: "Umgebungsvariable"
|
enviromentVariables: "Umgebungsvariable"
|
||||||
pageVariables: "Seitenelement"
|
pageVariables: "Seitenelement"
|
||||||
|
argVariables: "Eingabe-Slot"
|
||||||
|
@ -18,7 +18,7 @@ instance: "Instance"
|
|||||||
settings: "Settings"
|
settings: "Settings"
|
||||||
profile: "Profile"
|
profile: "Profile"
|
||||||
timeline: "Timeline"
|
timeline: "Timeline"
|
||||||
noAccountDescription: "This user has not created their bio yet."
|
noAccountDescription: "This user has not written their bio yet."
|
||||||
login: "Sign In"
|
login: "Sign In"
|
||||||
loggingIn: "Signing In"
|
loggingIn: "Signing In"
|
||||||
logout: "Sign Out"
|
logout: "Sign Out"
|
||||||
@ -35,6 +35,8 @@ unpin: "Unpin from profile"
|
|||||||
copyContent: "Copy contents"
|
copyContent: "Copy contents"
|
||||||
copyLink: "Copy link"
|
copyLink: "Copy link"
|
||||||
delete: "Delete"
|
delete: "Delete"
|
||||||
|
deleteAndEdit: "Delete and Edit"
|
||||||
|
deleteAndEditConfirm: "Are you sure you want to delete this note and edit it? You will lose all reactions, renotes and replies to it."
|
||||||
addToList: "Add to list"
|
addToList: "Add to list"
|
||||||
sendMessage: "Send a message"
|
sendMessage: "Send a message"
|
||||||
copyUsername: "Copy username"
|
copyUsername: "Copy username"
|
||||||
@ -86,7 +88,6 @@ add: "Add"
|
|||||||
reaction: "Reaction"
|
reaction: "Reaction"
|
||||||
reactionSettingDescription: "Assign your favorite reactions which want to pin in reaction picker."
|
reactionSettingDescription: "Assign your favorite reactions which want to pin in reaction picker."
|
||||||
rememberNoteVisibility: "Remember note visibility settings"
|
rememberNoteVisibility: "Remember note visibility settings"
|
||||||
renameFile: "Rename file"
|
|
||||||
attachCancel: "Remove attachment"
|
attachCancel: "Remove attachment"
|
||||||
markAsSensitive: "Mark as NSFW"
|
markAsSensitive: "Mark as NSFW"
|
||||||
unmarkAsSensitive: "Undo NSFW"
|
unmarkAsSensitive: "Undo NSFW"
|
||||||
@ -116,6 +117,7 @@ loginFailed: "Failed to sign in"
|
|||||||
showOnRemote: "View on remote instance"
|
showOnRemote: "View on remote instance"
|
||||||
general: "General"
|
general: "General"
|
||||||
wallpaper: "Wallpaper"
|
wallpaper: "Wallpaper"
|
||||||
|
setWallpaper: "Set wallpaper"
|
||||||
removeWallpaper: "Remove wallpaper"
|
removeWallpaper: "Remove wallpaper"
|
||||||
searchWith: "Search: {q}"
|
searchWith: "Search: {q}"
|
||||||
youHaveNoLists: "You don't have any lists"
|
youHaveNoLists: "You don't have any lists"
|
||||||
@ -204,10 +206,13 @@ messaging: "Messaging"
|
|||||||
upload: "Upload"
|
upload: "Upload"
|
||||||
fromDrive: "From Drive"
|
fromDrive: "From Drive"
|
||||||
fromUrl: "From URL"
|
fromUrl: "From URL"
|
||||||
|
uploadFromUrl: "Upload from a URL"
|
||||||
|
uploadFromUrlDescription: "URL of the file you want to upload"
|
||||||
|
uploadFromUrlRequested: "Upload requested"
|
||||||
|
uploadFromUrlMayTakeTime: "It may take some time until the upload is complete."
|
||||||
explore: "Explore"
|
explore: "Explore"
|
||||||
games: "Misskey Games"
|
games: "Misskey Games"
|
||||||
messageRead: "Read"
|
messageRead: "Read"
|
||||||
recentUsedEmojis: "Recently used emojis"
|
|
||||||
noMoreHistory: "There is no further history"
|
noMoreHistory: "There is no further history"
|
||||||
startMessaging: "Start messaging"
|
startMessaging: "Start messaging"
|
||||||
nUsersRead: "read by {n}"
|
nUsersRead: "read by {n}"
|
||||||
@ -223,30 +228,44 @@ yearsOld: "{age} years old"
|
|||||||
registeredDate: "Joined on"
|
registeredDate: "Joined on"
|
||||||
location: "Location"
|
location: "Location"
|
||||||
theme: "Theme"
|
theme: "Theme"
|
||||||
|
themeForLightMode: "Theme to use in Light Mode"
|
||||||
|
themeForDarkMode: "Theme to use in Dark Mode"
|
||||||
|
light: "Light"
|
||||||
|
dark: "Dark"
|
||||||
lightThemes: "Light theme"
|
lightThemes: "Light theme"
|
||||||
darkThemes: "Dark theme"
|
darkThemes: "Dark theme"
|
||||||
|
syncDeviceDarkMode: "Sync Dark Mode with your device settings"
|
||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
|
fileName: "Filename"
|
||||||
selectFile: "Select a file"
|
selectFile: "Select a file"
|
||||||
selectFiles: "Select files"
|
selectFiles: "Select files"
|
||||||
renameFolder: "Rename this folder"
|
renameFile: "Rename file"
|
||||||
|
folderName: "Folder name"
|
||||||
createFolder: "Create a folder"
|
createFolder: "Create a folder"
|
||||||
|
renameFolder: "Rename this folder"
|
||||||
deleteFolder: "Delete this folder"
|
deleteFolder: "Delete this folder"
|
||||||
addFile: "Add a file"
|
addFile: "Add a file"
|
||||||
emptyDrive: "The drive is empty"
|
emptyDrive: "The drive is empty"
|
||||||
emptyFolder: "This folder is empty"
|
emptyFolder: "This folder is empty"
|
||||||
|
unableToDelete: "Unable to delete"
|
||||||
|
inputNewFileName: "Enter a new filename"
|
||||||
|
inputNewFolderName: "Enter a new folder name"
|
||||||
|
circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
|
||||||
|
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
|
||||||
copyUrl: "Copy URL"
|
copyUrl: "Copy URL"
|
||||||
rename: "Rename"
|
rename: "Rename"
|
||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
nsfw: "NSFW"
|
nsfw: "NSFW"
|
||||||
disconnectedFromServer: "Connection to the server was inturrupted"
|
disconnectedFromServer: "Connection to the server was interrupted."
|
||||||
reload: "Refresh"
|
reload: "Refresh"
|
||||||
doNothing: "Ignore"
|
doNothing: "Ignore"
|
||||||
reloadConfirm: "Would you like to retry?"
|
reloadConfirm: "Would you like to refresh timeline?"
|
||||||
watch: "Watch"
|
watch: "Watch"
|
||||||
unwatch: "Undo Watch"
|
unwatch: "Undo Watch"
|
||||||
accept: "Accept"
|
accept: "Accept"
|
||||||
reject: "Reject"
|
reject: "Reject"
|
||||||
|
normal: "Normal"
|
||||||
instanceName: "Instance name"
|
instanceName: "Instance name"
|
||||||
instanceDescription: "Instance description"
|
instanceDescription: "Instance description"
|
||||||
maintainerName: "Maintainer"
|
maintainerName: "Maintainer"
|
||||||
@ -301,6 +320,7 @@ notesAndReplies: "Notes and replies"
|
|||||||
withFiles: "Media"
|
withFiles: "Media"
|
||||||
silence: "Silence"
|
silence: "Silence"
|
||||||
silenceConfirm: "Are you sure that you want to silence this user?"
|
silenceConfirm: "Are you sure that you want to silence this user?"
|
||||||
|
unsilence: "Unsilence"
|
||||||
unsilenceConfirm: "Are you sure that you want to undo silence of this user?"
|
unsilenceConfirm: "Are you sure that you want to undo silence of this user?"
|
||||||
popularUsers: "Trending users"
|
popularUsers: "Trending users"
|
||||||
recentlyUpdatedUsers: "Users with recent activity"
|
recentlyUpdatedUsers: "Users with recent activity"
|
||||||
@ -313,7 +333,7 @@ userList: "Lists"
|
|||||||
about: "About"
|
about: "About"
|
||||||
aboutMisskey: "About Misskey"
|
aboutMisskey: "About Misskey"
|
||||||
aboutMisskeyText: "Misskey is an open-source software developed by syuilo since 2014."
|
aboutMisskeyText: "Misskey is an open-source software developed by syuilo since 2014."
|
||||||
misskeyMembers: "It is currently developed an maintained by the members listed below:"
|
misskeyMembers: "It is currently developed and maintained by the members listed below:"
|
||||||
misskeySource: "Source code is available here:"
|
misskeySource: "Source code is available here:"
|
||||||
misskeyTranslation: "Help us with your contribution to translate Misskey:"
|
misskeyTranslation: "Help us with your contribution to translate Misskey:"
|
||||||
misskeyDonate: "Help us to keep improving the software by donating here:"
|
misskeyDonate: "Help us to keep improving the software by donating here:"
|
||||||
@ -334,10 +354,10 @@ resetPassword: "Reset password"
|
|||||||
newPasswordIs: "The new password is \"{password}\""
|
newPasswordIs: "The new password is \"{password}\""
|
||||||
post: "Post"
|
post: "Post"
|
||||||
posted: "Posted!"
|
posted: "Posted!"
|
||||||
autoReloadWhenDisconnected: "Auto reload when disconnected with server"
|
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 animations of User Interface"
|
reduceUiAnimation: "Reduce UI animation"
|
||||||
share: "Share"
|
share: "Share"
|
||||||
notFound: "Not found"
|
notFound: "Not found"
|
||||||
notFoundDescription: "There was no page corresponding to the specified URL."
|
notFoundDescription: "There was no page corresponding to the specified URL."
|
||||||
@ -387,16 +407,17 @@ strongPassword: "Strong password"
|
|||||||
passwordMatched: "Matched"
|
passwordMatched: "Matched"
|
||||||
passwordNotMatched: "Doesn't match"
|
passwordNotMatched: "Doesn't match"
|
||||||
signinWith: "Sign in with {x}"
|
signinWith: "Sign in with {x}"
|
||||||
|
signinFailed: "Unable to sign in. The username or password you entered is incorrect."
|
||||||
tapSecurityKey: "Tap your security key"
|
tapSecurityKey: "Tap your security key"
|
||||||
or: "Or"
|
or: "Or"
|
||||||
uiLanguage: "UI display language"
|
uiLanguage: "UI display language"
|
||||||
groupInvited: "Invited to group"
|
groupInvited: "Invited to group"
|
||||||
aboutX: "About {x}"
|
aboutX: "About {x}"
|
||||||
useOsNativeEmojis: "Use the OS native Emojis"
|
useOsNativeEmojis: "Use OS native Emojis"
|
||||||
noGroups: "No groups"
|
youHaveNoGroups: "You have no groups"
|
||||||
joinOrCreateGroup: "Get invited to join the groups or you can create your own group."
|
joinOrCreateGroup: "Get invited to join the groups or you can create your own group."
|
||||||
noHistory: "No history items"
|
noHistory: "No history items"
|
||||||
disableAnimatedMfm: "Disable MFM which has animations"
|
disableAnimatedMfm: "Disable MFM with animation"
|
||||||
doing: "On my way"
|
doing: "On my way"
|
||||||
category: "Category"
|
category: "Category"
|
||||||
tags: "Tags"
|
tags: "Tags"
|
||||||
@ -435,6 +456,8 @@ objectStorageRegion: "Region"
|
|||||||
objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does not have distinction about regions, leave it blank or fill with 'us-east-1'."
|
objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does not have distinction about regions, leave it blank or fill with 'us-east-1'."
|
||||||
objectStorageUseSSL: "Use SSL"
|
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"
|
||||||
|
objectStorageUseProxyDesc: "Turn off this if you are not going to use Proxy for ObjectStorage connection"
|
||||||
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"
|
||||||
@ -445,6 +468,38 @@ none: "None"
|
|||||||
volume: "Volume"
|
volume: "Volume"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Choose an emoji"
|
chooseEmoji: "Choose an emoji"
|
||||||
|
unableToProcess: "The operation could not be completed."
|
||||||
|
recentUsed: "Recently used"
|
||||||
|
install: "Install"
|
||||||
|
uninstall: "Uninstall"
|
||||||
|
installedApps: "Authorized Applications"
|
||||||
|
nothing: "There's nothing to see here"
|
||||||
|
installedDate: "Authorized"
|
||||||
|
lastUsedDate: "Last used"
|
||||||
|
state: "State"
|
||||||
|
sort: "Sort"
|
||||||
|
ascendingOrder: "Ascending"
|
||||||
|
descendingOrder: "Descending"
|
||||||
|
scratchpad: "Scratch pad"
|
||||||
|
scratchpadDescription: "Scratchpad provides experimental environment for AiScript. You can write, execute, and check the results that interact with Misskey."
|
||||||
|
output: "Output"
|
||||||
|
script: "Script"
|
||||||
|
disablePagesScript: "Disable AiScript on Pages"
|
||||||
|
updateRemoteUser: "Update remote user information"
|
||||||
|
deleteAllFiles: "Delete All Files"
|
||||||
|
deleteAllFilesConfirm: "Are you sure that you want to delete all files?"
|
||||||
|
removeAllFollowing: "Withhold All Followings"
|
||||||
|
removeAllFollowingDescription: "Unfollow all accounts from {host}. Please run this if the instance no longer exists."
|
||||||
|
userSuspended: "This user has been suspended."
|
||||||
|
userSilenced: "This user has been silenced."
|
||||||
|
_theme:
|
||||||
|
explore: "Explore Themes"
|
||||||
|
install: "Install theme"
|
||||||
|
manage: "Themes manager"
|
||||||
|
code: "Theme code"
|
||||||
|
installed: "{name} has been installed"
|
||||||
|
alreadyInstalled: "The theme is already installed"
|
||||||
|
invalid: "Theme format is invalid"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "New note"
|
note: "New note"
|
||||||
noteMy: "My note"
|
noteMy: "My note"
|
||||||
@ -477,7 +532,7 @@ _tutorial:
|
|||||||
step2_2: "Providing some information about who you are will make it easier for others to follow you back."
|
step2_2: "Providing some information about who you are will make it easier for others to follow you back."
|
||||||
step3_1: "Finished setting up your profile?"
|
step3_1: "Finished setting up your profile?"
|
||||||
step3_2: "The next step is to post a note. You can do this by pressing the pencil icon on the screen."
|
step3_2: "The next step is to post a note. You can do this by pressing the pencil icon on the screen."
|
||||||
step3_3: "Fill in the modal and press the button on the right top to post."
|
step3_3: "Fill in the modal and press the button on the top right to post."
|
||||||
step3_4: "Have nothing to say? Try \"just setting up my msky\"!"
|
step3_4: "Have nothing to say? Try \"just setting up my msky\"!"
|
||||||
step4_1: "Finished posting your first note?"
|
step4_1: "Finished posting your first note?"
|
||||||
step4_2: "Hurray! Now your first note is displayed on your timeline."
|
step4_2: "Hurray! Now your first note is displayed on your timeline."
|
||||||
@ -529,7 +584,11 @@ _permissions:
|
|||||||
"write:user-groups": "Edit or delete user groups"
|
"write:user-groups": "Edit or delete user groups"
|
||||||
_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?"
|
||||||
permissionAsk: "This application requires following permissions:"
|
permissionAsk: "This application requires following permissions:"
|
||||||
|
pleaseGoBack: "Please go back to the application"
|
||||||
|
callback: "Returning back to the application"
|
||||||
|
denied: "Access Denied"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "All notes"
|
all: "All notes"
|
||||||
homeTimeline: "Notes from following users"
|
homeTimeline: "Notes from following users"
|
||||||
@ -633,15 +692,15 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "Requests"
|
requests: "Requests"
|
||||||
users: "Difference in # of users"
|
users: "Difference in # of users"
|
||||||
usersTotal: "Total # of users"
|
usersTotal: "Cumulative total # of users"
|
||||||
notes: "Difference in # of notes"
|
notes: "Difference in # of notes"
|
||||||
notesTotal: "Total # of notes"
|
notesTotal: "Cumulative total # of notes"
|
||||||
ff: "Difference in # of followers"
|
ff: "Difference in # of followers"
|
||||||
ffTotal: "Total # of followers"
|
ffTotal: "Cumulative total # of followers"
|
||||||
cacheSize: "Difference in cache size"
|
cacheSize: "Difference in cache size"
|
||||||
cacheSizeTotal: "Total accumulated cache"
|
cacheSizeTotal: "Cumulative total cache size"
|
||||||
files: "Difference in # of files"
|
files: "Difference in # of files"
|
||||||
filesTotal: "Total # of files"
|
filesTotal: "Cumulative total # of files"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Home"
|
home: "Home"
|
||||||
local: "Local"
|
local: "Local"
|
||||||
@ -651,45 +710,39 @@ _pages:
|
|||||||
newPage: "Create a page"
|
newPage: "Create a page"
|
||||||
editPage: "Edit this page"
|
editPage: "Edit this page"
|
||||||
readPage: "Source view activated"
|
readPage: "Source view activated"
|
||||||
page-created: "Successfully created a page!"
|
created: "Successfully created a page!"
|
||||||
page-updated: "Successfully updated the page!"
|
updated: "Successfully updated the page!"
|
||||||
name-already-exists: "Specified page URL already exists."
|
deleted: "The page has been deleted"
|
||||||
title-invalid-name: "The specified page URL is invalid."
|
nameAlreadyExists: "The specified page URL already exists"
|
||||||
text-invalid-name: "Please double-check if it is not empty."
|
invalidNameTitle: "The specified page URL is invalid"
|
||||||
|
invalidNameText: "Check whether that is not a blank"
|
||||||
editThisPage: "Edit this page"
|
editThisPage: "Edit this page"
|
||||||
viewSource: "View source"
|
viewSource: "View source"
|
||||||
viewPage: "View your pages"
|
viewPage: "View your pages"
|
||||||
like: "Like"
|
like: "Like"
|
||||||
unlike: "Undo like"
|
unlike: "Undo like"
|
||||||
liked-pages: "Liked pages"
|
my: "My pages"
|
||||||
my-pages: "My pages"
|
liked: "Liked pages"
|
||||||
inspector: "Inspector"
|
inspector: "Inspector"
|
||||||
content: "Page block"
|
content: "Page block"
|
||||||
variables: "Variables"
|
variables: "Variables"
|
||||||
variables-info: "You can make your page more interactive by using variables. If you write down <b>{ variable name }</b> in the text, you can embed the value of the variable. For example, source text <b>Hello { thing } world!</b> with <b> ai </b> as the value of variable 'thing' will result in the text being <b>Hello ai world!</b>."
|
|
||||||
variables-info2: "Because the evaluation of variables are performed from top to bottom, the variable cannot refer to another variables which appear on later lines. For example, when defining three variables <b>A</b>, <b>B</b> and <b>C</b>, variable <b>C</b> <i>can</i> refer to variables <b>A</b> and <b>B</b> in its expression. However, variable <b>A</b> <i>cannot</i> refer to variables <b>B</b> or <b>C</b> in its expression."
|
|
||||||
variables-info3: "To get an input from user, insert \"user input\" block with your desired variable name (that variable will be declared automatically). You could then use that variable to perform actions on your page."
|
|
||||||
variables-info4: "Functions make it easier to perform repetitive tasks. To create a function, declare a variable of \"Function\" type. A function can have a slot (argument/parameter) which can be used inside the function as a variable. Thanks to AiScript specification, you can also use function itself as a parameter for other functions. (Search \"callback functions\" on google for more details)."
|
|
||||||
more-details: "More information"
|
|
||||||
title: "Title"
|
title: "Title"
|
||||||
url: "Page URL"
|
url: "Page URL"
|
||||||
summary: "Page summary"
|
summary: "Page summary"
|
||||||
alignCenter: "Center elements"
|
alignCenter: "Center elements"
|
||||||
hide-title-when-pinned: "Hide page title when pinned"
|
hideTitleWhenPinned: "Hide page title when pinned to profile"
|
||||||
font: "Font"
|
font: "Font"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans serif"
|
fontSansSerif: "Sans serif"
|
||||||
set-eye-catching-image: "Set thumbnail image"
|
eyeCatchingImageSet: "Set the eye-catching image"
|
||||||
remove-eye-catching-image: "Remove thumbnail image"
|
eyeCatchingImageRemove: "Delete the eye-catching image"
|
||||||
chooseBlock: "Add a block"
|
chooseBlock: "Add a block"
|
||||||
selectType: "Select a type"
|
selectType: "Select a type"
|
||||||
enterVariableName: "Please enter a name for your variable"
|
enterVariableName: "Please enter a name for your variable"
|
||||||
the-variable-name-is-already-used: "This name is already being used by other variable"
|
variableNameIsAlreadyUsed: "This name is already being used by other variable"
|
||||||
content-blocks: "Content"
|
contentBlocks: "Content"
|
||||||
input-blocks: "Input"
|
inputBlocks: "Input"
|
||||||
special-blocks: "Special"
|
specialBlocks: "Special"
|
||||||
post-from-post-form: "Post this content"
|
|
||||||
posted-from-post-form: "Successfully posted!"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "Text"
|
text: "Text"
|
||||||
textarea: "Text area"
|
textarea: "Text area"
|
||||||
@ -702,6 +755,7 @@ _pages:
|
|||||||
post: "Compose a note"
|
post: "Compose a note"
|
||||||
_post:
|
_post:
|
||||||
text: "Content"
|
text: "Content"
|
||||||
|
canvasId: "Canvas ID"
|
||||||
textInput: "Text input"
|
textInput: "Text input"
|
||||||
_textInput:
|
_textInput:
|
||||||
name: "Variable name"
|
name: "Variable name"
|
||||||
@ -717,6 +771,11 @@ _pages:
|
|||||||
name: "Variable name"
|
name: "Variable name"
|
||||||
text: "Title"
|
text: "Title"
|
||||||
default: "Default value"
|
default: "Default value"
|
||||||
|
canvas: "Canvas"
|
||||||
|
_canvas:
|
||||||
|
id: "Canvas ID"
|
||||||
|
width: "Width"
|
||||||
|
height: "Height"
|
||||||
switch: "Switch"
|
switch: "Switch"
|
||||||
_switch:
|
_switch:
|
||||||
name: "Variable name"
|
name: "Variable name"
|
||||||
@ -742,6 +801,9 @@ _pages:
|
|||||||
message: "Message to display when activated"
|
message: "Message to display when activated"
|
||||||
variable: "Variable to send"
|
variable: "Variable to send"
|
||||||
no-variable: "None"
|
no-variable: "None"
|
||||||
|
callAiScript: "Invoke AiScript"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "Function name"
|
||||||
radioButton: "Choice"
|
radioButton: "Choice"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "Variable name"
|
name: "Variable name"
|
||||||
@ -902,6 +964,7 @@ _pages:
|
|||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "Text"
|
arg1: "Text"
|
||||||
ref: "Variables"
|
ref: "Variables"
|
||||||
|
aiScriptVar: "Variable of AiScript"
|
||||||
fn: "Functions"
|
fn: "Functions"
|
||||||
_fn:
|
_fn:
|
||||||
slots: "Slots"
|
slots: "Slots"
|
||||||
|
@ -35,6 +35,8 @@ unpin: "Desfijar"
|
|||||||
copyContent: "Copiar contenido"
|
copyContent: "Copiar contenido"
|
||||||
copyLink: "Copiar enlace"
|
copyLink: "Copiar enlace"
|
||||||
delete: "Borrar"
|
delete: "Borrar"
|
||||||
|
deleteAndEdit: "Borrar y editar"
|
||||||
|
deleteAndEditConfirm: "¿Quieres borrar y editar este nota? Las reacciones, renotes, respuestas y todo desaparecerán."
|
||||||
addToList: "Agregar a lista"
|
addToList: "Agregar a lista"
|
||||||
sendMessage: "Énviar mensaje"
|
sendMessage: "Énviar mensaje"
|
||||||
copyUsername: "Copiar nombre de usuario"
|
copyUsername: "Copiar nombre de usuario"
|
||||||
@ -58,7 +60,7 @@ lists: "Listas"
|
|||||||
noLists: "No tiene listas"
|
noLists: "No tiene listas"
|
||||||
note: "Notas"
|
note: "Notas"
|
||||||
notes: "Notas"
|
notes: "Notas"
|
||||||
following: "Sigue"
|
following: "Siguiendo"
|
||||||
followers: "Seguidores"
|
followers: "Seguidores"
|
||||||
followsYou: "Te sigue"
|
followsYou: "Te sigue"
|
||||||
createList: "Crear lista"
|
createList: "Crear lista"
|
||||||
@ -86,7 +88,6 @@ add: "Añadir"
|
|||||||
reaction: "Reacción"
|
reaction: "Reacción"
|
||||||
reactionSettingDescription: "Asigne sus reacción favoritas que desean anclar en el selector de reacciones."
|
reactionSettingDescription: "Asigne sus reacción favoritas que desean anclar en el selector de reacciones."
|
||||||
rememberNoteVisibility: "Recordar visibilidad"
|
rememberNoteVisibility: "Recordar visibilidad"
|
||||||
renameFile: "Renombrar archivo"
|
|
||||||
attachCancel: "Quitar adjunto"
|
attachCancel: "Quitar adjunto"
|
||||||
markAsSensitive: "Marcar como sensible"
|
markAsSensitive: "Marcar como sensible"
|
||||||
unmarkAsSensitive: "Desmarcar como sensible"
|
unmarkAsSensitive: "Desmarcar como sensible"
|
||||||
@ -116,6 +117,7 @@ loginFailed: "Error al iniciar sesión."
|
|||||||
showOnRemote: "Ver en una instancia remota"
|
showOnRemote: "Ver en una instancia remota"
|
||||||
general: "General"
|
general: "General"
|
||||||
wallpaper: "Fondo de pantalla"
|
wallpaper: "Fondo de pantalla"
|
||||||
|
setWallpaper: "Establecer fondo de pantalla"
|
||||||
removeWallpaper: "Quitar fondo de pantalla"
|
removeWallpaper: "Quitar fondo de pantalla"
|
||||||
searchWith: "Buscar: {q}"
|
searchWith: "Buscar: {q}"
|
||||||
youHaveNoLists: "No tienes listas"
|
youHaveNoLists: "No tienes listas"
|
||||||
@ -204,10 +206,13 @@ messaging: "Chat"
|
|||||||
upload: "Subir"
|
upload: "Subir"
|
||||||
fromDrive: "Desde el drive"
|
fromDrive: "Desde el drive"
|
||||||
fromUrl: "Desde la URL"
|
fromUrl: "Desde la URL"
|
||||||
|
uploadFromUrl: "Subir desde una URL"
|
||||||
|
uploadFromUrlDescription: "URL del fichero que quieres subir"
|
||||||
|
uploadFromUrlRequested: "Subida solicitada"
|
||||||
|
uploadFromUrlMayTakeTime: "Subir el fichero puede tardar un tiempo."
|
||||||
explore: "Explorar"
|
explore: "Explorar"
|
||||||
games: "Misskey Games"
|
games: "Misskey Games"
|
||||||
messageRead: "Ya leído"
|
messageRead: "Ya leído"
|
||||||
recentUsedEmojis: "Emojis usados recientemente"
|
|
||||||
noMoreHistory: "El historial se ha acabado"
|
noMoreHistory: "El historial se ha acabado"
|
||||||
startMessaging: "Iniciar chat"
|
startMessaging: "Iniciar chat"
|
||||||
nUsersRead: "Leído por {n} personas"
|
nUsersRead: "Leído por {n} personas"
|
||||||
@ -223,17 +228,30 @@ yearsOld: "{age} años"
|
|||||||
registeredDate: "Fecha de registro"
|
registeredDate: "Fecha de registro"
|
||||||
location: "Lugar"
|
location: "Lugar"
|
||||||
theme: "Tema"
|
theme: "Tema"
|
||||||
|
themeForLightMode: "Tema para usar en Modo Linterna"
|
||||||
|
themeForDarkMode: "Tema para usar en Modo Oscuro"
|
||||||
|
light: "Linterna"
|
||||||
|
dark: "Oscuro"
|
||||||
lightThemes: "Tema claro"
|
lightThemes: "Tema claro"
|
||||||
darkThemes: "Tema oscuro"
|
darkThemes: "Tema oscuro"
|
||||||
|
syncDeviceDarkMode: "Sincronice el Modo Oscuro con la configuración de su dispositivo"
|
||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
|
fileName: "Nombre de archivo"
|
||||||
selectFile: "Elegir archivo"
|
selectFile: "Elegir archivo"
|
||||||
selectFiles: "Elegir archivos"
|
selectFiles: "Elegir archivos"
|
||||||
renameFolder: "Renombrar carpeta"
|
renameFile: "Renombrar archivo"
|
||||||
|
folderName: "Nombre de la carpeta"
|
||||||
createFolder: "Crear carpeta"
|
createFolder: "Crear carpeta"
|
||||||
|
renameFolder: "Renombrar carpeta"
|
||||||
deleteFolder: "Borrar carpeta"
|
deleteFolder: "Borrar carpeta"
|
||||||
addFile: "Añadir archivo"
|
addFile: "Añadir archivo"
|
||||||
emptyDrive: "El drive está vacío"
|
emptyDrive: "El drive está vacío"
|
||||||
emptyFolder: "La carpeta está vacía"
|
emptyFolder: "La carpeta está vacía"
|
||||||
|
unableToDelete: "No se puede borrar"
|
||||||
|
inputNewFileName: "Ingrese un nuevo nombre de archivo"
|
||||||
|
inputNewFolderName: "Ingrese un nuevo nombre de la carpeta"
|
||||||
|
circularReferenceFolder: "La carpeta de destino es una sub-carpeta de la carpeta que quieres mover."
|
||||||
|
hasChildFilesOrFolders: "No se puede borrar esta carpeta. No está vacía."
|
||||||
copyUrl: "Copiar URL"
|
copyUrl: "Copiar URL"
|
||||||
rename: "Renombrar"
|
rename: "Renombrar"
|
||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
@ -247,6 +265,7 @@ watch: "Ver"
|
|||||||
unwatch: "Dejar de ver"
|
unwatch: "Dejar de ver"
|
||||||
accept: "Aceptar"
|
accept: "Aceptar"
|
||||||
reject: "Rechazar"
|
reject: "Rechazar"
|
||||||
|
normal: "Normal"
|
||||||
instanceName: "Nombre de la instancia"
|
instanceName: "Nombre de la instancia"
|
||||||
instanceDescription: "Descripción de la instancia"
|
instanceDescription: "Descripción de la instancia"
|
||||||
maintainerName: "Nombre del administrador"
|
maintainerName: "Nombre del administrador"
|
||||||
@ -301,6 +320,7 @@ notesAndReplies: "Notas y respuestas"
|
|||||||
withFiles: "Adjuntos"
|
withFiles: "Adjuntos"
|
||||||
silence: "Silenciar"
|
silence: "Silenciar"
|
||||||
silenceConfirm: "¿Desea silenciar al usuario?"
|
silenceConfirm: "¿Desea silenciar al usuario?"
|
||||||
|
unsilence: "Dejar de silenciar"
|
||||||
unsilenceConfirm: "¿Desea dejar de silenciar al usuario?"
|
unsilenceConfirm: "¿Desea dejar de silenciar al usuario?"
|
||||||
popularUsers: "Usuarios populares"
|
popularUsers: "Usuarios populares"
|
||||||
recentlyUpdatedUsers: "Usuarios activos recientemente"
|
recentlyUpdatedUsers: "Usuarios activos recientemente"
|
||||||
@ -387,13 +407,14 @@ strongPassword: "Muy buena contraseña"
|
|||||||
passwordMatched: "Correcto"
|
passwordMatched: "Correcto"
|
||||||
passwordNotMatched: "Las contraseñas no son las mismas"
|
passwordNotMatched: "Las contraseñas no son las mismas"
|
||||||
signinWith: "Inicie sesión con {x}"
|
signinWith: "Inicie sesión con {x}"
|
||||||
|
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos."
|
||||||
tapSecurityKey: "Toque la clave de seguridad"
|
tapSecurityKey: "Toque la clave de seguridad"
|
||||||
or: "O"
|
or: "O"
|
||||||
uiLanguage: "Idioma de visualización de la interfaz"
|
uiLanguage: "Idioma de visualización de la interfaz"
|
||||||
groupInvited: "Invitado al grupo"
|
groupInvited: "Invitado al grupo"
|
||||||
aboutX: "Acerca de {x}"
|
aboutX: "Acerca de {x}"
|
||||||
useOsNativeEmojis: "Usa los emojis nativos de la plataforma"
|
useOsNativeEmojis: "Usa los emojis nativos de la plataforma"
|
||||||
noGroups: "Sin grupos"
|
youHaveNoGroups: "Sin grupos"
|
||||||
joinOrCreateGroup: "Obtenga una invitación para unirse al grupos o puede crear su propio grupo."
|
joinOrCreateGroup: "Obtenga una invitación para unirse al grupos o puede crear su propio grupo."
|
||||||
noHistory: "No hay datos en el historial"
|
noHistory: "No hay datos en el historial"
|
||||||
disableAnimatedMfm: "Deshabilitar MFM que tiene animaciones"
|
disableAnimatedMfm: "Deshabilitar MFM que tiene animaciones"
|
||||||
@ -435,6 +456,8 @@ objectStorageRegion: "Region"
|
|||||||
objectStorageRegionDesc: "Especifique una región como 'xx-east-1'. Si su servicio no tiene distinción sobre regiones, déjelo en blanco o complete con 'us-east-1'."
|
objectStorageRegionDesc: "Especifique una región como 'xx-east-1'. Si su servicio no tiene distinción sobre regiones, déjelo en blanco o complete con 'us-east-1'."
|
||||||
objectStorageUseSSL: "Usar SSL"
|
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"
|
||||||
|
objectStorageUseProxyDesc: "Desactive esto si no va a usar Proxy para la conexión de Almacenamiento de objetos"
|
||||||
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"
|
||||||
@ -445,6 +468,38 @@ none: "Ninguna"
|
|||||||
volume: "Volumen"
|
volume: "Volumen"
|
||||||
details: "Detalles"
|
details: "Detalles"
|
||||||
chooseEmoji: "Elije un emoji"
|
chooseEmoji: "Elije un emoji"
|
||||||
|
unableToProcess: "La operación no se puede llevar a cabo"
|
||||||
|
recentUsed: "Usado recientemente"
|
||||||
|
install: "Instalación"
|
||||||
|
uninstall: "Desinstalar"
|
||||||
|
installedApps: "Aplicaciones Autorizadas"
|
||||||
|
nothing: "No hay nada que ver aqui"
|
||||||
|
installedDate: "Autorizado"
|
||||||
|
lastUsedDate: "Utilizado el"
|
||||||
|
state: "Estado"
|
||||||
|
sort: "Ordenar"
|
||||||
|
ascendingOrder: "Ascendente"
|
||||||
|
descendingOrder: "Descendente"
|
||||||
|
scratchpad: "Scratch pad"
|
||||||
|
scratchpadDescription: "Scratchpad proporciona un entorno experimental para AiScript. Puede escribir, ejecutar y verificar los resultados que interactúan con Misskey."
|
||||||
|
output: "Salida"
|
||||||
|
script: "Script"
|
||||||
|
disablePagesScript: "Deshabilitar AiScript en Páginas"
|
||||||
|
updateRemoteUser: "Actualizar información de usuario remoto"
|
||||||
|
deleteAllFiles: "Borrar todos los archivos"
|
||||||
|
deleteAllFilesConfirm: "¿Desea borrar todos los archivos?"
|
||||||
|
removeAllFollowing: "Retener todos los siguientes"
|
||||||
|
removeAllFollowingDescription: "Cancelar todos los siguientes del servidor {host}. Ejecutar en caso de que esta instancia haya dejado de existir"
|
||||||
|
userSuspended: "Este usuario ha sido suspendido."
|
||||||
|
userSilenced: "Este usuario ha sido silenciado."
|
||||||
|
_theme:
|
||||||
|
explore: "Explorar temas"
|
||||||
|
install: "Instalar tema"
|
||||||
|
manage: "Gestor de temas"
|
||||||
|
code: "Código del tema"
|
||||||
|
installed: "{name} ha sido instalado"
|
||||||
|
alreadyInstalled: "Este tema ya está instalado"
|
||||||
|
invalid: "El formato del tema no es válido"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Notas"
|
note: "Notas"
|
||||||
noteMy: "Nota (a mí mismo)"
|
noteMy: "Nota (a mí mismo)"
|
||||||
@ -529,7 +584,11 @@ _permissions:
|
|||||||
"write:user-groups": "Administrar grupos de usuarios"
|
"write:user-groups": "Administrar grupos de usuarios"
|
||||||
_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?"
|
||||||
permissionAsk: "Esta aplicación requiere los siguientes permisos"
|
permissionAsk: "Esta aplicación requiere los siguientes permisos"
|
||||||
|
pleaseGoBack: "Por favor, vuelve a la aplicación"
|
||||||
|
callback: "Volviendo a la aplicación"
|
||||||
|
denied: "Acceso denegado"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "Todas las notas"
|
all: "Todas las notas"
|
||||||
homeTimeline: "Notas de los usuarios que sigues"
|
homeTimeline: "Notas de los usuarios que sigues"
|
||||||
@ -633,15 +692,15 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "Pedidos"
|
requests: "Pedidos"
|
||||||
users: "Variación de usuarios"
|
users: "Variación de usuarios"
|
||||||
usersTotal: "Total de usuarios"
|
usersTotal: "Total acumulado de usuarios"
|
||||||
notes: "Variación de la cantidad de notas"
|
notes: "Variación de la cantidad de notas"
|
||||||
notesTotal: "Estimación de notas"
|
notesTotal: "Total acumulado de la cantidad de notas"
|
||||||
ff: "Variación de cantidad de seguidos/seguidores"
|
ff: "Variación de cantidad de seguidos/seguidores"
|
||||||
ffTotal: "Total de seguidos/seguidores"
|
ffTotal: "Total acumulado de cantidad de seguidos/seguidores"
|
||||||
cacheSize: "Variación del tamaño de la caché"
|
cacheSize: "Variación del tamaño de la caché"
|
||||||
cacheSizeTotal: "Total del tamaño de la caché"
|
cacheSizeTotal: "Total acumulado del tamaño de la caché"
|
||||||
files: "Variación de cantidad de archivos"
|
files: "Variación de cantidad de archivos"
|
||||||
filesTotal: "Total de archivos"
|
filesTotal: "Total acumulado de cantidad de archivos"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Inicio"
|
home: "Inicio"
|
||||||
local: "Local"
|
local: "Local"
|
||||||
@ -651,45 +710,39 @@ _pages:
|
|||||||
newPage: "Crear página"
|
newPage: "Crear página"
|
||||||
editPage: "Editar página"
|
editPage: "Editar página"
|
||||||
readPage: "Viendo la fuente"
|
readPage: "Viendo la fuente"
|
||||||
page-created: "La página fue creada"
|
created: "La página fue creada"
|
||||||
page-updated: "La página fue actualizada"
|
updated: "La página fue actualizada"
|
||||||
name-already-exists: "La URL de la página seleccionada ya existe"
|
deleted: "La página borrada"
|
||||||
title-invalid-name: "URL inválida"
|
nameAlreadyExists: "La URL de la página especificada ya existe"
|
||||||
text-invalid-name: "Verifique que no tenga espacios en blanco"
|
invalidNameTitle: "URL inválida"
|
||||||
|
invalidNameText: "Verifique que no tenga espacios en blanco"
|
||||||
editThisPage: "Editar esta página"
|
editThisPage: "Editar esta página"
|
||||||
viewSource: "Ver la fuente"
|
viewSource: "Ver la fuente"
|
||||||
viewPage: "Ver página"
|
viewPage: "Ver página"
|
||||||
like: "Me gusta"
|
like: "Me gusta"
|
||||||
unlike: "Quitar me gusta"
|
unlike: "Quitar me gusta"
|
||||||
liked-pages: "Páginas que me gustan"
|
my: "Mis páginas"
|
||||||
my-pages: "Mis páginas"
|
liked: "Páginas que me gustan"
|
||||||
inspector: "Inspector"
|
inspector: "Inspector"
|
||||||
content: "Bloque de página"
|
content: "Bloque de página"
|
||||||
variables: "Variables"
|
variables: "Variables"
|
||||||
variables-info: "Puedes crear una página dinámica usando variables. Al escribir el <b>{ nombre de la variable }</b> dentro del texto, se puede embeber el valor de la variable allí. Por ejemplo, si en el texto <b>¡Hola { thing } mundo!</b> el valor de la variable (thing) es <b>ai</b>, el texto se vuelve <b>¡Hola ai mundo!</b>"
|
|
||||||
variables-info2: "La evaluación de las variables (el cálculo de los valores) se hace de arriba a abajo, por eso una variable no puede referenciar a otra que esté debajo. Por ejemplo, cuando se definen las variables <b>A、B、C</b>, <b>C</b> puede referenciar a <b>A</b> o <b>B</b>, pero <b>A</b> no puede referenciar a <b>B</b> ni a <b>C</b>."
|
|
||||||
variables-info3: "Para recibir la entrada del usuario, agregue un bloque \"entrada de usuario\" en la página, y configure el nombre de las variables que desea almacenar en el campo \"nombre de variables\" (Las variables se crearán automáticamente). Se ejecutaran acciones en base a la entrada del usuario de esas variables."
|
|
||||||
variables-info4: "Al usar funciones, se pueden agrupar el cálculo de valores de forma reutilizable. Para crear una función, se crea una variable de tipo \"función\". A la función de le puede configurar un slot (argumento), y el valor del slot está disponible como variable dentro de la función. También existen funciones que usan funciones como argumentos bajo el estandar AiScript (llamadas funciones de orden superior). Además de las funciones definidas previamente, se pueden definir funciones al momento en los slots de las funciones de orden superior."
|
|
||||||
more-details: "Más detalles"
|
|
||||||
title: "Título"
|
title: "Título"
|
||||||
url: "URL de la página"
|
url: "URL de la página"
|
||||||
summary: "Resumen de la página"
|
summary: "Resumen de la página"
|
||||||
alignCenter: "Centrar"
|
alignCenter: "Centrar"
|
||||||
hide-title-when-pinned: "Ocultar el título de la página al fijarse"
|
hideTitleWhenPinned: "Ocultar el título de la página al fijarse"
|
||||||
font: "Fuente"
|
font: "Fuente"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans Serif"
|
fontSansSerif: "Sans Serif"
|
||||||
set-eye-catching-image: "Elegir imagen llamativa"
|
eyeCatchingImageSet: "Elegir imagen llamativa"
|
||||||
remove-eye-catching-image: "Borrar imagen llamativa"
|
eyeCatchingImageRemove: "Borrar imagen llamativa"
|
||||||
chooseBlock: "Agregar bloque"
|
chooseBlock: "Agregar bloque"
|
||||||
selectType: "Elegir tipo"
|
selectType: "Elegir tipo"
|
||||||
enterVariableName: "Ingrese el nombre de la variable"
|
enterVariableName: "Ingrese el nombre de la variable"
|
||||||
the-variable-name-is-already-used: "El nombre de la variable ya está en uso"
|
variableNameIsAlreadyUsed: "El nombre de la variable ya está en uso"
|
||||||
content-blocks: "Contenido"
|
contentBlocks: "Contenido"
|
||||||
input-blocks: "Entrada"
|
inputBlocks: "Entrada"
|
||||||
special-blocks: "Especial"
|
specialBlocks: "Especial"
|
||||||
post-from-post-form: "Postear este contenido"
|
|
||||||
posted-from-post-form: "Posteado"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "Texto"
|
text: "Texto"
|
||||||
textarea: "Área de texto"
|
textarea: "Área de texto"
|
||||||
@ -702,6 +755,7 @@ _pages:
|
|||||||
post: "Formulario"
|
post: "Formulario"
|
||||||
_post:
|
_post:
|
||||||
text: "Contenido"
|
text: "Contenido"
|
||||||
|
canvasId: "Lienzo ID"
|
||||||
textInput: "Entrada de texto"
|
textInput: "Entrada de texto"
|
||||||
_textInput:
|
_textInput:
|
||||||
name: "Nombre de variable"
|
name: "Nombre de variable"
|
||||||
@ -717,6 +771,11 @@ _pages:
|
|||||||
name: "Nombre de variable"
|
name: "Nombre de variable"
|
||||||
text: "Título"
|
text: "Título"
|
||||||
default: "Valor predeterminado"
|
default: "Valor predeterminado"
|
||||||
|
canvas: "Lienzo"
|
||||||
|
_canvas:
|
||||||
|
id: "Lienzo ID"
|
||||||
|
width: "Ancho"
|
||||||
|
height: "Altura"
|
||||||
switch: "Interruptor"
|
switch: "Interruptor"
|
||||||
_switch:
|
_switch:
|
||||||
name: "Nombre de variable"
|
name: "Nombre de variable"
|
||||||
@ -742,6 +801,9 @@ _pages:
|
|||||||
message: "Mensaje mostrado al apretar"
|
message: "Mensaje mostrado al apretar"
|
||||||
variable: "Variable a enviar"
|
variable: "Variable a enviar"
|
||||||
no-variable: "Ninguna"
|
no-variable: "Ninguna"
|
||||||
|
callAiScript: "Invocar AiScript"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "Nombre de la función"
|
||||||
radioButton: "Botón de opción"
|
radioButton: "Botón de opción"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "Nombre de variable"
|
name: "Nombre de variable"
|
||||||
@ -902,6 +964,7 @@ _pages:
|
|||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "Texto"
|
arg1: "Texto"
|
||||||
ref: "Variables"
|
ref: "Variables"
|
||||||
|
aiScriptVar: "Variable de AiScript"
|
||||||
fn: "funciones"
|
fn: "funciones"
|
||||||
_fn:
|
_fn:
|
||||||
slots: "Slots"
|
slots: "Slots"
|
||||||
|
@ -35,13 +35,15 @@ unpin: "Désépingler"
|
|||||||
copyContent: "Copier le contenu"
|
copyContent: "Copier le contenu"
|
||||||
copyLink: "Copier le lien"
|
copyLink: "Copier le lien"
|
||||||
delete: "Supprimer"
|
delete: "Supprimer"
|
||||||
|
deleteAndEdit: "Supprimer et réécrire"
|
||||||
|
deleteAndEditConfirm: "Êtes-vous sûr de vouloir effacer cette note et la modifier ? Vous perdrez toutes les réactions, renotes et réponses."
|
||||||
addToList: "Ajouter à une liste"
|
addToList: "Ajouter à une liste"
|
||||||
sendMessage: "Envoyer un message"
|
sendMessage: "Envoyer un message"
|
||||||
copyUsername: "Copier le nom d'utilisateur"
|
copyUsername: "Copier le nom d'utilisateur"
|
||||||
reply: "Répondre"
|
reply: "Répondre"
|
||||||
loadMore: "Voir plus"
|
loadMore: "Voir plus"
|
||||||
youGotNewFollower: "Vous a abonnés"
|
youGotNewFollower: "Vous suit"
|
||||||
receiveFollowRequest: "Demande de abonnés reçue"
|
receiveFollowRequest: "Demande de suivi reçue"
|
||||||
followRequestAccepted: "L'abonne la demande acceptée"
|
followRequestAccepted: "L'abonne la demande acceptée"
|
||||||
mentions: "Mentions"
|
mentions: "Mentions"
|
||||||
directNotes: "Messages directs"
|
directNotes: "Messages directs"
|
||||||
@ -51,7 +53,7 @@ export: "Exporter"
|
|||||||
files: "Fichier·s"
|
files: "Fichier·s"
|
||||||
download: "Télécharger"
|
download: "Télécharger"
|
||||||
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\" ? Les notes avec ce fichier joint seront aussi supprimées."
|
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\" ? Les notes avec ce fichier joint seront aussi supprimées."
|
||||||
unfollowConfirm: "Êtes-vous sûr·de ne plus vouloir abonne {name} ?"
|
unfollowConfirm: "Se désabonner de {name} ?"
|
||||||
exportRequested: "Vous avez demandé une exportation. Cela pourrait prendre un peu de temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
|
exportRequested: "Vous avez demandé une exportation. Cela pourrait prendre un peu de temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
|
||||||
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
|
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
|
||||||
lists: "Listes"
|
lists: "Listes"
|
||||||
@ -60,17 +62,17 @@ note: "Note"
|
|||||||
notes: "Notes"
|
notes: "Notes"
|
||||||
following: "Abonnements"
|
following: "Abonnements"
|
||||||
followers: "Abonné·e·s"
|
followers: "Abonné·e·s"
|
||||||
followsYou: "Votre abonné"
|
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: "Une erreur est survenue"
|
||||||
retry: "Réessayer"
|
retry: "Réessayer"
|
||||||
enterListName: "Nom de la liste"
|
enterListName: "Nom de la liste"
|
||||||
privacy: "Vie privée"
|
privacy: "Vie privée"
|
||||||
makeFollowManuallyApprove: "Demandes d’abonnements requiert l’approbation"
|
makeFollowManuallyApprove: "Demandes d’suivi requiert l'approbation"
|
||||||
defaultNoteVisibility: "Visibilité par défaut"
|
defaultNoteVisibility: "Visibilité par défaut"
|
||||||
follow: "Abonnement"
|
follow: "Suivre"
|
||||||
followRequest: "Demande d’abonnement"
|
followRequest: "Demande d’suivre"
|
||||||
followRequests: "Demandes d’abonnement"
|
followRequests: "Demandes d’abonnement"
|
||||||
unfollow: "Se désabonner"
|
unfollow: "Se désabonner"
|
||||||
followRequestPending: "En attente d’approbation"
|
followRequestPending: "En attente d’approbation"
|
||||||
@ -86,7 +88,6 @@ add: "Ajouter"
|
|||||||
reaction: "Réactions"
|
reaction: "Réactions"
|
||||||
reactionSettingDescription: "Attribuez vos réactions préférées qui souhaitent épingler le sélecteur de réaction."
|
reactionSettingDescription: "Attribuez vos réactions préférées qui souhaitent épingler le sélecteur de réaction."
|
||||||
rememberNoteVisibility: "Se souvenir de la visibilité des notes"
|
rememberNoteVisibility: "Se souvenir de la visibilité des notes"
|
||||||
renameFile: "Renommer le ficher"
|
|
||||||
attachCancel: "Enlever le fichier attaché"
|
attachCancel: "Enlever le fichier attaché"
|
||||||
markAsSensitive: "Marquer comme sensible"
|
markAsSensitive: "Marquer comme sensible"
|
||||||
unmarkAsSensitive: "Enlever le marquage comme sensible"
|
unmarkAsSensitive: "Enlever le marquage comme sensible"
|
||||||
@ -116,10 +117,11 @@ loginFailed: "Échec de la connexion"
|
|||||||
showOnRemote: "Voir sur l'instance distante"
|
showOnRemote: "Voir sur l'instance distante"
|
||||||
general: "Général"
|
general: "Général"
|
||||||
wallpaper: "Arrière plan"
|
wallpaper: "Arrière plan"
|
||||||
|
setWallpaper: "Définir le fond d'écran"
|
||||||
removeWallpaper: "Supprimer l'arrière plan"
|
removeWallpaper: "Supprimer l'arrière plan"
|
||||||
searchWith: "Recherche : {q}"
|
searchWith: "Recherche : {q}"
|
||||||
youHaveNoLists: "Vous n'avez aucune liste"
|
youHaveNoLists: "Vous n'avez aucune liste"
|
||||||
followConfirm: "Désirez-vous abonne {name} ?"
|
followConfirm: "Désirez-vous suivre {name} ?"
|
||||||
proxyAccount: "Compte proxy"
|
proxyAccount: "Compte proxy"
|
||||||
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant pour les utilisateurs d'autres instances.\nExemple : quand un·e utilisateur·rice distant·e est ajouté·e à une liste, ses notes ne serait pas visibles sur l'instance si personne ne le·la abonné. Le compte proxy va donc le·la abonne pour que ses notes soient acheminées."
|
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant pour les utilisateurs d'autres instances.\nExemple : quand un·e utilisateur·rice distant·e est ajouté·e à une liste, ses notes ne serait pas visibles sur l'instance si personne ne le·la abonné. Le compte proxy va donc le·la abonne pour que ses notes soient acheminées."
|
||||||
host: "Hôte"
|
host: "Hôte"
|
||||||
@ -190,7 +192,7 @@ newPassword: "Nouveau mot de passe"
|
|||||||
newPasswordRetype: "Nouveau mot de passe (répéter)"
|
newPasswordRetype: "Nouveau mot de passe (répéter)"
|
||||||
attachFile: "Joindre un fichier"
|
attachFile: "Joindre un fichier"
|
||||||
more: "Plus !"
|
more: "Plus !"
|
||||||
featured: "Surlignage"
|
featured: "Tendances"
|
||||||
usernameOrUserId: "Nom d'utilisateur ou ID utilisateur"
|
usernameOrUserId: "Nom d'utilisateur ou ID utilisateur"
|
||||||
noSuchUser: "Utilisateur non trouvé"
|
noSuchUser: "Utilisateur non trouvé"
|
||||||
lookup: "Recherche"
|
lookup: "Recherche"
|
||||||
@ -204,12 +206,15 @@ messaging: "Discuter"
|
|||||||
upload: "Téléchargez"
|
upload: "Téléchargez"
|
||||||
fromDrive: "Depuis le Drive"
|
fromDrive: "Depuis le Drive"
|
||||||
fromUrl: "De l'URL"
|
fromUrl: "De l'URL"
|
||||||
|
uploadFromUrl: "Téléverser via une URL"
|
||||||
|
uploadFromUrlDescription: "URL du fichier que vous souhaitez téléverser"
|
||||||
|
uploadFromUrlRequested: "Téléversement demandé"
|
||||||
|
uploadFromUrlMayTakeTime: "Le téléversement de votre fichier peut prendre un certain temps."
|
||||||
explore: "Découvrir"
|
explore: "Découvrir"
|
||||||
games: "Jeux de Misskey"
|
games: "Jeux de Misskey"
|
||||||
messageRead: "Lus"
|
messageRead: "Lus"
|
||||||
recentUsedEmojis: "Emoji récemment utilisé"
|
|
||||||
noMoreHistory: "Plus d'histoire passée"
|
noMoreHistory: "Plus d'histoire passée"
|
||||||
startMessaging: "Commencer à écrire un discutez"
|
startMessaging: "Commencer à discuter"
|
||||||
nUsersRead: "{n} personnes ont lu"
|
nUsersRead: "{n} personnes ont lu"
|
||||||
agreeTo: "D'accord {0}"
|
agreeTo: "D'accord {0}"
|
||||||
tos: "Conditions d'utilisation"
|
tos: "Conditions d'utilisation"
|
||||||
@ -223,17 +228,30 @@ yearsOld: "{age} ans"
|
|||||||
registeredDate: "Date de création"
|
registeredDate: "Date de création"
|
||||||
location: "Localisation"
|
location: "Localisation"
|
||||||
theme: "Thème"
|
theme: "Thème"
|
||||||
|
themeForLightMode: "Thème à utiliser en Mode Lumière"
|
||||||
|
themeForDarkMode: "Thème à utiliser en Mode Sombre"
|
||||||
|
light: "Lumière"
|
||||||
|
dark: "Sombre"
|
||||||
lightThemes: "Thème lumineux"
|
lightThemes: "Thème lumineux"
|
||||||
darkThemes: "Thème sombre"
|
darkThemes: "Thème sombre"
|
||||||
|
syncDeviceDarkMode: "Synchronisez le mode sombre avec les paramètres de votre appareil"
|
||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
|
fileName: "Nom du fichier"
|
||||||
selectFile: "Choisir le fichier"
|
selectFile: "Choisir le fichier"
|
||||||
selectFiles: "Choisir le fichiers"
|
selectFiles: "Choisir le fichiers"
|
||||||
renameFolder: "Renommer le dossier"
|
renameFile: "Renommer le ficher"
|
||||||
|
folderName: "Nom du dossier"
|
||||||
createFolder: "Créer un dossier"
|
createFolder: "Créer un dossier"
|
||||||
|
renameFolder: "Renommer le dossier"
|
||||||
deleteFolder: "Supprimer le dossier"
|
deleteFolder: "Supprimer le dossier"
|
||||||
addFile: "Ajoutez un fichier"
|
addFile: "Ajoutez un fichier"
|
||||||
emptyDrive: "Le Drive est vide"
|
emptyDrive: "Le Drive est vide"
|
||||||
emptyFolder: "Le dossier est vide"
|
emptyFolder: "Le dossier est vide"
|
||||||
|
unableToDelete: "Ne peut pas être supprimé"
|
||||||
|
inputNewFileName: "Entrez un nouveau nom de fichier"
|
||||||
|
inputNewFolderName: "Entrez un nouveau nom de dossier"
|
||||||
|
circularReferenceFolder: "Le dossier de destination est un sous-dossier du dossier que vous souhaitez déplacer."
|
||||||
|
hasChildFilesOrFolders: "Ce dossier n'est pas vide, il ne peut pas être supprimé"
|
||||||
copyUrl: "Copier l’URL"
|
copyUrl: "Copier l’URL"
|
||||||
rename: "Renommer"
|
rename: "Renommer"
|
||||||
avatar: "Avatar"
|
avatar: "Avatar"
|
||||||
@ -247,6 +265,7 @@ watch: "Surveiller"
|
|||||||
unwatch: "Ne plus surveiller"
|
unwatch: "Ne plus surveiller"
|
||||||
accept: "Autoriser"
|
accept: "Autoriser"
|
||||||
reject: "Refuser"
|
reject: "Refuser"
|
||||||
|
normal: "Normal"
|
||||||
instanceName: "Nom de l’instance"
|
instanceName: "Nom de l’instance"
|
||||||
instanceDescription: "Description de l’instance"
|
instanceDescription: "Description de l’instance"
|
||||||
maintainerName: "Nom d'administrateur"
|
maintainerName: "Nom d'administrateur"
|
||||||
@ -301,6 +320,7 @@ notesAndReplies: "Notes et Répondres"
|
|||||||
withFiles: "Avec fichiers joints"
|
withFiles: "Avec fichiers joints"
|
||||||
silence: "Mettre en masquer"
|
silence: "Mettre en masquer"
|
||||||
silenceConfirm: "Mettre l'utilisateur sous masquer ?"
|
silenceConfirm: "Mettre l'utilisateur sous masquer ?"
|
||||||
|
unsilence: "Annuler la masquer"
|
||||||
unsilenceConfirm: "Voulez-vous annuler le masquer ?"
|
unsilenceConfirm: "Voulez-vous annuler le masquer ?"
|
||||||
popularUsers: "Utilisateur·rice·s populaires"
|
popularUsers: "Utilisateur·rice·s populaires"
|
||||||
recentlyUpdatedUsers: "Utilisateur·rice·s actif·ve·s récemment"
|
recentlyUpdatedUsers: "Utilisateur·rice·s actif·ve·s récemment"
|
||||||
@ -387,13 +407,14 @@ strongPassword: "Fort mot de passe"
|
|||||||
passwordMatched: "Correcte"
|
passwordMatched: "Correcte"
|
||||||
passwordNotMatched: "Ne correspond pas"
|
passwordNotMatched: "Ne correspond pas"
|
||||||
signinWith: "Connectez-vous avec {x}"
|
signinWith: "Connectez-vous avec {x}"
|
||||||
|
signinFailed: "Échec d’authentification. Veuillez vérifier que votre nom d’utilisateur et mot de passe sont corrects."
|
||||||
tapSecurityKey: "Touchez la clé de sécurité"
|
tapSecurityKey: "Touchez la clé de sécurité"
|
||||||
or: "OU"
|
or: "OU"
|
||||||
uiLanguage: "Langue d'affichage de l'interface"
|
uiLanguage: "Langue d'affichage de l'interface"
|
||||||
groupInvited: "Invité au groupe"
|
groupInvited: "Invité au groupe"
|
||||||
aboutX: "À propos de {x}"
|
aboutX: "À propos de {x}"
|
||||||
useOsNativeEmojis: "Utilisez les emojis natifs de la plateforme"
|
useOsNativeEmojis: "Utilisez les emojis natifs de la plateforme"
|
||||||
noGroups: "Pas de groupes"
|
youHaveNoGroups: "Vous n'avez aucune groupe"
|
||||||
joinOrCreateGroup: "Soyez invité à rejoindre les groupes ou vous pouvez créer votre propre groupe."
|
joinOrCreateGroup: "Soyez invité à rejoindre les groupes ou vous pouvez créer votre propre groupe."
|
||||||
noHistory: "Pas d'historique"
|
noHistory: "Pas d'historique"
|
||||||
disableAnimatedMfm: "Désactiver MFM qui a des animations"
|
disableAnimatedMfm: "Désactiver MFM qui a des animations"
|
||||||
@ -435,6 +456,8 @@ objectStorageRegion: "Region"
|
|||||||
objectStorageRegionDesc: "Spécifiez une région comme 'xx-east-1'. Si votre service ne fait pas de distinction entre les régions, laissez-le vide ou remplissez 'us-east-1'."
|
objectStorageRegionDesc: "Spécifiez une région comme 'xx-east-1'. Si votre service ne fait pas de distinction entre les régions, laissez-le vide ou remplissez 'us-east-1'."
|
||||||
objectStorageUseSSL: "Utiliser SSL"
|
objectStorageUseSSL: "Utiliser SSL"
|
||||||
objectStorageUseSSLDesc: "Désactivez-le si vous n'utilisez pas HTTPS pour la connexion API"
|
objectStorageUseSSLDesc: "Désactivez-le si vous n'utilisez pas HTTPS pour la connexion API"
|
||||||
|
objectStorageUseProxy: "Se connecter via proxy"
|
||||||
|
objectStorageUseProxyDesc: "Désactivez-le si vous n'utilisez pas Proxy pour la connexion de stockage d'objets"
|
||||||
serverLogs: "Journaux serveur"
|
serverLogs: "Journaux serveur"
|
||||||
deleteAll: "Supprimer tout"
|
deleteAll: "Supprimer tout"
|
||||||
showFixedPostForm: "Afficher le formulaire en haut du fil d'actualité"
|
showFixedPostForm: "Afficher le formulaire en haut du fil d'actualité"
|
||||||
@ -445,6 +468,38 @@ none: "Rien"
|
|||||||
volume: "Volume"
|
volume: "Volume"
|
||||||
details: "Détails"
|
details: "Détails"
|
||||||
chooseEmoji: "Choisissez des emojis"
|
chooseEmoji: "Choisissez des emojis"
|
||||||
|
unableToProcess: "L'opération n'a pas pu être complétée"
|
||||||
|
recentUsed: "Récemment utilisé"
|
||||||
|
install: "Installation"
|
||||||
|
uninstall: "Désinstaller"
|
||||||
|
installedApps: "Applications Autorisées"
|
||||||
|
nothing: "Il n'y a rien à voir ici"
|
||||||
|
installedDate: "Autorisé"
|
||||||
|
lastUsedDate: "Dernière utilisation"
|
||||||
|
state: "État"
|
||||||
|
sort: "Trier"
|
||||||
|
ascendingOrder: "Ascendant"
|
||||||
|
descendingOrder: "Descendant"
|
||||||
|
scratchpad: "Scratch pad"
|
||||||
|
scratchpadDescription: "Scratchpad fournit un environnement expérimental pour AiScript. Vous pouvez écrire, exécuter et vérifier les résultats qui interagissent avec Misskey."
|
||||||
|
output: "Sortie"
|
||||||
|
script: "Script"
|
||||||
|
disablePagesScript: "Désactiver AiScript sur les Pages"
|
||||||
|
updateRemoteUser: "Mettre à jour les informations de l’utilisateur·rice distant·e"
|
||||||
|
deleteAllFiles: "Supprimer tous les fichiers"
|
||||||
|
deleteAllFilesConfirm: "Êtes vous surs de vouloir supprimer tous les fichiers ?"
|
||||||
|
removeAllFollowing: "Retenir tous les abonnements"
|
||||||
|
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Exécutez cette commande si l'instance n'existe plus."
|
||||||
|
userSuspended: "Cette utilisateur·trice a été suspendue."
|
||||||
|
userSilenced: "Cette utilisateur·trice a été masquer."
|
||||||
|
_theme:
|
||||||
|
explore: "Explorer les thèmes"
|
||||||
|
install: "Installer un thème"
|
||||||
|
manage: "Gestion des thèmes"
|
||||||
|
code: "Code du thème"
|
||||||
|
installed: "{name} a été installé"
|
||||||
|
alreadyInstalled: "Ce thème est déjà installé"
|
||||||
|
invalid: "Le format du thème n'est pas valide"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Nouvelle note"
|
note: "Nouvelle note"
|
||||||
noteMy: "Ma note"
|
noteMy: "Ma note"
|
||||||
@ -493,7 +548,7 @@ _tutorial:
|
|||||||
step7_3: "Alors, profitez de Misskey 🚀"
|
step7_3: "Alors, profitez de Misskey 🚀"
|
||||||
_2fa:
|
_2fa:
|
||||||
alreadyRegistered: "Cette étape à déjà été complétée"
|
alreadyRegistered: "Cette étape à déjà été complétée"
|
||||||
registerDevice: "S’inscrire l'appareil"
|
registerDevice: "Ajouter un appareil"
|
||||||
registerKey: "S’inscrire la clé"
|
registerKey: "S’inscrire la clé"
|
||||||
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
|
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
|
||||||
step2: "Ensuite, scannez le code QR affiché avec l'application."
|
step2: "Ensuite, scannez le code QR affiché avec l'application."
|
||||||
@ -529,7 +584,11 @@ _permissions:
|
|||||||
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
|
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
|
||||||
_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?"
|
||||||
permissionAsk: "Cette application nécessite les autorisations suivantes "
|
permissionAsk: "Cette application nécessite les autorisations suivantes "
|
||||||
|
pleaseGoBack: "Veillez retourner à l'application"
|
||||||
|
callback: "Retour vers l’application"
|
||||||
|
denied: "Accès refusé"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "Toutes les notes"
|
all: "Toutes les notes"
|
||||||
homeTimeline: "Notes de l'utilisateur auquel je m'abonne"
|
homeTimeline: "Notes de l'utilisateur auquel je m'abonne"
|
||||||
@ -620,7 +679,7 @@ _charts:
|
|||||||
federationInstancesIncDec: "Variation du nombre d'instances"
|
federationInstancesIncDec: "Variation du nombre d'instances"
|
||||||
federationInstancesTotal: "Nombre d'instances au total"
|
federationInstancesTotal: "Nombre d'instances au total"
|
||||||
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
|
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
|
||||||
usersTotal: "Nombre d'utilsateur·rice·s au total"
|
usersTotal: "Nombre d'utilisateur·rice·s au total"
|
||||||
activeUsers: "Utilisateur·rice·s actif·ve·s"
|
activeUsers: "Utilisateur·rice·s actif·ve·s"
|
||||||
notesIncDec: "Variation du nombre d'notes"
|
notesIncDec: "Variation du nombre d'notes"
|
||||||
localNotesIncDec: "Variation du nombre de notes local"
|
localNotesIncDec: "Variation du nombre de notes local"
|
||||||
@ -633,15 +692,15 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "Requêtes"
|
requests: "Requêtes"
|
||||||
users: "Variation du nombre d'utilisateur·rice·s"
|
users: "Variation du nombre d'utilisateur·rice·s"
|
||||||
usersTotal: "Somme du nombre d'utilisateur·rice·s accumulés"
|
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
|
||||||
notes: "Variation du nombre d'notes"
|
notes: "Variation du nombre d'notes"
|
||||||
notesTotal: "Somme du nombre d’notes accumulés"
|
notesTotal: "Nombre d'notes au total cumulé"
|
||||||
ff: "Variation des abonné·e·s"
|
ff: "Variation des abonné·e·s"
|
||||||
ffTotal: "Somme du nombre d'abonnements accumulés"
|
ffTotal: "Nombre d'abonné·e·s au total cumulé"
|
||||||
cacheSize: "Variation de la taille du cache"
|
cacheSize: "Variation de la taille du cache"
|
||||||
cacheSizeTotal: "Somme de la taille du cache accumulé"
|
cacheSizeTotal: "La taille du cache au total cumulé"
|
||||||
files: "Variation du nombre de fichiers"
|
files: "Variation du nombre de fichiers"
|
||||||
filesTotal: "Somme du nombre de fichiers accumulés"
|
filesTotal: "Nombre de fichiers au total cumulé"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Principal"
|
home: "Principal"
|
||||||
local: "Local"
|
local: "Local"
|
||||||
@ -651,45 +710,39 @@ _pages:
|
|||||||
newPage: "Créer une page"
|
newPage: "Créer une page"
|
||||||
editPage: "Modifier une page"
|
editPage: "Modifier une page"
|
||||||
readPage: "Voir la source"
|
readPage: "Voir la source"
|
||||||
page-created: "Page a été créée !"
|
created: "La page a été créée !"
|
||||||
page-updated: "A mis à jour la page"
|
updated: "La page a été mise à jour !"
|
||||||
name-already-exists: "Une page portant le même nom existe déjà"
|
deleted: "La page a bien été supprimée"
|
||||||
title-invalid-name: "L’URL de la page spécifiée n’est pas valide"
|
nameAlreadyExists: "La URL de page spécifiée existe déjà"
|
||||||
text-invalid-name: "Assurez-vous qu'il n'est pas vide"
|
invalidNameTitle: "La URL de la page spécifiée n’est pas valide"
|
||||||
|
invalidNameText: "Assurez-vous qu'il n'est pas vide"
|
||||||
editThisPage: "Éditer cette page"
|
editThisPage: "Éditer cette page"
|
||||||
viewSource: "Afficher la source"
|
viewSource: "Afficher la source"
|
||||||
viewPage: "Afficher la page"
|
viewPage: "Afficher la page"
|
||||||
like: "Favori"
|
like: "Favori"
|
||||||
unlike: "Je n’favoris pas"
|
unlike: "Je n’favoris pas"
|
||||||
liked-pages: "Pages favoris"
|
my: "Mes pages"
|
||||||
my-pages: "Mes pages"
|
liked: "Pages favoris"
|
||||||
inspector: "Inspecteur"
|
inspector: "Inspecteur"
|
||||||
content: "Bloc de page"
|
content: "Bloc de page"
|
||||||
variables: "Variables"
|
variables: "Variables"
|
||||||
variables-info: "Vous pouvez créer une page dynamique à l'aide de variables. En tapant le <b>{nom de variable}</b> dans le texte, vous pouvez y incorporer la valeur de la variable. Par exemple, si dans le texte <b>Bonjour {chose} monde!</b> la valeur de la variable (chose) est <b>ai</b>, le texte devient est <b>Bonjour ai monde!</b>."
|
|
||||||
variables-info2: "L'évaluation des variables (le calcul des valeurs) se fait de haut en bas, donc l'variable ne peut pas se référer à une autre qui est en dessous. Par exemple, lorsque les variables <b>A、B、C</b> sont définies, <b>C</b> peut faire référence à <b>A</b> ou <b>B</b>, mais <b>A</b> ne peut pas faire référence à <b>B</b> ou <b>C</b>."
|
|
||||||
variables-info3: "Pour recevoir une entrée utilisateur, ajoutez un bloc \"Entrée\" sur la page et définissez le nom des variables que vous souhaitez stocker dans le champ \"Nom de la variable\" (les variables seront créées automatiquement). Les actions seront exécutées en fonction de l'entrée utilisateur de ces variables."
|
|
||||||
variables-info4: "Les fonctions vous permettent d'organiser le processus de calcul des valeurs sous une forme réutilisable. Pour créer une fonction, créez une variable de type \"fonction\". Une fonction peut avoir un slot (argument) et sa valeur peut être utilisée comme variable dans la fonction. Il existe également une fonction qui prend une fonction comme argument dans la norme AiScript (appelée fonction d'ordre supérieur). En plus des fonctions prédéfinies, elles peuvent être définies instantanément dans ces emplacements de fonction d'ordre supérieur."
|
|
||||||
more-details: "Description"
|
|
||||||
title: "Titre"
|
title: "Titre"
|
||||||
url: "URL de page"
|
url: "URL de page"
|
||||||
summary: "Résumé de page"
|
summary: "Résumé de page"
|
||||||
alignCenter: "Centrée"
|
alignCenter: "Centrée"
|
||||||
hide-title-when-pinned: "Masquer le titre de la page lorsque celle-ci est épinglée au profil"
|
hideTitleWhenPinned: "Masquer le titre de la page lorsque celle-ci est épinglée au profil"
|
||||||
font: "Police de caractères"
|
font: "Police de caractères"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans Serif"
|
fontSansSerif: "Sans Serif"
|
||||||
set-eye-catching-image: "Définir une image attirante"
|
eyeCatchingImageSet: "Définir une image attirante"
|
||||||
remove-eye-catching-image: "Supprimer une image attirante"
|
eyeCatchingImageRemove: "Supprimer une image attirante"
|
||||||
chooseBlock: "Ajouter un bloc"
|
chooseBlock: "Ajouter un bloc"
|
||||||
selectType: "Choisir un type"
|
selectType: "Choisir un type"
|
||||||
enterVariableName: "Veuillez entrer un nom de variable"
|
enterVariableName: "Veuillez entrer un nom de variable"
|
||||||
the-variable-name-is-already-used: "Cette variable est déjà utilisée"
|
variableNameIsAlreadyUsed: "Cette variable est déjà utilisée"
|
||||||
content-blocks: "Contenu"
|
contentBlocks: "Contenu"
|
||||||
input-blocks: "Entrée"
|
inputBlocks: "Entrée"
|
||||||
special-blocks: "Spécial"
|
specialBlocks: "Spécial"
|
||||||
post-from-post-form: "Publier ce contenu"
|
|
||||||
posted-from-post-form: "Publié !"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "Texte"
|
text: "Texte"
|
||||||
textarea: "Zone de texte"
|
textarea: "Zone de texte"
|
||||||
@ -702,6 +755,7 @@ _pages:
|
|||||||
post: "Formulaire à publier"
|
post: "Formulaire à publier"
|
||||||
_post:
|
_post:
|
||||||
text: "Contenu"
|
text: "Contenu"
|
||||||
|
canvasId: "Toile ID"
|
||||||
textInput: "Entrée de textuelle"
|
textInput: "Entrée de textuelle"
|
||||||
_textInput:
|
_textInput:
|
||||||
name: "Nom de la variable"
|
name: "Nom de la variable"
|
||||||
@ -717,6 +771,11 @@ _pages:
|
|||||||
name: "Nom de la variable"
|
name: "Nom de la variable"
|
||||||
text: "Titre"
|
text: "Titre"
|
||||||
default: "Valeur par défaut"
|
default: "Valeur par défaut"
|
||||||
|
canvas: "Toile"
|
||||||
|
_canvas:
|
||||||
|
id: "Toile ID"
|
||||||
|
width: "Largeur"
|
||||||
|
height: "Hauteur"
|
||||||
switch: "Basculer"
|
switch: "Basculer"
|
||||||
_switch:
|
_switch:
|
||||||
name: "Nom de la variable"
|
name: "Nom de la variable"
|
||||||
@ -742,6 +801,9 @@ _pages:
|
|||||||
message: "Message à afficher lorsque appuyé"
|
message: "Message à afficher lorsque appuyé"
|
||||||
variable: "Variable à envoyer"
|
variable: "Variable à envoyer"
|
||||||
no-variable: "Rien"
|
no-variable: "Rien"
|
||||||
|
callAiScript: "Appeler AiScript"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "Nom de la fonction"
|
||||||
radioButton: "Choix"
|
radioButton: "Choix"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "Nom de la variable"
|
name: "Nom de la variable"
|
||||||
@ -902,6 +964,7 @@ _pages:
|
|||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "Texte"
|
arg1: "Texte"
|
||||||
ref: "Variables"
|
ref: "Variables"
|
||||||
|
aiScriptVar: "Variable d'AiScript"
|
||||||
fn: "Fonction"
|
fn: "Fonction"
|
||||||
_fn:
|
_fn:
|
||||||
slots: "Slots"
|
slots: "Slots"
|
||||||
|
@ -16,7 +16,7 @@ const merge = (...args) => args.reduce((a, c) => ({
|
|||||||
const languages = [
|
const languages = [
|
||||||
//'cs-CZ',
|
//'cs-CZ',
|
||||||
//'da-DK',
|
//'da-DK',
|
||||||
//'de-DE',
|
'de-DE',
|
||||||
'en-US',
|
'en-US',
|
||||||
'es-ES',
|
'es-ES',
|
||||||
'fr-FR',
|
'fr-FR',
|
||||||
@ -26,7 +26,7 @@ const languages = [
|
|||||||
//'nl-NL',
|
//'nl-NL',
|
||||||
//'pl-PL',
|
//'pl-PL',
|
||||||
'zh-CN',
|
'zh-CN',
|
||||||
//'zh-TW',
|
'zh-TW',
|
||||||
];
|
];
|
||||||
|
|
||||||
const primaries = {
|
const primaries = {
|
||||||
|
@ -265,6 +265,7 @@ watch: "ウォッチ"
|
|||||||
unwatch: "ウォッチ解除"
|
unwatch: "ウォッチ解除"
|
||||||
accept: "許可"
|
accept: "許可"
|
||||||
reject: "拒否"
|
reject: "拒否"
|
||||||
|
normal: "正常"
|
||||||
instanceName: "インスタンス名"
|
instanceName: "インスタンス名"
|
||||||
instanceDescription: "インスタンスの紹介"
|
instanceDescription: "インスタンスの紹介"
|
||||||
maintainerName: "管理者の名前"
|
maintainerName: "管理者の名前"
|
||||||
@ -319,6 +320,7 @@ notesAndReplies: "投稿と返信"
|
|||||||
withFiles: "ファイル付き"
|
withFiles: "ファイル付き"
|
||||||
silence: "サイレンス"
|
silence: "サイレンス"
|
||||||
silenceConfirm: "サイレンスしますか?"
|
silenceConfirm: "サイレンスしますか?"
|
||||||
|
unsilence: "サイレンス解除"
|
||||||
unsilenceConfirm: "サイレンス解除しますか?"
|
unsilenceConfirm: "サイレンス解除しますか?"
|
||||||
popularUsers: "人気のユーザー"
|
popularUsers: "人気のユーザー"
|
||||||
recentlyUpdatedUsers: "最近投稿したユーザー"
|
recentlyUpdatedUsers: "最近投稿したユーザー"
|
||||||
@ -454,6 +456,8 @@ objectStorageRegion: "Region"
|
|||||||
objectStorageRegionDesc: "'xx-east-1'のようなregionを指定してください。使用サービスにregionの概念がない場合は、空または'us-east-1'にしてください。"
|
objectStorageRegionDesc: "'xx-east-1'のようなregionを指定してください。使用サービスにregionの概念がない場合は、空または'us-east-1'にしてください。"
|
||||||
objectStorageUseSSL: "SSLを使用する"
|
objectStorageUseSSL: "SSLを使用する"
|
||||||
objectStorageUseSSLDesc: "API接続にhttpsを使用しない場合はオフにしてください"
|
objectStorageUseSSLDesc: "API接続にhttpsを使用しない場合はオフにしてください"
|
||||||
|
objectStorageUseProxy: "Proxyを利用する"
|
||||||
|
objectStorageUseProxyDesc: "API接続にproxyを利用しない場合はオフにしてください"
|
||||||
serverLogs: "サーバーログ"
|
serverLogs: "サーバーログ"
|
||||||
deleteAll: "全て削除"
|
deleteAll: "全て削除"
|
||||||
showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
|
showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
|
||||||
@ -466,6 +470,37 @@ details: "詳細"
|
|||||||
chooseEmoji: "絵文字を選択"
|
chooseEmoji: "絵文字を選択"
|
||||||
unableToProcess: "操作を完了できません"
|
unableToProcess: "操作を完了できません"
|
||||||
recentUsed: "最近使用"
|
recentUsed: "最近使用"
|
||||||
|
install: "インストール"
|
||||||
|
uninstall: "アンインストール"
|
||||||
|
installedApps: "インストールされたアプリ"
|
||||||
|
nothing: "ありません"
|
||||||
|
installedDate: "インストール日時"
|
||||||
|
lastUsedDate: "最終使用日時"
|
||||||
|
state: "状態"
|
||||||
|
sort: "ソート"
|
||||||
|
ascendingOrder: "昇順"
|
||||||
|
descendingOrder: "降順"
|
||||||
|
scratchpad: "スクラッチパッド"
|
||||||
|
scratchpadDescription: "スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。"
|
||||||
|
output: "出力"
|
||||||
|
script: "スクリプト"
|
||||||
|
disablePagesScript: "Pagesのスクリプトを無効にする"
|
||||||
|
updateRemoteUser: "リモートユーザー情報の更新"
|
||||||
|
deleteAllFiles: "すべてのファイルを削除"
|
||||||
|
deleteAllFilesConfirm: "すべてのファイルを削除しますか?"
|
||||||
|
removeAllFollowing: "フォローを全解除"
|
||||||
|
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
||||||
|
userSuspended: "このユーザーは凍結されています。"
|
||||||
|
userSilenced: "このユーザーはサイレンスされています。"
|
||||||
|
|
||||||
|
_theme:
|
||||||
|
explore: "テーマを探す"
|
||||||
|
install: "テーマのインストール"
|
||||||
|
manage: "テーマの管理"
|
||||||
|
code: "テーマコード"
|
||||||
|
installed: "{name}をインストールしました"
|
||||||
|
alreadyInstalled: "そのテーマは既にインストールされています"
|
||||||
|
invalid: "テーマの形式が間違っています"
|
||||||
|
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "ノート"
|
note: "ノート"
|
||||||
@ -557,7 +592,11 @@ _permissions:
|
|||||||
|
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
||||||
|
shareAccessAsk: "アカウントへのアクセスを許可しますか?"
|
||||||
permissionAsk: "このアプリは次の権限を要求しています"
|
permissionAsk: "このアプリは次の権限を要求しています"
|
||||||
|
pleaseGoBack: "アプリケーションに戻ってやっていってください"
|
||||||
|
callback: "アプリケーションに戻っています"
|
||||||
|
denied: "アクセスを拒否しました"
|
||||||
|
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "全てのノート"
|
all: "全てのノート"
|
||||||
@ -672,15 +711,15 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "リクエスト"
|
requests: "リクエスト"
|
||||||
users: "ユーザーの増減"
|
users: "ユーザーの増減"
|
||||||
usersTotal: "ユーザーの積算"
|
usersTotal: "ユーザーの累積"
|
||||||
notes: "ノートの増減"
|
notes: "ノートの増減"
|
||||||
notesTotal: "ノートの積算"
|
notesTotal: "ノートの累積"
|
||||||
ff: "フォロー/フォロワーの増減"
|
ff: "フォロー/フォロワーの増減"
|
||||||
ffTotal: "フォロー/フォロワーの積算"
|
ffTotal: "フォロー/フォロワーの累積"
|
||||||
cacheSize: "キャッシュサイズの増減"
|
cacheSize: "キャッシュサイズの増減"
|
||||||
cacheSizeTotal: "キャッシュサイズの積算"
|
cacheSizeTotal: "キャッシュサイズの累積"
|
||||||
files: "ファイル数の増減"
|
files: "ファイル数の増減"
|
||||||
filesTotal: "ファイル数の積算"
|
filesTotal: "ファイル数の累積"
|
||||||
|
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "ホーム"
|
home: "ホーム"
|
||||||
@ -739,6 +778,8 @@ _pages:
|
|||||||
post: "投稿フォーム"
|
post: "投稿フォーム"
|
||||||
_post:
|
_post:
|
||||||
text: "内容"
|
text: "内容"
|
||||||
|
attachCanvasImage: "キャンバスの画像を添付する"
|
||||||
|
canvasId: "キャンバスID"
|
||||||
|
|
||||||
textInput: "テキスト入力"
|
textInput: "テキスト入力"
|
||||||
_textInput:
|
_textInput:
|
||||||
@ -758,6 +799,12 @@ _pages:
|
|||||||
text: "タイトル"
|
text: "タイトル"
|
||||||
default: "デフォルト値"
|
default: "デフォルト値"
|
||||||
|
|
||||||
|
canvas: "キャンバス"
|
||||||
|
_canvas:
|
||||||
|
id: "キャンバスID"
|
||||||
|
width: "幅"
|
||||||
|
height: "高さ"
|
||||||
|
|
||||||
switch: "スイッチ"
|
switch: "スイッチ"
|
||||||
_switch:
|
_switch:
|
||||||
name: "変数名"
|
name: "変数名"
|
||||||
@ -785,6 +832,9 @@ _pages:
|
|||||||
message: "押したときに表示するメッセージ"
|
message: "押したときに表示するメッセージ"
|
||||||
variable: "送信する変数"
|
variable: "送信する変数"
|
||||||
no-variable: "なし"
|
no-variable: "なし"
|
||||||
|
callAiScript: "AiScript呼び出し"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "関数名"
|
||||||
|
|
||||||
radioButton: "選択肢"
|
radioButton: "選択肢"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
@ -947,6 +997,7 @@ _pages:
|
|||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "テキスト"
|
arg1: "テキスト"
|
||||||
ref: "変数"
|
ref: "変数"
|
||||||
|
aiScriptVar: "AiScript変数"
|
||||||
fn: "関数"
|
fn: "関数"
|
||||||
_fn:
|
_fn:
|
||||||
slots: "スロット"
|
slots: "スロット"
|
||||||
|
@ -62,7 +62,6 @@ clickToShow: "押してみ、見せたるわ"
|
|||||||
sensitive: "見たらあかんで"
|
sensitive: "見たらあかんで"
|
||||||
add: "増やす"
|
add: "増やす"
|
||||||
reaction: "リアクション"
|
reaction: "リアクション"
|
||||||
renameFile: "ファイル名をいらう"
|
|
||||||
attachCancel: "くっつけるのやめよか"
|
attachCancel: "くっつけるのやめよか"
|
||||||
markAsSensitive: "ちょっと見せられへんわ"
|
markAsSensitive: "ちょっと見せられへんわ"
|
||||||
unmarkAsSensitive: "別にええんじゃね?"
|
unmarkAsSensitive: "別にええんじゃね?"
|
||||||
@ -102,6 +101,7 @@ all: "みな"
|
|||||||
retypedNotMatch: "そやないねん。"
|
retypedNotMatch: "そやないねん。"
|
||||||
remove: "ほかす"
|
remove: "ほかす"
|
||||||
noMoreHistory: "これより過去の履歴はあらへんで"
|
noMoreHistory: "これより過去の履歴はあらへんで"
|
||||||
|
renameFile: "ファイル名をいらう"
|
||||||
nsfw: "見たらあかんで"
|
nsfw: "見たらあかんで"
|
||||||
userList: "リスト"
|
userList: "リスト"
|
||||||
about: "情報"
|
about: "情報"
|
||||||
|
@ -35,6 +35,8 @@ unpin: "프로필에서 고정 해제"
|
|||||||
copyContent: "내용 복사"
|
copyContent: "내용 복사"
|
||||||
copyLink: "링크 복사"
|
copyLink: "링크 복사"
|
||||||
delete: "삭제"
|
delete: "삭제"
|
||||||
|
deleteAndEdit: "삭제 후 편집"
|
||||||
|
deleteAndEditConfirm: "이 노트를 삭제한 뒤 다시 편집하시겠습니까? 이 노트에 대한 리액션, 리노트, 답글 또한 모두 삭제됩니다."
|
||||||
addToList: "리스트에 추가"
|
addToList: "리스트에 추가"
|
||||||
sendMessage: "메시지 보내기"
|
sendMessage: "메시지 보내기"
|
||||||
copyUsername: "유저명 복사"
|
copyUsername: "유저명 복사"
|
||||||
@ -86,7 +88,6 @@ add: "추가"
|
|||||||
reaction: "리액션"
|
reaction: "리액션"
|
||||||
reactionSettingDescription: "리액션 선택 상자에 표시할 리액션을 설정합니다."
|
reactionSettingDescription: "리액션 선택 상자에 표시할 리액션을 설정합니다."
|
||||||
rememberNoteVisibility: "공개 범위를 기억하기"
|
rememberNoteVisibility: "공개 범위를 기억하기"
|
||||||
renameFile: "파일 이름 변경"
|
|
||||||
attachCancel: "첨부 취소"
|
attachCancel: "첨부 취소"
|
||||||
markAsSensitive: "열람주의로 설정"
|
markAsSensitive: "열람주의로 설정"
|
||||||
unmarkAsSensitive: "열람주의 해제"
|
unmarkAsSensitive: "열람주의 해제"
|
||||||
@ -116,6 +117,7 @@ loginFailed: "로그인에 실패했습니다"
|
|||||||
showOnRemote: "리모트에서 보기"
|
showOnRemote: "리모트에서 보기"
|
||||||
general: "일반"
|
general: "일반"
|
||||||
wallpaper: "배경"
|
wallpaper: "배경"
|
||||||
|
setWallpaper: "배경화면 설정"
|
||||||
removeWallpaper: "배경 제거"
|
removeWallpaper: "배경 제거"
|
||||||
searchWith: "검색: {q}"
|
searchWith: "검색: {q}"
|
||||||
youHaveNoLists: "리스트가 없습니다"
|
youHaveNoLists: "리스트가 없습니다"
|
||||||
@ -204,10 +206,13 @@ messaging: "대화"
|
|||||||
upload: "업로드"
|
upload: "업로드"
|
||||||
fromDrive: "드라이브에서"
|
fromDrive: "드라이브에서"
|
||||||
fromUrl: "URL로부터"
|
fromUrl: "URL로부터"
|
||||||
|
uploadFromUrl: "URL 업로드"
|
||||||
|
uploadFromUrlDescription: "업로드하려는 파일의 URL"
|
||||||
|
uploadFromUrlRequested: "업로드를 요청했습니다"
|
||||||
|
uploadFromUrlMayTakeTime: "업로드가 완료될 때까지 시간이 소요될 수 있습니다."
|
||||||
explore: "발견하기"
|
explore: "발견하기"
|
||||||
games: "Misskey Games"
|
games: "Misskey Games"
|
||||||
messageRead: "읽음"
|
messageRead: "읽음"
|
||||||
recentUsedEmojis: "최근에 사용한 이모지"
|
|
||||||
noMoreHistory: "이것보다 과거의 기록이 없습니다"
|
noMoreHistory: "이것보다 과거의 기록이 없습니다"
|
||||||
startMessaging: "대화 시작하기"
|
startMessaging: "대화 시작하기"
|
||||||
nUsersRead: "{n}명이 읽음"
|
nUsersRead: "{n}명이 읽음"
|
||||||
@ -223,17 +228,30 @@ yearsOld: "{age}세"
|
|||||||
registeredDate: "등록일"
|
registeredDate: "등록일"
|
||||||
location: "장소"
|
location: "장소"
|
||||||
theme: "테마"
|
theme: "테마"
|
||||||
|
themeForLightMode: "라이트 모드에서 사용할 테마"
|
||||||
|
themeForDarkMode: "다크 모드에서 사용할 테마"
|
||||||
|
light: "라이트"
|
||||||
|
dark: "다크"
|
||||||
lightThemes: "밝은 테마"
|
lightThemes: "밝은 테마"
|
||||||
darkThemes: "어두운 테마"
|
darkThemes: "어두운 테마"
|
||||||
|
syncDeviceDarkMode: "디바이스의 다크 모드 설정과 동기화"
|
||||||
drive: "드라이브"
|
drive: "드라이브"
|
||||||
|
fileName: "파일명"
|
||||||
selectFile: "파일 선택"
|
selectFile: "파일 선택"
|
||||||
selectFiles: "파일 선택"
|
selectFiles: "파일 선택"
|
||||||
renameFolder: "폴더 이름 바꾸기"
|
renameFile: "파일 이름 변경"
|
||||||
|
folderName: "폴더명"
|
||||||
createFolder: "폴더 만들기"
|
createFolder: "폴더 만들기"
|
||||||
|
renameFolder: "폴더 이름 바꾸기"
|
||||||
deleteFolder: "폴더 삭제"
|
deleteFolder: "폴더 삭제"
|
||||||
addFile: "파일 추가"
|
addFile: "파일 추가"
|
||||||
emptyDrive: "드라이브가 비어 있습니다"
|
emptyDrive: "드라이브가 비어 있습니다"
|
||||||
emptyFolder: "폴더가 비어 있습니다"
|
emptyFolder: "폴더가 비어 있습니다"
|
||||||
|
unableToDelete: "삭제할 수 없습니다"
|
||||||
|
inputNewFileName: "바꿀 파일명을 입력해 주세요"
|
||||||
|
inputNewFolderName: "바꿀 폴더명을 입력해 주세요"
|
||||||
|
circularReferenceFolder: "지정한 폴더가 이동할 폴더의 하위 폴더입니다."
|
||||||
|
hasChildFilesOrFolders: "이 폴더는 비어있지 않기 때문에 삭제할 수 없습니다."
|
||||||
copyUrl: "URL 복사"
|
copyUrl: "URL 복사"
|
||||||
rename: "이름 변경"
|
rename: "이름 변경"
|
||||||
avatar: "아바타"
|
avatar: "아바타"
|
||||||
@ -247,6 +265,7 @@ watch: "지켜보기"
|
|||||||
unwatch: "지켜보기 해제"
|
unwatch: "지켜보기 해제"
|
||||||
accept: "허가"
|
accept: "허가"
|
||||||
reject: "거부"
|
reject: "거부"
|
||||||
|
normal: "정상"
|
||||||
instanceName: "인스턴스 이름"
|
instanceName: "인스턴스 이름"
|
||||||
instanceDescription: "인스턴스 소개"
|
instanceDescription: "인스턴스 소개"
|
||||||
maintainerName: "관리자 이름"
|
maintainerName: "관리자 이름"
|
||||||
@ -301,6 +320,7 @@ notesAndReplies: "글과 답글"
|
|||||||
withFiles: "미디어"
|
withFiles: "미디어"
|
||||||
silence: "사일런스"
|
silence: "사일런스"
|
||||||
silenceConfirm: "이 계정을 사일런스로 설정하시겠습니까?"
|
silenceConfirm: "이 계정을 사일런스로 설정하시겠습니까?"
|
||||||
|
unsilence: "사일런스 해제"
|
||||||
unsilenceConfirm: "이 계정의 사일런스를 해제하시겠습니까?"
|
unsilenceConfirm: "이 계정의 사일런스를 해제하시겠습니까?"
|
||||||
popularUsers: "인기 유저"
|
popularUsers: "인기 유저"
|
||||||
recentlyUpdatedUsers: "최근 활동한 유저"
|
recentlyUpdatedUsers: "최근 활동한 유저"
|
||||||
@ -387,13 +407,14 @@ strongPassword: "강한 비밀번호"
|
|||||||
passwordMatched: "일치합니다"
|
passwordMatched: "일치합니다"
|
||||||
passwordNotMatched: "일치하지 않습니다"
|
passwordNotMatched: "일치하지 않습니다"
|
||||||
signinWith: "{x}로 로그인"
|
signinWith: "{x}로 로그인"
|
||||||
|
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
|
||||||
tapSecurityKey: "보안 키를 터치"
|
tapSecurityKey: "보안 키를 터치"
|
||||||
or: "혹은"
|
or: "혹은"
|
||||||
uiLanguage: "UI 표시 언어"
|
uiLanguage: "UI 표시 언어"
|
||||||
groupInvited: "그룹에 초대되었습니다"
|
groupInvited: "그룹에 초대되었습니다"
|
||||||
aboutX: "{x}에 대하여"
|
aboutX: "{x}에 대하여"
|
||||||
useOsNativeEmojis: "OS 기본 이모지를 사용"
|
useOsNativeEmojis: "OS 기본 이모지를 사용"
|
||||||
noGroups: "그룹이 없습니다"
|
youHaveNoGroups: "그룹이 없습니다"
|
||||||
joinOrCreateGroup: "다른 그룹의 초대를 받거나, 직접 새 그룹을 만들어 보세요."
|
joinOrCreateGroup: "다른 그룹의 초대를 받거나, 직접 새 그룹을 만들어 보세요."
|
||||||
noHistory: "기록이 없습니다"
|
noHistory: "기록이 없습니다"
|
||||||
disableAnimatedMfm: "움직임이 있는 MFM을 비활성화"
|
disableAnimatedMfm: "움직임이 있는 MFM을 비활성화"
|
||||||
@ -435,6 +456,8 @@ objectStorageRegion: "Region"
|
|||||||
objectStorageRegionDesc: "'xx-east-1'와 같이 region을 지정해주세요. 사용하는 서비스에 region 개념이 없는 경우, 비워 두거나 'us-east-1'으로 설정해 주세요."
|
objectStorageRegionDesc: "'xx-east-1'와 같이 region을 지정해주세요. 사용하는 서비스에 region 개념이 없는 경우, 비워 두거나 'us-east-1'으로 설정해 주세요."
|
||||||
objectStorageUseSSL: "SSL 사용"
|
objectStorageUseSSL: "SSL 사용"
|
||||||
objectStorageUseSSLDesc: "API 호출시 HTTPS 를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
objectStorageUseSSLDesc: "API 호출시 HTTPS 를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
||||||
|
objectStorageUseProxy: "연결에 프록시를 사용"
|
||||||
|
objectStorageUseProxyDesc: "오브젝트 스토리지 API 호출시 프록시를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
||||||
serverLogs: "서버 로그"
|
serverLogs: "서버 로그"
|
||||||
deleteAll: "모두 삭제"
|
deleteAll: "모두 삭제"
|
||||||
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
|
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
|
||||||
@ -445,6 +468,38 @@ none: "없음"
|
|||||||
volume: "음량"
|
volume: "음량"
|
||||||
details: "자세히"
|
details: "자세히"
|
||||||
chooseEmoji: "이모지 선택"
|
chooseEmoji: "이모지 선택"
|
||||||
|
unableToProcess: "작업을 완료할 수 없습니다"
|
||||||
|
recentUsed: "최근 사용"
|
||||||
|
install: "설치"
|
||||||
|
uninstall: "삭제"
|
||||||
|
installedApps: "인증된 애플리케이션"
|
||||||
|
nothing: "아무것도 없습니다"
|
||||||
|
installedDate: "승인한 날짜"
|
||||||
|
lastUsedDate: "마지막 사용"
|
||||||
|
state: "상태"
|
||||||
|
sort: "정렬"
|
||||||
|
ascendingOrder: "오름차순"
|
||||||
|
descendingOrder: "내림차순"
|
||||||
|
scratchpad: "스크래치 패드"
|
||||||
|
scratchpadDescription: "스크래치 패드는 AiScript 의 테스트 환경을 제공합니다. Misskey 와 상호 작용하는 코드를 작성, 실행 및 결과를 확인할 수 있습니다."
|
||||||
|
output: "출력"
|
||||||
|
script: "스크립트"
|
||||||
|
disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음"
|
||||||
|
updateRemoteUser: "리모트 유저 정보 갱신"
|
||||||
|
deleteAllFiles: "모든 파일 삭제"
|
||||||
|
deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?"
|
||||||
|
removeAllFollowing: "모든 팔로잉 해제"
|
||||||
|
removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요."
|
||||||
|
userSuspended: "이 계정은 정지된 상태입니다."
|
||||||
|
userSilenced: "이 계정은 사일런스된 상태입니다."
|
||||||
|
_theme:
|
||||||
|
explore: "테마 찾아보기"
|
||||||
|
install: "테마 설치"
|
||||||
|
manage: "테마 관리"
|
||||||
|
code: "테마 코드"
|
||||||
|
installed: "{name} 테마가 설치되었습니다"
|
||||||
|
alreadyInstalled: "이미 설치된 테마입니다"
|
||||||
|
invalid: "테마 형식이 올바르지 않습니다"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "새 노트"
|
note: "새 노트"
|
||||||
noteMy: "내 노트"
|
noteMy: "내 노트"
|
||||||
@ -529,7 +584,11 @@ _permissions:
|
|||||||
"write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다"
|
"write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "\"{name}\" 이 계정에 접근하는 것을 허용하시겠습니까?"
|
shareAccess: "\"{name}\" 이 계정에 접근하는 것을 허용하시겠습니까?"
|
||||||
|
shareAccessAsk: "이 애플리케이션이 계정에 접근하는 것을 허용하시겠습니까?"
|
||||||
permissionAsk: "이 앱은 다음의 권한을 요청합니다"
|
permissionAsk: "이 앱은 다음의 권한을 요청합니다"
|
||||||
|
pleaseGoBack: "앱으로 돌아가서 시도해 주세요"
|
||||||
|
callback: "앱으로 돌아갑니다"
|
||||||
|
denied: "접근이 거부되었습니다"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "모든 노트"
|
all: "모든 노트"
|
||||||
homeTimeline: "팔로우중인 유저의 노트"
|
homeTimeline: "팔로우중인 유저의 노트"
|
||||||
@ -618,26 +677,26 @@ _exportOrImport:
|
|||||||
userLists: "리스트"
|
userLists: "리스트"
|
||||||
_charts:
|
_charts:
|
||||||
federationInstancesIncDec: "연합 인스턴스 수 증감"
|
federationInstancesIncDec: "연합 인스턴스 수 증감"
|
||||||
federationInstancesTotal: "총 연합 인스턴스 수"
|
federationInstancesTotal: "연합 인스턴스 수 합계"
|
||||||
usersIncDec: "유저 수 증감"
|
usersIncDec: "유저 수 증감"
|
||||||
usersTotal: "유저 수 합계"
|
usersTotal: "유저 수 합계"
|
||||||
activeUsers: "활성 유저 수"
|
activeUsers: "활성 유저 수"
|
||||||
notesIncDec: "노트 수 증감"
|
notesIncDec: "노트 수 증감"
|
||||||
localNotesIncDec: "로컬 노트 수 증감"
|
localNotesIncDec: "로컬 노트 수 증감"
|
||||||
remoteNotesIncDec: "리모트 노트 수 증감"
|
remoteNotesIncDec: "리모트 노트 수 증감"
|
||||||
notesTotal: "총 노트 수"
|
notesTotal: "노트 수 합계"
|
||||||
filesIncDec: "파일 수 증감"
|
filesIncDec: "파일 수 증감"
|
||||||
filesTotal: "총 파일 수"
|
filesTotal: "파일 수 합계"
|
||||||
storageUsageIncDec: "스토리지 사용량 증감"
|
storageUsageIncDec: "스토리지 사용량 증감"
|
||||||
storageUsageTotal: "총 스토리지 사용량"
|
storageUsageTotal: "스토리지 사용량 합계"
|
||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "요청"
|
requests: "요청"
|
||||||
users: "유저 수 증감"
|
users: "유저 수 증감"
|
||||||
usersTotal: "누적 유저 수"
|
usersTotal: "누적 유저 수"
|
||||||
notes: "노트 수 증감"
|
notes: "노트 수 증감"
|
||||||
notesTotal: "총 노트 수"
|
notesTotal: "누적 노트 수"
|
||||||
ff: "팔로잉/팔로워 증감"
|
ff: "팔로잉/팔로워 증감"
|
||||||
ffTotal: "팔로잉/팔로워 누적"
|
ffTotal: "누적 팔로잉/팔로워 수"
|
||||||
cacheSize: "캐시 용량 증감"
|
cacheSize: "캐시 용량 증감"
|
||||||
cacheSizeTotal: "누적 캐시 용량"
|
cacheSizeTotal: "누적 캐시 용량"
|
||||||
files: "파일 수 증감"
|
files: "파일 수 증감"
|
||||||
@ -651,45 +710,39 @@ _pages:
|
|||||||
newPage: "페이지 만들기"
|
newPage: "페이지 만들기"
|
||||||
editPage: "페이지 수정"
|
editPage: "페이지 수정"
|
||||||
readPage: "소스 표시 중"
|
readPage: "소스 표시 중"
|
||||||
page-created: "페이지를 만들었습니다"
|
created: "페이지를 만들었습니다"
|
||||||
page-updated: "페이지를 수정했습니다"
|
updated: "페이지를 수정했습니다"
|
||||||
name-already-exists: "지정한 페이지 URL이 이미 존재합니다"
|
deleted: "페이지가 삭제되었습니다"
|
||||||
title-invalid-name: "유효하지 않은 페이지 URL입니다"
|
nameAlreadyExists: "지정한 페이지 URL이 이미 존재합니다"
|
||||||
text-invalid-name: "비어있지 않은지 확인해주세요"
|
invalidNameTitle: "유효하지 않은 페이지 URL입니다"
|
||||||
|
invalidNameText: "비어있지 않은지 확인해주세요"
|
||||||
editThisPage: "이 페이지를 편집"
|
editThisPage: "이 페이지를 편집"
|
||||||
viewSource: "소스 보기"
|
viewSource: "소스 보기"
|
||||||
viewPage: "페이지 보기"
|
viewPage: "페이지 보기"
|
||||||
like: "좋아요"
|
like: "좋아요"
|
||||||
unlike: "좋아요 해제"
|
unlike: "좋아요 해제"
|
||||||
liked-pages: "좋아요한 페이지"
|
my: "내 페이지"
|
||||||
my-pages: "내 페이지"
|
liked: "좋아요한 페이지"
|
||||||
inspector: "인스펙터"
|
inspector: "인스펙터"
|
||||||
content: "페이지 블록"
|
content: "페이지 블록"
|
||||||
variables: "변수"
|
variables: "변수"
|
||||||
variables-info: "변수를 사용하면 동적인 페이지를 만들 수 있습니다. 텍스트에 <b>{ 변수명 }</b>을 적으면 그 위치에 변수의 값을 집어넣습니다. 예를 들어, <b>Hello { thing } world!</b> 라는 텍스트가 있을 때, 변수(thing)의 값이 <b>ai</b>인 경우 텍스트는 <b>Hello ai world!</b>가 됩니다."
|
|
||||||
variables-info2: "변수의 평가(값을 계산해내는 것)는 위에서부터 아래로 진행되므로 어떤 변수의 내부에서 자신보다 아래에 있는 변수를 참조할 수는 없습니다. 예를 들자면 위에서부터 <b>A, B, C</b>의 3개의 변수가 정의되어 있을 때, <b>C</b>의 내부에 <b>A</b>나 <b>B</b>를 참조할 수는 있지만, <b>A</b>의 내부에서 <b>B</b>나 <b>C</b>를 참조할 수는 없습니다."
|
|
||||||
variables-info3: "사용자로부터 입력을 받으려면, 페이지에 \"사용자 입력\" 블록을 삽입하고 \"변수명\" 에 입력받은 값을 저장하고 싶은 변수명을 설정합니다 (변수는 자동으로 생성됩니다). 그 변수를 사용하여 사용자 입력에 따라 동작할 수 있습니다."
|
|
||||||
variables-info4: "함수를 사용하면 반복되는 작업을 손쉽게 처리할 수 있습니다. 함수를 만드시려면 \"함수\" 타입의 변수를 만듭니다. 함수에서 슬롯(인수)를 받도록 설정하면, 함수를 사용할 때 슬롯에 입력된 값을 함수 안에서 변수로써 이용할 수 있게 됩니다. 또한, AiScript 표준에는 함수를 인수로 받는 함수(고차함수)도 존재합니다. 함수를 미리 정의하는 것 외에, 이와 같은 고차함수를 즉석으로 설정할 수 있습니다."
|
|
||||||
more-details: "자세한 설명"
|
|
||||||
title: "제목"
|
title: "제목"
|
||||||
url: "페이지 URL"
|
url: "페이지 URL"
|
||||||
summary: "페이지 요약"
|
summary: "페이지 요약"
|
||||||
alignCenter: "가운데 정렬"
|
alignCenter: "가운데 정렬"
|
||||||
hide-title-when-pinned: "프로필에 고정할 때 타이틀을 표시하지 않음"
|
hideTitleWhenPinned: "프로필에 고정해놓은 경우 타이틀을 표시하지 않음"
|
||||||
font: "폰트"
|
font: "폰트"
|
||||||
fontSerif: "명조체"
|
fontSerif: "명조체"
|
||||||
fontSansSerif: "고딕체"
|
fontSansSerif: "고딕체"
|
||||||
set-eye-catching-image: "아이캐치 이미지를 설정"
|
eyeCatchingImageSet: "아이캐치 이미지를 설정"
|
||||||
remove-eye-catching-image: "아이캐치 이미지 삭제"
|
eyeCatchingImageRemove: "아이캐치 이미지를 삭제"
|
||||||
chooseBlock: "블록 추가"
|
chooseBlock: "블록 추가"
|
||||||
selectType: "종류 선택"
|
selectType: "종류 선택"
|
||||||
enterVariableName: "변수명을 지정해주세요"
|
enterVariableName: "변수명을 지정해주세요"
|
||||||
the-variable-name-is-already-used: "해당 변수명은 이미 사용중입니다"
|
variableNameIsAlreadyUsed: "해당 변수명은 이미 사용중입니다"
|
||||||
content-blocks: "컨텐츠"
|
contentBlocks: "콘텐츠"
|
||||||
input-blocks: "입력"
|
inputBlocks: "입력"
|
||||||
special-blocks: "특수"
|
specialBlocks: "특수"
|
||||||
post-from-post-form: "이 내용을 올리기"
|
|
||||||
posted-from-post-form: "게시하였습니다"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "텍스트"
|
text: "텍스트"
|
||||||
textarea: "텍스트 영역"
|
textarea: "텍스트 영역"
|
||||||
@ -702,6 +755,7 @@ _pages:
|
|||||||
post: "글 입력란"
|
post: "글 입력란"
|
||||||
_post:
|
_post:
|
||||||
text: "내용"
|
text: "내용"
|
||||||
|
canvasId: "캔버스 ID"
|
||||||
textInput: "텍스트 입력"
|
textInput: "텍스트 입력"
|
||||||
_textInput:
|
_textInput:
|
||||||
name: "변수명"
|
name: "변수명"
|
||||||
@ -717,6 +771,11 @@ _pages:
|
|||||||
name: "변수명"
|
name: "변수명"
|
||||||
text: "제목"
|
text: "제목"
|
||||||
default: "기본값"
|
default: "기본값"
|
||||||
|
canvas: "캔버스"
|
||||||
|
_canvas:
|
||||||
|
id: "캔버스 ID"
|
||||||
|
width: "폭"
|
||||||
|
height: "높이"
|
||||||
switch: "스위치"
|
switch: "스위치"
|
||||||
_switch:
|
_switch:
|
||||||
name: "변수명"
|
name: "변수명"
|
||||||
@ -742,6 +801,9 @@ _pages:
|
|||||||
message: "눌렀을 때 표시할 페이지"
|
message: "눌렀을 때 표시할 페이지"
|
||||||
variable: "보낼 변수"
|
variable: "보낼 변수"
|
||||||
no-variable: "없음"
|
no-variable: "없음"
|
||||||
|
callAiScript: "AiScript 호출"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "함수명"
|
||||||
radioButton: "선택지"
|
radioButton: "선택지"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "변수명"
|
name: "변수명"
|
||||||
@ -902,6 +964,7 @@ _pages:
|
|||||||
_splitStrByLine:
|
_splitStrByLine:
|
||||||
arg1: "텍스트"
|
arg1: "텍스트"
|
||||||
ref: "변수"
|
ref: "변수"
|
||||||
|
aiScriptVar: "AiScript 변수"
|
||||||
fn: "함수"
|
fn: "함수"
|
||||||
_fn:
|
_fn:
|
||||||
slots: "슬롯"
|
slots: "슬롯"
|
||||||
|
@ -35,6 +35,8 @@ unpin: "取消置顶"
|
|||||||
copyContent: "复制内容"
|
copyContent: "复制内容"
|
||||||
copyLink: "复制链接"
|
copyLink: "复制链接"
|
||||||
delete: "删除"
|
delete: "删除"
|
||||||
|
deleteAndEdit: "删除和编辑"
|
||||||
|
deleteAndEditConfirm: "要删除此帖并再次编辑吗?对此帖的所有回应,转推和回复也将被删除。"
|
||||||
addToList: "添加至列表"
|
addToList: "添加至列表"
|
||||||
sendMessage: "发送"
|
sendMessage: "发送"
|
||||||
copyUsername: "复制用户名"
|
copyUsername: "复制用户名"
|
||||||
@ -86,7 +88,6 @@ add: "添加"
|
|||||||
reaction: "反应"
|
reaction: "反应"
|
||||||
reactionSettingDescription: "选择您想要固定在反应选择器中的反应。"
|
reactionSettingDescription: "选择您想要固定在反应选择器中的反应。"
|
||||||
rememberNoteVisibility: "记录公开范围"
|
rememberNoteVisibility: "记录公开范围"
|
||||||
renameFile: "重命名文件"
|
|
||||||
attachCancel: "删除附件"
|
attachCancel: "删除附件"
|
||||||
markAsSensitive: "阅读注意"
|
markAsSensitive: "阅读注意"
|
||||||
unmarkAsSensitive: "取消标记为敏感内容"
|
unmarkAsSensitive: "取消标记为敏感内容"
|
||||||
@ -116,6 +117,7 @@ loginFailed: "登录失败"
|
|||||||
showOnRemote: "转到所在实例显示"
|
showOnRemote: "转到所在实例显示"
|
||||||
general: "常规设置"
|
general: "常规设置"
|
||||||
wallpaper: "壁纸"
|
wallpaper: "壁纸"
|
||||||
|
setWallpaper: "设置壁纸"
|
||||||
removeWallpaper: "移除壁纸"
|
removeWallpaper: "移除壁纸"
|
||||||
searchWith: "搜索:{q}"
|
searchWith: "搜索:{q}"
|
||||||
youHaveNoLists: "列表为空"
|
youHaveNoLists: "列表为空"
|
||||||
@ -204,10 +206,13 @@ messaging: "聊天"
|
|||||||
upload: "上传"
|
upload: "上传"
|
||||||
fromDrive: "从网盘中"
|
fromDrive: "从网盘中"
|
||||||
fromUrl: "从 URL"
|
fromUrl: "从 URL"
|
||||||
|
uploadFromUrl: "从网址上传"
|
||||||
|
uploadFromUrlDescription: "要上传的文件的URL"
|
||||||
|
uploadFromUrlRequested: "请求上传"
|
||||||
|
uploadFromUrlMayTakeTime: "上传完成可能需要一些时间。"
|
||||||
explore: "发现"
|
explore: "发现"
|
||||||
games: "Misskey游戏"
|
games: "Misskey游戏"
|
||||||
messageRead: "已读"
|
messageRead: "已读"
|
||||||
recentUsedEmojis: "最近使用的Emoji表情"
|
|
||||||
noMoreHistory: "没有更多的历史记录"
|
noMoreHistory: "没有更多的历史记录"
|
||||||
startMessaging: "开始聊天"
|
startMessaging: "开始聊天"
|
||||||
nUsersRead: "{n}人已读"
|
nUsersRead: "{n}人已读"
|
||||||
@ -223,17 +228,30 @@ yearsOld: "{age}岁"
|
|||||||
registeredDate: "注册于"
|
registeredDate: "注册于"
|
||||||
location: "位置"
|
location: "位置"
|
||||||
theme: "主题"
|
theme: "主题"
|
||||||
|
themeForLightMode: "在轻便模式下使用的主题"
|
||||||
|
themeForDarkMode: "在黑暗模式下使用的主题"
|
||||||
|
light: "浅色"
|
||||||
|
dark: "深色"
|
||||||
lightThemes: "亮色主题"
|
lightThemes: "亮色主题"
|
||||||
darkThemes: "暗色主题"
|
darkThemes: "暗色主题"
|
||||||
|
syncDeviceDarkMode: "将黑暗模式与设备设置同步"
|
||||||
drive: "网盘"
|
drive: "网盘"
|
||||||
|
fileName: "文件名称"
|
||||||
selectFile: "选择文件"
|
selectFile: "选择文件"
|
||||||
selectFiles: "选择文件"
|
selectFiles: "选择文件"
|
||||||
renameFolder: "重命名文件夹"
|
renameFile: "重命名文件"
|
||||||
|
folderName: "文件夹名称"
|
||||||
createFolder: "创建文件夹"
|
createFolder: "创建文件夹"
|
||||||
|
renameFolder: "重命名文件夹"
|
||||||
deleteFolder: "删除文件夹"
|
deleteFolder: "删除文件夹"
|
||||||
addFile: "添加文件"
|
addFile: "添加文件"
|
||||||
emptyDrive: "驱动器为空"
|
emptyDrive: "驱动器为空"
|
||||||
emptyFolder: "空文件夹"
|
emptyFolder: "空文件夹"
|
||||||
|
unableToDelete: "无法删除"
|
||||||
|
inputNewFileName: "请输入新文件名"
|
||||||
|
inputNewFolderName: "请输入新文件名"
|
||||||
|
circularReferenceFolder: "目标文件夹是您要移动的文件夹的子文件夹。"
|
||||||
|
hasChildFilesOrFolders: "此文件夹不为空,无法删除。"
|
||||||
copyUrl: "复制链接"
|
copyUrl: "复制链接"
|
||||||
rename: "重命名"
|
rename: "重命名"
|
||||||
avatar: "头像"
|
avatar: "头像"
|
||||||
@ -387,13 +405,14 @@ strongPassword: "密码强度:强"
|
|||||||
passwordMatched: "密码一致"
|
passwordMatched: "密码一致"
|
||||||
passwordNotMatched: "密码不一致"
|
passwordNotMatched: "密码不一致"
|
||||||
signinWith: "以{x}登录"
|
signinWith: "以{x}登录"
|
||||||
|
signinFailed: "无法登录。请检查您的用户名和密码。"
|
||||||
tapSecurityKey: "点击安全密钥"
|
tapSecurityKey: "点击安全密钥"
|
||||||
or: "或者"
|
or: "或者"
|
||||||
uiLanguage: "显示语言"
|
uiLanguage: "显示语言"
|
||||||
groupInvited: "群组招待"
|
groupInvited: "群组招待"
|
||||||
aboutX: "关于 {x}"
|
aboutX: "关于 {x}"
|
||||||
useOsNativeEmojis: "使用OS原生Emoji"
|
useOsNativeEmojis: "使用OS原生Emoji"
|
||||||
noGroups: "没有组"
|
youHaveNoGroups: "没有组"
|
||||||
joinOrCreateGroup: "加入或者创建群组"
|
joinOrCreateGroup: "加入或者创建群组"
|
||||||
noHistory: "没有历史记录"
|
noHistory: "没有历史记录"
|
||||||
disableAnimatedMfm: "禁用MFM动画"
|
disableAnimatedMfm: "禁用MFM动画"
|
||||||
@ -445,9 +464,30 @@ none: "空"
|
|||||||
volume: "音量"
|
volume: "音量"
|
||||||
details: "详情"
|
details: "详情"
|
||||||
chooseEmoji: "选择表情符号"
|
chooseEmoji: "选择表情符号"
|
||||||
|
unableToProcess: "操作无法完成"
|
||||||
|
recentUsed: "最近使用"
|
||||||
|
install: "安装"
|
||||||
|
uninstall: "卸载"
|
||||||
|
installedApps: "已授权的应用"
|
||||||
|
nothing: "没什么"
|
||||||
|
installedDate: "授权日期"
|
||||||
|
lastUsedDate: "最近使用"
|
||||||
|
state: "状态"
|
||||||
|
sort: "排序"
|
||||||
|
ascendingOrder: "升序"
|
||||||
|
descendingOrder: "降序"
|
||||||
|
output: "输出"
|
||||||
|
_theme:
|
||||||
|
explore: "寻找主题"
|
||||||
|
install: "安装主题"
|
||||||
|
manage: "主题管理"
|
||||||
|
code: "主题代码"
|
||||||
|
installed: "{name} 已安装"
|
||||||
|
alreadyInstalled: "此主题已经安装"
|
||||||
|
invalid: "主题格式错误"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "帖子"
|
note: "帖子"
|
||||||
noteMy: "我的笔记"
|
noteMy: "我的帖子"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
chat: "聊天"
|
chat: "聊天"
|
||||||
chatBg: "聊天背景"
|
chatBg: "聊天背景"
|
||||||
@ -529,7 +569,11 @@ _permissions:
|
|||||||
"write:user-groups": "操作用户组"
|
"write:user-groups": "操作用户组"
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
||||||
|
shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?"
|
||||||
permissionAsk: "这个应用程序需要以下权限"
|
permissionAsk: "这个应用程序需要以下权限"
|
||||||
|
pleaseGoBack: "请返回到应用程序"
|
||||||
|
callback: "回到应用程序"
|
||||||
|
denied: "拒绝访问"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "所有帖子"
|
all: "所有帖子"
|
||||||
homeTimeline: "已关注用户的帖子"
|
homeTimeline: "已关注用户的帖子"
|
||||||
@ -633,15 +677,15 @@ _charts:
|
|||||||
_instanceCharts:
|
_instanceCharts:
|
||||||
requests: "请求"
|
requests: "请求"
|
||||||
users: "用户数量:增加/减少"
|
users: "用户数量:增加/减少"
|
||||||
usersTotal: "用户总数"
|
usersTotal: "用户总计"
|
||||||
notes: "帖子:增加/减少"
|
notes: "帖子:增加/减少"
|
||||||
notesTotal: "帖子:总数"
|
notesTotal: "帖子总计"
|
||||||
ff: "关注/被关注:数量变化"
|
ff: "关注/被关注:数量变化"
|
||||||
ffTotal: "关注/被关注:总数"
|
ffTotal: "关注/被关注者总计"
|
||||||
cacheSize: "缓存大小:增加/减少"
|
cacheSize: "缓存大小:增加/减少"
|
||||||
cacheSizeTotal: "合计缓存大小"
|
cacheSizeTotal: "缓存大小总计"
|
||||||
files: "文件总数增减"
|
files: "文件总数增减"
|
||||||
filesTotal: "合计文件总数"
|
filesTotal: "文件数总计"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "首页"
|
home: "首页"
|
||||||
local: "本地"
|
local: "本地"
|
||||||
@ -651,45 +695,39 @@ _pages:
|
|||||||
newPage: "创建页面"
|
newPage: "创建页面"
|
||||||
editPage: "编辑页面"
|
editPage: "编辑页面"
|
||||||
readPage: "查看源"
|
readPage: "查看源"
|
||||||
page-created: "页面已创建"
|
created: "页面已创建"
|
||||||
page-updated: "页面已更新"
|
updated: "页面已更新"
|
||||||
name-already-exists: "该页面URL已存在"
|
deleted: "该页面已被删除"
|
||||||
title-invalid-name: "无效的页面URL"
|
nameAlreadyExists: "该页面URL已存在"
|
||||||
text-invalid-name: "请确认该项不为空"
|
invalidNameTitle: "无效的页面URL"
|
||||||
|
invalidNameText: "请确认该项不为空"
|
||||||
editThisPage: "编辑此页面"
|
editThisPage: "编辑此页面"
|
||||||
viewSource: "查看源代码"
|
viewSource: "查看源代码"
|
||||||
viewPage: "查看页面"
|
viewPage: "查看页面"
|
||||||
like: "赞"
|
like: "赞"
|
||||||
unlike: "取消赞"
|
unlike: "取消赞"
|
||||||
liked-pages: "喜欢的页面"
|
my: "我的页面"
|
||||||
my-pages: "我的页面"
|
liked: "喜欢的页面"
|
||||||
inspector: "检查器"
|
inspector: "检查器"
|
||||||
content: "页面内容"
|
content: "页面内容"
|
||||||
variables: "变量"
|
variables: "变量"
|
||||||
variables-info: "您可以使用变量创建动态页面。在文本中通过<b>{变量名}</b>的写法来嵌入变量值。例如在文本<b>Hello { thing } world!</b>中,如果变量(thing)的值为<b>ai</b>,那么该文本会成为<b>Hello ai world!</b>。"
|
|
||||||
variables-info2: "因为变量的计算(计算变量值)是从上到下执行的,所以不能在变量中引用下面的变量。例如从上到下依次定义了<b>A,B,C</b>3个变量,那么<b>C</b>中可以引用<b>A</b>或<b>B</b>,但是<b>A</b>无法引用<b>B</b>或<b>C</b>。"
|
|
||||||
variables-info3: "为了接收来自用户的输入,页面上设有“用户输入”块,在“变量名称”中设置要在其中保存输入值的变量名(变量会自动创建)。您可以使用该变量执行操作以响应用户输入。"
|
|
||||||
variables-info4: "通过使用函数,您可以将数值计算过程组合成可重用的形式。要创建函数,需要创建一个“函数”类型的变量。你可以将函数设定为槽函数(参数)的格式,槽函数的值可作为函数中的变量使用。另外,AiScript标准中还有一些函数会将函数作为参数(称为高阶函数)。\n除了已经预先定义的函数外,您也可以将它们设置为这些高阶函数的槽函数。"
|
|
||||||
more-details: "详细说明"
|
|
||||||
title: "标题"
|
title: "标题"
|
||||||
url: "页面URL"
|
url: "页面URL"
|
||||||
summary: "页面摘要"
|
summary: "页面摘要"
|
||||||
alignCenter: "居中"
|
alignCenter: "居中"
|
||||||
hide-title-when-pinned: "置顶时隐藏标题"
|
hideTitleWhenPinned: "置顶时隐藏标题"
|
||||||
font: "字体"
|
font: "字体"
|
||||||
fontSerif: "衬线字体"
|
fontSerif: "衬线字体"
|
||||||
fontSansSerif: "无衬线字体"
|
fontSansSerif: "无衬线字体"
|
||||||
set-eye-catching-image: "设置封面图片"
|
eyeCatchingImageSet: "设置封面图片"
|
||||||
remove-eye-catching-image: "删除封面图片"
|
eyeCatchingImageRemove: "删除封面图片"
|
||||||
chooseBlock: "添加块"
|
chooseBlock: "添加块"
|
||||||
selectType: "选择类型"
|
selectType: "选择类型"
|
||||||
enterVariableName: "请输入变量名"
|
enterVariableName: "请输入变量名"
|
||||||
the-variable-name-is-already-used: "变量名已使用"
|
variableNameIsAlreadyUsed: "变量名已使用"
|
||||||
content-blocks: "内容"
|
contentBlocks: "内容"
|
||||||
input-blocks: "输入"
|
inputBlocks: "输入"
|
||||||
special-blocks: "特殊"
|
specialBlocks: "特殊"
|
||||||
post-from-post-form: "发布此内容"
|
|
||||||
posted-from-post-form: "已发布"
|
|
||||||
blocks:
|
blocks:
|
||||||
text: "文本"
|
text: "文本"
|
||||||
textarea: "文本区域"
|
textarea: "文本区域"
|
||||||
|
@ -82,7 +82,6 @@ sensitive: "敏感內容"
|
|||||||
add: "新增"
|
add: "新增"
|
||||||
reaction: "反應"
|
reaction: "反應"
|
||||||
rememberNoteVisibility: "記住筆記隱私設定"
|
rememberNoteVisibility: "記住筆記隱私設定"
|
||||||
renameFile: "重新命名檔案"
|
|
||||||
attachCancel: "移除附件"
|
attachCancel: "移除附件"
|
||||||
markAsSensitive: "標記為敏感內容"
|
markAsSensitive: "標記為敏感內容"
|
||||||
unmarkAsSensitive: "取消標記為敏感內容"
|
unmarkAsSensitive: "取消標記為敏感內容"
|
||||||
@ -175,7 +174,6 @@ fromUrl: "從URL"
|
|||||||
explore: "探索"
|
explore: "探索"
|
||||||
games: "Misskey 遊戲"
|
games: "Misskey 遊戲"
|
||||||
messageRead: "已讀"
|
messageRead: "已讀"
|
||||||
recentUsedEmojis: "最近使用的表情符號"
|
|
||||||
noMoreHistory: "沒有更多歷史紀錄"
|
noMoreHistory: "沒有更多歷史紀錄"
|
||||||
startMessaging: "開始傳送訊息"
|
startMessaging: "開始傳送訊息"
|
||||||
nUsersRead: "{n}人已讀"
|
nUsersRead: "{n}人已讀"
|
||||||
@ -193,8 +191,9 @@ darkThemes: "灰暗主題"
|
|||||||
drive: "雲端硬碟"
|
drive: "雲端硬碟"
|
||||||
selectFile: "選擇檔案"
|
selectFile: "選擇檔案"
|
||||||
selectFiles: "選擇檔案"
|
selectFiles: "選擇檔案"
|
||||||
renameFolder: "重新命名資料夾"
|
renameFile: "重新命名檔案"
|
||||||
createFolder: "新增資料夾"
|
createFolder: "新增資料夾"
|
||||||
|
renameFolder: "重新命名資料夾"
|
||||||
deleteFolder: "刪除資料夾"
|
deleteFolder: "刪除資料夾"
|
||||||
addFile: "添加檔案"
|
addFile: "添加檔案"
|
||||||
emptyDrive: "雲端硬碟為空"
|
emptyDrive: "雲端硬碟為空"
|
||||||
|
36
migration/1585361548360-miauth.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class miauth1585361548360 implements MigrationInterface {
|
||||||
|
name = 'miauth1585361548360'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "lastUsedAt" TIMESTAMP WITH TIME ZONE DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "session" character varying(128) DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "name" character varying(128) DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "description" character varying(512) DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "iconUrl" character varying(512) DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "permission" character varying(64) array NOT NULL DEFAULT '{}'::varchar[]`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD "fetched" boolean NOT NULL DEFAULT false`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "appId" DROP NOT NULL`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "appId" SET DEFAULT null`, undefined);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_bf3a053c07d9fb5d87317c56ee" ON "access_token" ("session") `, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560"`, undefined);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_bf3a053c07d9fb5d87317c56ee"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "appId" DROP DEFAULT`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "appId" SET NOT NULL`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" ADD CONSTRAINT "FK_a3ff16c90cc87a82a0b5959e560" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "fetched"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "permission"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "iconUrl"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "description"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "name"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "session"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "lastUsedAt"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
48
migration/1585385921215-custom-notification.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class customNotification1585385921215 implements MigrationInterface {
|
||||||
|
name = 'customNotification1585385921215'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD "customBody" character varying(2048)`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD "customHeader" character varying(256)`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD "customIcon" character varying(1024)`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD "appAccessTokenId" character varying(32)`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "notifierId" DROP NOT NULL`, undefined);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "notification"."notifierId" IS 'The ID of sender user of the Notification.'`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`, undefined);
|
||||||
|
await queryRunner.query(`CREATE TYPE "notification_type_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "notification_type_enum" USING "type"::"text"::"notification_type_enum"`, undefined);
|
||||||
|
await queryRunner.query(`DROP TYPE "notification_type_enum_old"`, undefined);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "notification"."type" IS 'The type of the Notification.'`, undefined);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_3b4e96eec8d36a8bbb9d02aa71" ON "notification" ("notifierId") `, undefined);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_33f33cc8ef29d805a97ff4628b" ON "notification" ("type") `, undefined);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_080ab397c379af09b9d2169e5b" ON "notification" ("isRead") `, undefined);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_e22bf6bda77b6adc1fd9e75c8c" ON "notification" ("appAccessTokenId") `, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710" FOREIGN KEY ("notifierId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_e22bf6bda77b6adc1fd9e75c8c9" FOREIGN KEY ("appAccessTokenId") REFERENCES "access_token"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_e22bf6bda77b6adc1fd9e75c8c9"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710"`, undefined);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_e22bf6bda77b6adc1fd9e75c8c"`, undefined);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_080ab397c379af09b9d2169e5b"`, undefined);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_33f33cc8ef29d805a97ff4628b"`, undefined);
|
||||||
|
await queryRunner.query(`DROP INDEX "IDX_3b4e96eec8d36a8bbb9d02aa71"`, undefined);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "notification"."type" IS ''`, undefined);
|
||||||
|
await queryRunner.query(`CREATE TYPE "notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited')`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "notification_type_enum_old" USING "type"::"text"::"notification_type_enum_old"`, undefined);
|
||||||
|
await queryRunner.query(`DROP TYPE "notification_type_enum"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TYPE "notification_type_enum_old" RENAME TO "notification_type_enum"`, undefined);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "notification"."notifierId" IS ''`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "notifierId" SET NOT NULL`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_3b4e96eec8d36a8bbb9d02aa710" FOREIGN KEY ("notifierId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "appAccessTokenId"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "customIcon"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "customHeader"`, undefined);
|
||||||
|
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "customBody"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
migration/1585772678853-ap-url.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* tslint:disable:quotemark class-name indent */
|
||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class apUrl1585772678853 implements MigrationInterface {
|
||||||
|
name = 'apUrl1585772678853'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" ADD "url" character varying(512)`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "url"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
migration/1586624197029-AddObjectStorageUseProxy.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from 'typeorm';
|
||||||
|
|
||||||
|
export class AddObjectStorageUseProxy1586624197029 implements MigrationInterface {
|
||||||
|
name = 'AddObjectStorageUseProxy1586624197029'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "objectStorageUseProxy" boolean NOT NULL DEFAULT true`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageUseProxy"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
migration/1586641139527-remote-reaction.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class remoteReaction1586641139527 implements MigrationInterface {
|
||||||
|
name = 'remoteReaction1586641139527'
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(260)`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(130)`, undefined);
|
||||||
|
}
|
||||||
|
}
|
14
migration/1586708940386-pageAiScript.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class pageAiScript1586708940386 implements MigrationInterface {
|
||||||
|
name = 'pageAiScript1586708940386'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "page" ADD "script" character varying(16384) NOT NULL DEFAULT ''`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "script"`, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
147
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||||
"version": "12.23.0",
|
"version": "12.35.0",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -11,11 +11,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./index.js",
|
"start": "node ./index.js",
|
||||||
|
"start-product": "cross-env NODE_ENV=production node ./index.js",
|
||||||
"init": "npm run migrate",
|
"init": "npm run migrate",
|
||||||
"ormconfig": "node ./built/ormconfig.js",
|
"ormconfig": "node ./built/ormconfig.js",
|
||||||
"migrate": "ts-node ./node_modules/typeorm/cli.js migration:run",
|
"migrate": "ts-node ./node_modules/typeorm/cli.js migration:run",
|
||||||
"migrateandstart": "npm run migrate && npm run start",
|
"migrateandstart": "npm run migrate && npm run start",
|
||||||
"build": "webpack && gulp build",
|
"build": "webpack && gulp build",
|
||||||
|
"build-product": "cross-env NODE_ENV=production webpack && gulp build",
|
||||||
"webpack": "webpack",
|
"webpack": "webpack",
|
||||||
"watch": "webpack --watch",
|
"watch": "webpack --watch",
|
||||||
"gulp": "gulp build",
|
"gulp": "gulp build",
|
||||||
@ -30,18 +32,19 @@
|
|||||||
"lodash": "^4.17.13"
|
"lodash": "^4.17.13"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/elasticsearch": "7.6.0",
|
"@elastic/elasticsearch": "7.6.1",
|
||||||
"@fortawesome/fontawesome-svg-core": "1.2.27",
|
"@fortawesome/fontawesome-svg-core": "1.2.28",
|
||||||
"@fortawesome/free-brands-svg-icons": "5.12.1",
|
"@fortawesome/free-brands-svg-icons": "5.13.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "5.12.1",
|
"@fortawesome/free-regular-svg-icons": "5.13.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "5.12.1",
|
"@fortawesome/free-solid-svg-icons": "5.13.0",
|
||||||
"@fortawesome/vue-fontawesome": "0.1.9",
|
"@fortawesome/vue-fontawesome": "0.1.9",
|
||||||
"@juggle/resize-observer": "3.0.2",
|
"@juggle/resize-observer": "3.1.3",
|
||||||
"@koa/cors": "3.0.0",
|
"@koa/cors": "3.0.0",
|
||||||
"@koa/multer": "2.0.2",
|
"@koa/multer": "2.0.2",
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
|
"@syuilo/aiscript": "0.4.0",
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/bull": "3.12.0",
|
"@types/bull": "3.12.2",
|
||||||
"@types/cbor": "5.0.0",
|
"@types/cbor": "5.0.0",
|
||||||
"@types/dateformat": "3.0.1",
|
"@types/dateformat": "3.0.1",
|
||||||
"@types/double-ended-queue": "2.1.1",
|
"@types/double-ended-queue": "2.1.1",
|
||||||
@ -51,10 +54,10 @@
|
|||||||
"@types/gulp-rename": "0.0.33",
|
"@types/gulp-rename": "0.0.33",
|
||||||
"@types/gulp-replace": "0.0.31",
|
"@types/gulp-replace": "0.0.31",
|
||||||
"@types/is-url": "1.2.28",
|
"@types/is-url": "1.2.28",
|
||||||
"@types/js-yaml": "3.12.2",
|
"@types/js-yaml": "3.12.3",
|
||||||
"@types/jsdom": "12.2.4",
|
"@types/jsdom": "16.2.1",
|
||||||
"@types/katex": "0.11.0",
|
"@types/katex": "0.11.0",
|
||||||
"@types/koa": "2.11.1",
|
"@types/koa": "2.11.3",
|
||||||
"@types/koa-bodyparser": "4.3.0",
|
"@types/koa-bodyparser": "4.3.0",
|
||||||
"@types/koa-compress": "2.0.9",
|
"@types/koa-compress": "2.0.9",
|
||||||
"@types/koa-cors": "0.0.0",
|
"@types/koa-cors": "0.0.0",
|
||||||
@ -68,8 +71,9 @@
|
|||||||
"@types/koa__router": "8.0.2",
|
"@types/koa__router": "8.0.2",
|
||||||
"@types/lolex": "5.1.0",
|
"@types/lolex": "5.1.0",
|
||||||
"@types/markdown-it": "0.0.9",
|
"@types/markdown-it": "0.0.9",
|
||||||
"@types/mocha": "7.0.1",
|
"@types/mocha": "7.0.2",
|
||||||
"@types/node": "13.7.1",
|
"@types/node": "13.13.0",
|
||||||
|
"@types/node-fetch": "2.5.6",
|
||||||
"@types/nodemailer": "6.4.0",
|
"@types/nodemailer": "6.4.0",
|
||||||
"@types/nprogress": "0.2.0",
|
"@types/nprogress": "0.2.0",
|
||||||
"@types/oauth": "0.9.1",
|
"@types/oauth": "0.9.1",
|
||||||
@ -80,10 +84,8 @@
|
|||||||
"@types/qrcode": "1.3.4",
|
"@types/qrcode": "1.3.4",
|
||||||
"@types/random-seed": "0.3.3",
|
"@types/random-seed": "0.3.3",
|
||||||
"@types/ratelimiter": "2.1.28",
|
"@types/ratelimiter": "2.1.28",
|
||||||
"@types/redis": "2.8.15",
|
"@types/redis": "2.8.18",
|
||||||
"@types/rename": "1.0.1",
|
"@types/rename": "1.0.1",
|
||||||
"@types/request": "2.48.4",
|
|
||||||
"@types/request-promise-native": "1.0.17",
|
|
||||||
"@types/request-stats": "3.0.0",
|
"@types/request-stats": "3.0.0",
|
||||||
"@types/rimraf": "2.0.3",
|
"@types/rimraf": "2.0.3",
|
||||||
"@types/seedrandom": "2.4.28",
|
"@types/seedrandom": "2.4.28",
|
||||||
@ -93,47 +95,46 @@
|
|||||||
"@types/systeminformation": "3.54.1",
|
"@types/systeminformation": "3.54.1",
|
||||||
"@types/tinycolor2": "1.4.2",
|
"@types/tinycolor2": "1.4.2",
|
||||||
"@types/tmp": "0.1.0",
|
"@types/tmp": "0.1.0",
|
||||||
"@types/uuid": "3.4.7",
|
"@types/uuid": "7.0.2",
|
||||||
"@types/web-push": "3.3.0",
|
"@types/web-push": "3.3.0",
|
||||||
"@types/webpack": "4.41.6",
|
"@types/webpack": "4.41.10",
|
||||||
"@types/webpack-stream": "3.2.10",
|
"@types/webpack-stream": "3.2.10",
|
||||||
"@types/websocket": "1.0.0",
|
"@types/websocket": "1.0.0",
|
||||||
"@types/ws": "7.2.1",
|
"@types/ws": "7.2.4",
|
||||||
"@typescript-eslint/parser": "2.19.2",
|
"@typescript-eslint/parser": "2.28.0",
|
||||||
"agentkeepalive": "4.1.0",
|
"abort-controller": "3.0.0",
|
||||||
"animejs": "3.1.0",
|
"apexcharts": "3.18.1",
|
||||||
"apexcharts": "3.15.6",
|
|
||||||
"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.617.0",
|
"aws-sdk": "2.658.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bull": "3.12.1",
|
"bull": "3.13.0",
|
||||||
"cafy": "15.2.1",
|
"cafy": "15.2.1",
|
||||||
"cbor": "5.0.1",
|
"cbor": "5.0.2",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"chalk": "3.0.0",
|
"chalk": "4.0.0",
|
||||||
"chart.js": "2.9.3",
|
"chart.js": "2.9.3",
|
||||||
"cli-highlight": "2.1.4",
|
"cli-highlight": "2.1.4",
|
||||||
"commander": "4.1.1",
|
"commander": "4.1.1",
|
||||||
"content-disposition": "0.5.3",
|
"content-disposition": "0.5.3",
|
||||||
"crc-32": "1.2.0",
|
"crc-32": "1.2.0",
|
||||||
"css-loader": "3.4.2",
|
"css-loader": "3.5.2",
|
||||||
"cssnano": "4.1.10",
|
"cssnano": "4.1.10",
|
||||||
"dateformat": "3.0.3",
|
"dateformat": "3.0.3",
|
||||||
"diskusage": "1.1.3",
|
"diskusage": "1.1.3",
|
||||||
"double-ended-queue": "2.1.0-0",
|
"double-ended-queue": "2.1.0-0",
|
||||||
"eslint": "6.8.0",
|
"eslint": "6.8.0",
|
||||||
"eslint-plugin-vue": "6.1.2",
|
"eslint-plugin-vue": "6.2.2",
|
||||||
"eventemitter3": "4.0.0",
|
"eventemitter3": "4.0.0",
|
||||||
"feed": "4.1.0",
|
"feed": "4.1.0",
|
||||||
"fibers": "4.0.2",
|
"fibers": "4.0.2",
|
||||||
"file-type": "14.1.2",
|
"file-type": "14.1.4",
|
||||||
"fluent-ffmpeg": "2.1.2",
|
"fluent-ffmpeg": "2.1.2",
|
||||||
"glob": "7.1.6",
|
"glob": "7.1.6",
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-clean-css": "4.2.0",
|
"gulp-clean-css": "4.3.0",
|
||||||
"gulp-dart-sass": "0.9.1",
|
"gulp-dart-sass": "1.0.1",
|
||||||
"gulp-mocha": "7.0.2",
|
"gulp-mocha": "7.0.2",
|
||||||
"gulp-rename": "2.0.0",
|
"gulp-rename": "2.0.0",
|
||||||
"gulp-replace": "1.0.0",
|
"gulp-replace": "1.0.0",
|
||||||
@ -143,21 +144,22 @@
|
|||||||
"gulp-typescript": "5.0.1",
|
"gulp-typescript": "5.0.1",
|
||||||
"hard-source-webpack-plugin": "0.13.1",
|
"hard-source-webpack-plugin": "0.13.1",
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"http-signature": "1.3.1",
|
"http-proxy-agent": "4.0.1",
|
||||||
|
"http-signature": "1.3.4",
|
||||||
"https-proxy-agent": "5.0.0",
|
"https-proxy-agent": "5.0.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.13.1",
|
"js-yaml": "3.13.1",
|
||||||
"jsdom": "16.1.0",
|
"jsdom": "16.2.2",
|
||||||
"json5": "2.1.1",
|
"json5": "2.1.3",
|
||||||
"json5-loader": "3.0.0",
|
"json5-loader": "3.0.0",
|
||||||
"jsrsasign": "8.0.12",
|
"jsrsasign": "8.0.15",
|
||||||
"katex": "0.11.1",
|
"katex": "0.11.1",
|
||||||
"koa": "2.11.0",
|
"koa": "2.11.0",
|
||||||
"koa-bodyparser": "4.2.1",
|
"koa-bodyparser": "4.3.0",
|
||||||
"koa-compress": "3.0.0",
|
"koa-compress": "3.1.0",
|
||||||
"koa-favicon": "2.0.1",
|
"koa-favicon": "2.1.0",
|
||||||
"koa-json-body": "5.3.0",
|
"koa-json-body": "5.3.0",
|
||||||
"koa-logger": "3.2.1",
|
"koa-logger": "3.2.1",
|
||||||
"koa-mount": "4.0.0",
|
"koa-mount": "4.0.0",
|
||||||
@ -165,102 +167,101 @@
|
|||||||
"koa-slow": "2.1.0",
|
"koa-slow": "2.1.0",
|
||||||
"koa-views": "6.2.1",
|
"koa-views": "6.2.1",
|
||||||
"langmap": "0.0.16",
|
"langmap": "0.0.16",
|
||||||
"loader-utils": "1.2.3",
|
|
||||||
"lolex": "5.1.2",
|
"lolex": "5.1.2",
|
||||||
"lookup-dns-cache": "2.1.0",
|
"lookup-dns-cache": "2.1.0",
|
||||||
"markdown-it": "10.0.0",
|
"markdown-it": "10.0.0",
|
||||||
"mocha": "7.0.1",
|
"markdown-it-anchor": "5.2.7",
|
||||||
|
"mocha": "7.1.1",
|
||||||
"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": "1.0.4",
|
"nested-property": "1.0.4",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.0",
|
||||||
"nodemailer": "6.4.2",
|
"nodemailer": "6.4.6",
|
||||||
"nprogress": "0.2.0",
|
"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": "5.1.1",
|
"parse5": "5.1.1",
|
||||||
"parsimmon": "1.13.0",
|
"parsimmon": "1.13.0",
|
||||||
"pg": "7.18.1",
|
"pg": "8.0.2",
|
||||||
"portal-vue": "2.1.7",
|
"portal-vue": "2.1.7",
|
||||||
"portscanner": "2.2.0",
|
"portscanner": "2.2.0",
|
||||||
"postcss-loader": "3.0.0",
|
"postcss-loader": "3.0.0",
|
||||||
"prismjs": "1.19.0",
|
"prismjs": "1.20.0",
|
||||||
"probe-image-size": "5.0.0",
|
"probe-image-size": "5.0.0",
|
||||||
"progress-bar-webpack-plugin": "2.1.0",
|
"progress-bar-webpack-plugin": "2.1.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.1.6",
|
"pureimage": "0.2.1",
|
||||||
"qrcode": "1.4.4",
|
"qrcode": "1.4.4",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"randomcolor": "0.5.4",
|
"randomcolor": "0.5.4",
|
||||||
"ratelimiter": "3.4.0",
|
"ratelimiter": "3.4.1",
|
||||||
"recaptcha-promise": "0.1.3",
|
"recaptcha-promise": "0.1.3",
|
||||||
"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",
|
||||||
"rename": "1.0.4",
|
"rename": "1.0.4",
|
||||||
"request": "2.88.2",
|
|
||||||
"request-promise-native": "1.0.8",
|
|
||||||
"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.25.0",
|
"sass": "1.26.3",
|
||||||
"sass-loader": "8.0.2",
|
"sass-loader": "8.0.2",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"sharp": "0.24.0",
|
"sharp": "0.25.2",
|
||||||
"showdown": "1.9.1",
|
"showdown": "1.9.1",
|
||||||
"showdown-highlightjs-extension": "0.1.2",
|
"showdown-highlightjs-extension": "0.1.2",
|
||||||
"speakeasy": "2.0.0",
|
"speakeasy": "2.0.0",
|
||||||
"stringz": "2.0.0",
|
"stringz": "2.1.0",
|
||||||
"style-loader": "1.1.3",
|
"style-loader": "1.1.4",
|
||||||
"summaly": "2.3.1",
|
"summaly": "2.3.1",
|
||||||
"syslog-pro": "1.0.0",
|
"syslog-pro": "1.0.0",
|
||||||
"systeminformation": "4.21.2",
|
"systeminformation": "4.23.3",
|
||||||
"syuilo-password-strength": "0.0.1",
|
"syuilo-password-strength": "0.0.1",
|
||||||
"terser-webpack-plugin": "2.3.4",
|
"terser-webpack-plugin": "2.3.5",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.113.2",
|
"three": "0.115.0",
|
||||||
"tinycolor2": "1.4.1",
|
"tinycolor2": "1.4.1",
|
||||||
"tmp": "0.1.0",
|
"tmp": "0.1.0",
|
||||||
"ts-loader": "6.2.1",
|
"ts-loader": "6.2.2",
|
||||||
"ts-node": "8.6.2",
|
"ts-node": "8.8.2",
|
||||||
"tslint": "6.0.0",
|
"tslint": "6.1.1",
|
||||||
"tslint-sonarts": "1.9.0",
|
"tslint-sonarts": "1.9.0",
|
||||||
"typeorm": "0.2.22",
|
"typeorm": "0.2.24",
|
||||||
"typescript": "3.7.5",
|
"typescript": "3.8.3",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"url-loader": "3.0.0",
|
"url-loader": "3.0.0",
|
||||||
"uuid": "3.4.0",
|
"uuid": "7.0.3",
|
||||||
"v-animate-css": "0.0.3",
|
"v-animate-css": "0.0.3",
|
||||||
"v-debounce": "0.1.2",
|
"v-debounce": "0.1.2",
|
||||||
"vue": "2.6.11",
|
"vue": "2.6.11",
|
||||||
"vue-color": "2.7.0",
|
"vue-color": "2.7.1",
|
||||||
"vue-content-loading": "1.6.0",
|
"vue-content-loading": "1.6.0",
|
||||||
"vue-cropperjs": "4.0.1",
|
"vue-cropperjs": "4.1.0",
|
||||||
"vue-i18n": "8.15.3",
|
"vue-i18n": "8.17.2",
|
||||||
"vue-json-pretty": "1.6.3",
|
"vue-json-pretty": "1.6.3",
|
||||||
"vue-loader": "15.9.0",
|
"vue-loader": "15.9.1",
|
||||||
"vue-marquee-text-component": "1.1.1",
|
"vue-marquee-text-component": "1.1.1",
|
||||||
"vue-meta": "2.3.2",
|
"vue-meta": "2.3.3",
|
||||||
"vue-prism-component": "1.1.1",
|
"vue-prism-component": "1.2.0",
|
||||||
"vue-router": "3.1.5",
|
"vue-prism-editor": "0.5.1",
|
||||||
|
"vue-router": "3.1.6",
|
||||||
"vue-style-loader": "4.1.2",
|
"vue-style-loader": "4.1.2",
|
||||||
"vue-svg-inline-loader": "1.4.5",
|
"vue-svg-inline-loader": "1.5.0",
|
||||||
"vue-template-compiler": "2.6.11",
|
"vue-template-compiler": "2.6.11",
|
||||||
"vuedraggable": "2.23.2",
|
"vuedraggable": "2.23.2",
|
||||||
"vuex": "3.1.2",
|
"vuex": "3.1.3",
|
||||||
"vuex-persistedstate": "2.7.1",
|
"vuex-persistedstate": "3.0.1",
|
||||||
"web-push": "3.4.3",
|
"web-push": "3.4.3",
|
||||||
"webpack": "4.41.6",
|
"webpack": "4.42.1",
|
||||||
"webpack-cli": "3.3.11",
|
"webpack-cli": "3.3.11",
|
||||||
"websocket": "1.0.31",
|
"websocket": "1.0.31",
|
||||||
"ws": "7.2.1",
|
"ws": "7.2.3",
|
||||||
"xev": "2.0.1"
|
"xev": "2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -99,7 +99,7 @@ async function isPortAvailable(port: number): Promise<boolean> {
|
|||||||
function showEnvironment(): void {
|
function showEnvironment(): void {
|
||||||
const env = process.env.NODE_ENV;
|
const env = process.env.NODE_ENV;
|
||||||
const logger = bootLogger.createSubLogger('env');
|
const logger = bootLogger.createSubLogger('env');
|
||||||
logger.info(typeof env == 'undefined' ? 'NODE_ENV is not set' : `NODE_ENV: ${env}`);
|
logger.info(typeof env === 'undefined' ? 'NODE_ENV is not set' : `NODE_ENV: ${env}`);
|
||||||
|
|
||||||
if (env !== 'production') {
|
if (env !== 'production') {
|
||||||
logger.warn('The environment is not in production mode.');
|
logger.warn('The environment is not in production mode.');
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
<button class="item _button account" @click="openAccountMenu" v-if="$store.getters.isSignedIn">
|
<button class="item _button account" @click="openAccountMenu" v-if="$store.getters.isSignedIn">
|
||||||
<mk-avatar :user="$store.state.i" class="avatar"/><mk-acct class="text" :user="$store.state.i"/>
|
<mk-avatar :user="$store.state.i" class="avatar"/><mk-acct class="text" :user="$store.state.i"/>
|
||||||
</button>
|
</button>
|
||||||
<div class="divider"></div>
|
|
||||||
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
|
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
|
||||||
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
|
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
|
||||||
</button>
|
</button>
|
||||||
@ -157,14 +156,13 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
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, faGamepad, faServer, faFileAlt, faSatellite, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faTerminal, 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, faGamepad, faServer, faFileAlt, faSatellite, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
|
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { ResizeObserver } from '@juggle/resize-observer';
|
import { ResizeObserver } from '@juggle/resize-observer';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import i18n from './i18n';
|
import i18n from './i18n';
|
||||||
import { host, instanceName } from './config';
|
import { host, instanceName } from './config';
|
||||||
import { search } from './scripts/search';
|
import { search } from './scripts/search';
|
||||||
import { isDeviceDarkmode } from './scripts/is-device-darkmode';
|
|
||||||
import MkToast from './components/toast.vue';
|
import MkToast from './components/toast.vue';
|
||||||
|
|
||||||
const DESKTOP_THRESHOLD = 1100;
|
const DESKTOP_THRESHOLD = 1100;
|
||||||
@ -225,10 +223,6 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
if (this.$store.state.device.syncDeviceDarkMode) {
|
|
||||||
this.$store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.$store.getters.isSignedIn) {
|
if (this.$store.getters.isSignedIn) {
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
this.connection = this.$root.stream.useSharedConnection('main');
|
||||||
this.connection.on('notification', this.onNotification);
|
this.connection.on('notification', this.onNotification);
|
||||||
@ -252,7 +246,10 @@ export default Vue.extend({
|
|||||||
if (this.isDesktop) this.adjustWidgetsWidth();
|
if (this.isDesktop) this.adjustWidgetsWidth();
|
||||||
|
|
||||||
const adjustTitlePosition = () => {
|
const adjustTitlePosition = () => {
|
||||||
this.$refs.title.style.left = (this.$refs.main.getBoundingClientRect().left - this.$refs.nav.offsetWidth) + 'px';
|
const left = this.$refs.main.getBoundingClientRect().left - this.$refs.nav.offsetWidth;
|
||||||
|
if (left >= 0) {
|
||||||
|
this.$refs.title.style.left = left + 'px';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
adjustTitlePosition();
|
adjustTitlePosition();
|
||||||
@ -313,7 +310,7 @@ export default Vue.extend({
|
|||||||
title: this.$t('search'),
|
title: this.$t('search'),
|
||||||
input: true
|
input: true
|
||||||
}).then(async ({ canceled, result: query }) => {
|
}).then(async ({ canceled, result: query }) => {
|
||||||
if (canceled || query == null || query == '') return;
|
if (canceled || query == null || query === '') return;
|
||||||
|
|
||||||
this.searching = true;
|
this.searching = true;
|
||||||
search(this, query).finally(() => {
|
search(this, query).finally(() => {
|
||||||
@ -323,7 +320,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
searchKeypress(e) {
|
searchKeypress(e) {
|
||||||
if (e.keyCode == 13) {
|
if (e.keyCode === 13) {
|
||||||
this.searchWait = true;
|
this.searchWait = true;
|
||||||
search(this, this.searchQuery).finally(() => {
|
search(this, this.searchQuery).finally(() => {
|
||||||
this.searchWait = false;
|
this.searchWait = false;
|
||||||
@ -473,6 +470,11 @@ export default Vue.extend({
|
|||||||
to: '/games',
|
to: '/games',
|
||||||
icon: faGamepad,
|
icon: faGamepad,
|
||||||
}, null] : []), {
|
}, null] : []), {
|
||||||
|
type: 'link',
|
||||||
|
text: this.$t('scratchpad'),
|
||||||
|
to: '/scratchpad',
|
||||||
|
icon: faTerminal,
|
||||||
|
}, null, {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
text: this.$t('help'),
|
text: this.$t('help'),
|
||||||
to: '/docs',
|
to: '/docs',
|
||||||
@ -622,12 +624,12 @@ export default Vue.extend({
|
|||||||
.mk-app {
|
.mk-app {
|
||||||
$header-height: 60px;
|
$header-height: 60px;
|
||||||
$nav-width: 250px;
|
$nav-width: 250px;
|
||||||
$nav-icon-only-width: 74px;
|
$nav-icon-only-width: 80px;
|
||||||
$main-width: 650px;
|
$main-width: 650px;
|
||||||
$ui-font-size: 1em;
|
$ui-font-size: 1em;
|
||||||
$nav-icon-only-threshold: 1300px;
|
$nav-icon-only-threshold: 1300px;
|
||||||
$nav-hide-threshold: 700px;
|
$nav-hide-threshold: 650px;
|
||||||
$side-hide-threshold: 1100px;
|
$side-hide-threshold: 1070px;
|
||||||
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -822,8 +824,6 @@ export default Vue.extend({
|
|||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
width: $nav-width;
|
width: $nav-width;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 16px 0;
|
|
||||||
padding-bottom: calc(3.7rem + 24px);
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: var(--navBg);
|
background: var(--navBg);
|
||||||
@ -836,13 +836,21 @@ export default Vue.extend({
|
|||||||
|
|
||||||
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
|
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
|
||||||
width: $nav-icon-only-width;
|
width: $nav-icon-only-width;
|
||||||
padding: 8px 0;
|
|
||||||
padding-bottom: calc(3.7rem + 24px);
|
|
||||||
|
|
||||||
> .divider {
|
> .divider {
|
||||||
margin: 8px auto;
|
margin: 8px auto;
|
||||||
width: calc(100% - 32px);
|
width: calc(100% - 32px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .item {
|
||||||
|
&:first-child {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .item {
|
> .item {
|
||||||
@ -892,15 +900,26 @@ export default Vue.extend({
|
|||||||
color: var(--navActive);
|
color: var(--navActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:first-child, &:last-child {
|
||||||
position: fixed;
|
position: sticky;
|
||||||
bottom: 0;
|
z-index: 1;
|
||||||
width: inherit;
|
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
background: var(--navBg);
|
background: var(--wboyroyc);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
top: 0;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
border-bottom: solid 1px var(--divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
bottom: 0;
|
||||||
|
margin-top: 16px;
|
||||||
border-top: solid 1px var(--divider);
|
border-top: solid 1px var(--divider);
|
||||||
border-right: solid 1px var(--divider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
|
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
|
||||||
@ -961,6 +980,10 @@ export default Vue.extend({
|
|||||||
&:not(.naked) {
|
&:not(.naked) {
|
||||||
background: var(--pageBg);
|
background: var(--pageBg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.naked {
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<redoc spec-url='/api.json'></redoc>
|
<redoc spec-url="/api.json" expand-responses="200" expand-single-schema-field="true"></redoc>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
7
src/client/assets/unread.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" width="32px" height="32px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
|
||||||
|
<circle fill="#3AA2DC" cx="16.5" cy="16.5" r="6"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 536 B |
@ -38,13 +38,6 @@ import Vue from 'vue';
|
|||||||
import * as tinycolor from 'tinycolor2';
|
import * as tinycolor from 'tinycolor2';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: {
|
|
||||||
smooth: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
now: new Date(),
|
now: new Date(),
|
||||||
@ -83,9 +76,6 @@ export default Vue.extend({
|
|||||||
return tinycolor(this.computedStyle.getPropertyValue('--accent')).toHexString();
|
return tinycolor(this.computedStyle.getPropertyValue('--accent')).toHexString();
|
||||||
},
|
},
|
||||||
|
|
||||||
ms(): number {
|
|
||||||
return this.now.getMilliseconds() * (this.smooth ? 1 : 0);
|
|
||||||
},
|
|
||||||
s(): number {
|
s(): number {
|
||||||
return this.now.getSeconds();
|
return this.now.getSeconds();
|
||||||
},
|
},
|
||||||
@ -97,13 +87,13 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
hAngle(): number {
|
hAngle(): number {
|
||||||
return Math.PI * (this.h % 12 + (this.m + (this.s + this.ms / 1000) / 60) / 60) / 6;
|
return Math.PI * (this.h % 12 + (this.m + this.s / 60) / 60) / 6;
|
||||||
},
|
},
|
||||||
mAngle(): number {
|
mAngle(): number {
|
||||||
return Math.PI * (this.m + (this.s + this.ms / 1000) / 60) / 30;
|
return Math.PI * (this.m + this.s / 60) / 30;
|
||||||
},
|
},
|
||||||
sAngle(): number {
|
sAngle(): number {
|
||||||
return Math.PI * (this.s + this.ms / 1000) / 30;
|
return Math.PI * this.s / 30;
|
||||||
},
|
},
|
||||||
|
|
||||||
graduations(): any {
|
graduations(): any {
|
||||||
@ -121,7 +111,7 @@ export default Vue.extend({
|
|||||||
const update = () => {
|
const update = () => {
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
this.tick();
|
this.tick();
|
||||||
requestAnimationFrame(update);
|
setTimeout(update, 1000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
update();
|
update();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<component :is="$store.state.device.animation ? 'transition-group' : 'div'" class="sqadhkmv" name="list" tag="div" :data-direction="direction" :data-reversed="reversed ? 'true' : 'false'">
|
<component :is="$store.state.device.animation ? 'transition-group' : 'div'" class="sqadhkmv" 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" :i="i"></slot>
|
<slot :item="item"></slot>
|
||||||
<div class="separator" :key="item.id + '_date'" v-if="showDate(i, item)">
|
<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>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mjndxjcg _panel">
|
<div class="mjndxjcg _panel">
|
||||||
<img src="https://xn--931a.moe/assets/error.png" 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('error') }}</p>
|
||||||
<mk-button @click="() => $emit('retry')" class="button">{{ $t('retry') }}</mk-button>
|
<mk-button @click="() => $emit('retry')" class="button">{{ $t('retry') }}</mk-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { url as local } from '../config';
|
import { url as local } from '../config';
|
||||||
import XUrlPreview from './url-preview-popup.vue';
|
import MkUrlPreview from './url-preview-popup.vue';
|
||||||
|
import { isDeviceTouch } from '../scripts/is-device-touch';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: {
|
props: {
|
||||||
@ -44,7 +45,7 @@ export default Vue.extend({
|
|||||||
if (!document.body.contains(this.$el)) return;
|
if (!document.body.contains(this.$el)) return;
|
||||||
if (this.preview) return;
|
if (this.preview) return;
|
||||||
|
|
||||||
this.preview = new XUrlPreview({
|
this.preview = new MkUrlPreview({
|
||||||
parent: this,
|
parent: this,
|
||||||
propsData: {
|
propsData: {
|
||||||
url: this.url,
|
url: this.url,
|
||||||
@ -61,11 +62,13 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMouseover() {
|
onMouseover() {
|
||||||
|
if (isDeviceTouch()) return;
|
||||||
clearTimeout(this.showTimer);
|
clearTimeout(this.showTimer);
|
||||||
clearTimeout(this.hideTimer);
|
clearTimeout(this.hideTimer);
|
||||||
this.showTimer = setTimeout(this.showPreview, 500);
|
this.showTimer = setTimeout(this.showPreview, 500);
|
||||||
},
|
},
|
||||||
onMouseleave() {
|
onMouseleave() {
|
||||||
|
if (isDeviceTouch()) return;
|
||||||
clearTimeout(this.showTimer);
|
clearTimeout(this.showTimer);
|
||||||
clearTimeout(this.hideTimer);
|
clearTimeout(this.hideTimer);
|
||||||
this.hideTimer = setTimeout(this.closePreview, 500);
|
this.hideTimer = setTimeout(this.closePreview, 500);
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="qjewsnkgzzxlxtzncydssfbgjibiehcy" v-if="image.isSensitive && hide && !$store.state.device.alwaysShowNsfw" @click="hide = false">
|
<div class="qjewsnkgzzxlxtzncydssfbgjibiehcy" v-if="hide" @click="hide = false">
|
||||||
<div>
|
<div>
|
||||||
<b><fa :icon="faExclamationTriangle"/> {{ $t('sensitive') }}</b>
|
<b><fa :icon="faExclamationTriangle"/> {{ $t('sensitive') }}</b>
|
||||||
<span>{{ $t('clickToShow') }}</span>
|
<span>{{ $t('clickToShow') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="gqnyydlzavusgskkfvwvjiattxdzsqlf" v-else
|
<div class="gqnyydlzavusgskkfvwvjiattxdzsqlf" v-else>
|
||||||
|
<i><fa :icon="faEyeSlash" @click="hide = true"/></i>
|
||||||
|
<a
|
||||||
:href="image.url"
|
:href="image.url"
|
||||||
:style="style"
|
:style="style"
|
||||||
:title="image.name"
|
:title="image.name"
|
||||||
@ -13,11 +15,12 @@
|
|||||||
>
|
>
|
||||||
<div v-if="image.type === 'image/gif'">GIF</div>
|
<div v-if="image.type === 'image/gif'">GIF</div>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
import { getStaticImageUrl } from '../scripts/get-static-image-url';
|
||||||
import ImageViewer from './image-viewer.vue';
|
import ImageViewer from './image-viewer.vue';
|
||||||
@ -36,7 +39,8 @@ export default Vue.extend({
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hide: true,
|
hide: true,
|
||||||
faExclamationTriangle
|
faExclamationTriangle,
|
||||||
|
faEyeSlash
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -59,6 +63,9 @@ export default Vue.extend({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.hide = this.image.isSensitive && !this.$store.state.device.alwaysShowNsfw;
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick() {
|
onClick() {
|
||||||
if (this.$store.state.device.imageNewTab) {
|
if (this.$store.state.device.imageNewTab) {
|
||||||
@ -78,6 +85,24 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.gqnyydlzavusgskkfvwvjiattxdzsqlf {
|
.gqnyydlzavusgskkfvwvjiattxdzsqlf {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> i {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: var(--fg);
|
||||||
|
color: var(--accentLighten);
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: .5;
|
||||||
|
padding: 3px 6px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> a {
|
||||||
display: block;
|
display: block;
|
||||||
cursor: zoom-in;
|
cursor: zoom-in;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -102,6 +127,7 @@ export default Vue.extend({
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.qjewsnkgzzxlxtzncydssfbgjibiehcy {
|
.qjewsnkgzzxlxtzncydssfbgjibiehcy {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -34,9 +34,7 @@ export default Vue.extend({
|
|||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
// specify the parent element
|
// specify the parent element
|
||||||
parentElement: {
|
parentElement: {}
|
||||||
type: Object
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -69,7 +67,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
if (this.$refs.gridOuter) {
|
if (this.$refs.gridOuter) {
|
||||||
let height = 287;
|
let height = 287;
|
||||||
const parent = this.$props.parentElement || this.$parent.$el;
|
const parent = this.parentElement || this.$parent.$el;
|
||||||
|
|
||||||
if (this.$refs.gridOuter.clientHeight) {
|
if (this.$refs.gridOuter.clientHeight) {
|
||||||
height = this.$refs.gridOuter.clientHeight;
|
height = this.$refs.gridOuter.clientHeight;
|
||||||
@ -83,6 +81,11 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
parentElement() {
|
||||||
|
this.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="video.isSensitive && hide && !$store.state.device.alwaysShowNsfw" @click="hide = false">
|
<div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="hide" @click="hide = false">
|
||||||
<div>
|
<div>
|
||||||
<b><fa icon="exclamation-triangle"/> {{ $t('sensitive') }}</b>
|
<b><fa :icon="faExclamationTriangle"/> {{ $t('sensitive') }}</b>
|
||||||
<span>{{ $t('clickToShow') }}</span>
|
<span>{{ $t('clickToShow') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="kkjnbbplepmiyuadieoenjgutgcmtsvu" v-else
|
<div class="kkjnbbplepmiyuadieoenjgutgcmtsvu" v-else>
|
||||||
|
<i><fa :icon="faEyeSlash" @click="hide = true"/></i>
|
||||||
|
<a
|
||||||
:href="video.url"
|
:href="video.url"
|
||||||
rel="nofollow noopener"
|
rel="nofollow noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -14,11 +16,13 @@
|
|||||||
>
|
>
|
||||||
<fa :icon="faPlayCircle"/>
|
<fa :icon="faPlayCircle"/>
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faPlayCircle } from '@fortawesome/free-regular-svg-icons';
|
import { faPlayCircle } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
@ -32,7 +36,9 @@ export default Vue.extend({
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hide: true,
|
hide: true,
|
||||||
faPlayCircle
|
faPlayCircle,
|
||||||
|
faExclamationTriangle,
|
||||||
|
faEyeSlash
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -41,12 +47,33 @@ export default Vue.extend({
|
|||||||
'background-image': `url(${this.video.thumbnailUrl})`
|
'background-image': `url(${this.video.thumbnailUrl})`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
created() {
|
||||||
|
this.hide = this.video.isSensitive && !this.$store.state.device.alwaysShowNsfw;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.kkjnbbplepmiyuadieoenjgutgcmtsvu {
|
.kkjnbbplepmiyuadieoenjgutgcmtsvu {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> i {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: var(--fg);
|
||||||
|
color: var(--accentLighten);
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: .5;
|
||||||
|
padding: 3px 6px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> a {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -58,6 +85,7 @@ export default Vue.extend({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icozogqfvdetwohsdglrbswgrejoxbdj {
|
.icozogqfvdetwohsdglrbswgrejoxbdj {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<mk-avatar class="avatar" :user="appearNote.user"/>
|
<mk-avatar class="avatar" :user="appearNote.user"/>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<x-note-header class="header" :note="appearNote" :mini="true"/>
|
<x-note-header class="header" :note="appearNote" :mini="true"/>
|
||||||
<div class="body" v-if="appearNote.deletedAt == null">
|
<div class="body" v-if="appearNote.deletedAt == null" ref="noteBody">
|
||||||
<p v-if="appearNote.cw != null" class="cw">
|
<p v-if="appearNote.cw != null" class="cw">
|
||||||
<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" />
|
<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" />
|
||||||
<x-cw-button v-model="showContent" :note="appearNote"/>
|
<x-cw-button v-model="showContent" :note="appearNote"/>
|
||||||
@ -46,10 +46,10 @@
|
|||||||
<a class="rp" v-if="appearNote.renote != null">RN:</a>
|
<a class="rp" v-if="appearNote.renote != null">RN:</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="files" v-if="appearNote.files.length > 0">
|
<div class="files" v-if="appearNote.files.length > 0">
|
||||||
<x-media-list :media-list="appearNote.files"/>
|
<x-media-list :media-list="appearNote.files" :parent-element="noteBody"/>
|
||||||
</div>
|
</div>
|
||||||
<x-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
|
<x-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
|
||||||
<x-url-preview v-for="url in urls" :url="url" :key="url" :compact="true" class="url-preview"/>
|
<mk-url-preview v-for="url in urls" :url="url" :key="url" :compact="true" class="url-preview"/>
|
||||||
<div class="renote" v-if="appearNote.renote"><x-note-preview :note="appearNote.renote"/></div>
|
<div class="renote" v-if="appearNote.renote"><x-note-preview :note="appearNote.renote"/></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -97,7 +97,7 @@ import XReactionsViewer from './reactions-viewer.vue';
|
|||||||
import XMediaList from './media-list.vue';
|
import XMediaList from './media-list.vue';
|
||||||
import XCwButton from './cw-button.vue';
|
import XCwButton from './cw-button.vue';
|
||||||
import XPoll from './poll.vue';
|
import XPoll from './poll.vue';
|
||||||
import XUrlPreview from './url-preview.vue';
|
import MkUrlPreview from './url-preview.vue';
|
||||||
import MkReactionPicker from './reaction-picker.vue';
|
import MkReactionPicker from './reaction-picker.vue';
|
||||||
import pleaseLogin from '../scripts/please-login';
|
import pleaseLogin from '../scripts/please-login';
|
||||||
import { focusPrev, focusNext } from '../scripts/focus';
|
import { focusPrev, focusNext } from '../scripts/focus';
|
||||||
@ -115,7 +115,7 @@ export default Vue.extend({
|
|||||||
XMediaList,
|
XMediaList,
|
||||||
XCwButton,
|
XCwButton,
|
||||||
XPoll,
|
XPoll,
|
||||||
XUrlPreview,
|
MkUrlPreview,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -142,6 +142,7 @@ export default Vue.extend({
|
|||||||
replies: [],
|
replies: [],
|
||||||
showContent: false,
|
showContent: false,
|
||||||
hideThisNote: false,
|
hideThisNote: false,
|
||||||
|
noteBody: this.$refs.noteBody,
|
||||||
faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan
|
faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -254,6 +255,8 @@ export default Vue.extend({
|
|||||||
if (this.$store.getters.isSignedIn) {
|
if (this.$store.getters.isSignedIn) {
|
||||||
this.connection.on('_connected_', this.onStreamConnected);
|
this.connection.on('_connected_', this.onStreamConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.noteBody = this.$refs.noteBody
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
@ -301,6 +304,14 @@ export default Vue.extend({
|
|||||||
case 'reacted': {
|
case 'reacted': {
|
||||||
const reaction = body.reaction;
|
const reaction = body.reaction;
|
||||||
|
|
||||||
|
if (body.emoji) {
|
||||||
|
const emojis = this.appearNote.emojis || [];
|
||||||
|
if (!emojis.includes(body.emoji)) {
|
||||||
|
emojis.push(body.emoji);
|
||||||
|
Vue.set(this.appearNote, 'emojis', emojis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.appearNote.reactions == null) {
|
if (this.appearNote.reactions == null) {
|
||||||
Vue.set(this.appearNote, 'reactions', {});
|
Vue.set(this.appearNote, 'reactions', {});
|
||||||
}
|
}
|
||||||
@ -517,11 +528,11 @@ export default Vue.extend({
|
|||||||
icon: faLink,
|
icon: faLink,
|
||||||
text: this.$t('copyLink'),
|
text: this.$t('copyLink'),
|
||||||
action: this.copyLink
|
action: this.copyLink
|
||||||
}, this.appearNote.uri ? {
|
}, (this.appearNote.url || this.appearNote.uri) ? {
|
||||||
icon: faExternalLinkSquareAlt,
|
icon: faExternalLinkSquareAlt,
|
||||||
text: this.$t('showOnRemote'),
|
text: this.$t('showOnRemote'),
|
||||||
action: () => {
|
action: () => {
|
||||||
window.open(this.appearNote.uri, '_blank');
|
window.open(this.appearNote.url || this.appearNote.uri, '_blank');
|
||||||
}
|
}
|
||||||
} : undefined,
|
} : undefined,
|
||||||
null,
|
null,
|
||||||
@ -561,13 +572,13 @@ export default Vue.extend({
|
|||||||
}]
|
}]
|
||||||
: []
|
: []
|
||||||
),
|
),
|
||||||
...(this.appearNote.userId == this.$store.state.i.id ? [
|
...(this.appearNote.userId == this.$store.state.i.id || this.$store.state.i.isModerator || this.$store.state.i.isAdmin ? [
|
||||||
null,
|
null,
|
||||||
{
|
this.appearNote.userId == this.$store.state.i.id ? {
|
||||||
icon: faEdit,
|
icon: faEdit,
|
||||||
text: this.$t('deleteAndEdit'),
|
text: this.$t('deleteAndEdit'),
|
||||||
action: this.delEdit
|
action: this.delEdit
|
||||||
},
|
} : undefined,
|
||||||
{
|
{
|
||||||
icon: faTrashAlt,
|
icon: faTrashAlt,
|
||||||
text: this.$t('delete'),
|
text: this.$t('delete'),
|
||||||
@ -585,11 +596,11 @@ export default Vue.extend({
|
|||||||
icon: faLink,
|
icon: faLink,
|
||||||
text: this.$t('copyLink'),
|
text: this.$t('copyLink'),
|
||||||
action: this.copyLink
|
action: this.copyLink
|
||||||
}, this.appearNote.uri ? {
|
}, (this.appearNote.url || this.appearNote.uri) ? {
|
||||||
icon: faExternalLinkSquareAlt,
|
icon: faExternalLinkSquareAlt,
|
||||||
text: this.$t('showOnRemote'),
|
text: this.$t('showOnRemote'),
|
||||||
action: () => {
|
action: () => {
|
||||||
window.open(this.appearNote.uri, '_blank');
|
window.open(this.appearNote.url || this.appearNote.uri, '_blank');
|
||||||
}
|
}
|
||||||
} : undefined]
|
} : undefined]
|
||||||
.filter(x => x !== undefined);
|
.filter(x => x !== undefined);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-notes" v-size="[{ max: 500 }]">
|
<div class="mk-notes" v-size="[{ max: 500 }]">
|
||||||
<div class="empty" v-if="empty">
|
<div class="_fullinfo" v-if="empty">
|
||||||
<img src="https://xn--931a.moe/assets/info.png" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||||
<div>{{ $t('noNotes') }}</div>
|
<div>{{ $t('noNotes') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -90,18 +90,6 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.mk-notes {
|
.mk-notes {
|
||||||
> .empty {
|
|
||||||
padding: 32px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 128px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .notes {
|
> .notes {
|
||||||
> ::v-deep *:not(:last-child) {
|
> ::v-deep *:not(:last-child) {
|
||||||
margin-bottom: var(--marginFull);
|
margin-bottom: var(--marginFull);
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-notification" :class="notification.type" v-size="[{ max: 500 }, { max: 600 }]">
|
<div class="mk-notification" :class="notification.type" v-size="[{ max: 500 }, { max: 600 }]">
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<mk-avatar class="avatar" :user="notification.user"/>
|
<mk-avatar v-if="notification.user" class="icon" :user="notification.user"/>
|
||||||
<div class="icon" :class="notification.type">
|
<img v-else class="icon" :src="notification.icon" alt=""/>
|
||||||
|
<div class="sub-icon" :class="notification.type">
|
||||||
<fa :icon="faPlus" v-if="notification.type === 'follow'"/>
|
<fa :icon="faPlus" v-if="notification.type === 'follow'"/>
|
||||||
<fa :icon="faClock" v-if="notification.type === 'receiveFollowRequest'"/>
|
<fa :icon="faClock" v-else-if="notification.type === 'receiveFollowRequest'"/>
|
||||||
<fa :icon="faCheck" v-if="notification.type === 'followRequestAccepted'"/>
|
<fa :icon="faCheck" v-else-if="notification.type === 'followRequestAccepted'"/>
|
||||||
<fa :icon="faIdCardAlt" v-if="notification.type === 'groupInvited'"/>
|
<fa :icon="faIdCardAlt" v-else-if="notification.type === 'groupInvited'"/>
|
||||||
<fa :icon="faRetweet" v-if="notification.type === 'renote'"/>
|
<fa :icon="faRetweet" v-else-if="notification.type === 'renote'"/>
|
||||||
<fa :icon="faReply" v-if="notification.type === 'reply'"/>
|
<fa :icon="faReply" v-else-if="notification.type === 'reply'"/>
|
||||||
<fa :icon="faAt" v-if="notification.type === 'mention'"/>
|
<fa :icon="faAt" v-else-if="notification.type === 'mention'"/>
|
||||||
<fa :icon="faQuoteLeft" v-if="notification.type === 'quote'"/>
|
<fa :icon="faQuoteLeft" v-else-if="notification.type === 'quote'"/>
|
||||||
<x-reaction-icon v-if="notification.type === 'reaction'" :reaction="notification.reaction" :no-style="true"/>
|
<x-reaction-icon v-else-if="notification.type === 'reaction'" :reaction="notification.reaction" :customEmojis="notification.note.emojis" :no-style="true"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tail">
|
<div class="tail">
|
||||||
<header>
|
<header>
|
||||||
<router-link class="name" :to="notification.user | userPage" v-user-preview="notification.user.id"><mk-user-name :user="notification.user"/></router-link>
|
<router-link v-if="notification.user" class="name" :to="notification.user | userPage" v-user-preview="notification.user.id"><mk-user-name :user="notification.user"/></router-link>
|
||||||
|
<span v-else>{{ notification.header }}</span>
|
||||||
<mk-time :time="notification.createdAt" v-if="withTime"/>
|
<mk-time :time="notification.createdAt" v-if="withTime"/>
|
||||||
</header>
|
</header>
|
||||||
<router-link v-if="notification.type === 'reaction'" class="text" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
<router-link v-if="notification.type === 'reaction'" class="text" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||||
@ -42,6 +44,9 @@
|
|||||||
<span v-if="notification.type === 'followRequestAccepted'" class="text" style="opacity: 0.6;">{{ $t('followRequestAccepted') }}</span>
|
<span v-if="notification.type === 'followRequestAccepted'" class="text" style="opacity: 0.6;">{{ $t('followRequestAccepted') }}</span>
|
||||||
<span v-if="notification.type === 'receiveFollowRequest'" class="text" style="opacity: 0.6;">{{ $t('receiveFollowRequest') }}<div v-if="full && !followRequestDone"><button class="_textButton" @click="acceptFollowRequest()">{{ $t('accept') }}</button> | <button class="_textButton" @click="rejectFollowRequest()">{{ $t('reject') }}</button></div></span>
|
<span v-if="notification.type === 'receiveFollowRequest'" class="text" style="opacity: 0.6;">{{ $t('receiveFollowRequest') }}<div v-if="full && !followRequestDone"><button class="_textButton" @click="acceptFollowRequest()">{{ $t('accept') }}</button> | <button class="_textButton" @click="rejectFollowRequest()">{{ $t('reject') }}</button></div></span>
|
||||||
<span v-if="notification.type === 'groupInvited'" class="text" style="opacity: 0.6;">{{ $t('groupInvited') }}: <b>{{ notification.invitation.group.name }}</b><div v-if="full && !groupInviteDone"><button class="_textButton" @click="acceptGroupInvitation()">{{ $t('accept') }}</button> | <button class="_textButton" @click="rejectGroupInvitation()">{{ $t('reject') }}</button></div></span>
|
<span v-if="notification.type === 'groupInvited'" class="text" style="opacity: 0.6;">{{ $t('groupInvited') }}: <b>{{ notification.invitation.group.name }}</b><div v-if="full && !groupInviteDone"><button class="_textButton" @click="acceptGroupInvitation()">{{ $t('accept') }}</button> | <button class="_textButton" @click="rejectGroupInvitation()">{{ $t('reject') }}</button></div></span>
|
||||||
|
<span v-if="notification.type === 'app'" class="text">
|
||||||
|
<mfm :text="notification.body" :nowrap="!full"/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -142,14 +147,14 @@ export default Vue.extend({
|
|||||||
height: 42px;
|
height: 42px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
|
||||||
> .avatar {
|
> .icon {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .icon {
|
> .sub-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
@ -163,6 +168,10 @@ export default Vue.extend({
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -35,6 +35,7 @@ export default Vue.extend({
|
|||||||
border: solid var(--lineWidth) var(--urlPreviewBorder);
|
border: solid var(--lineWidth) var(--urlPreviewBorder);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--divider);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -42,9 +43,8 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .thumbnail {
|
> .thumbnail {
|
||||||
position: absolute;
|
width: 100%;
|
||||||
width: 100px;
|
height: 200px;
|
||||||
height: 100%;
|
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -17,10 +17,11 @@ import XTextarea from './page.textarea.vue';
|
|||||||
import XPost from './page.post.vue';
|
import XPost from './page.post.vue';
|
||||||
import XCounter from './page.counter.vue';
|
import XCounter from './page.counter.vue';
|
||||||
import XRadioButton from './page.radio-button.vue';
|
import XRadioButton from './page.radio-button.vue';
|
||||||
|
import XCanvas from './page.canvas.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf, XCounter, XRadioButton
|
XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf, XCounter, XRadioButton, XCanvas
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
|
@ -28,7 +28,7 @@ export default Vue.extend({
|
|||||||
text: this.script.interpolate(this.value.content)
|
text: this.script.interpolate(this.value.content)
|
||||||
});
|
});
|
||||||
} else if (this.value.action === 'resetRandom') {
|
} else if (this.value.action === 'resetRandom') {
|
||||||
this.script.aiScript.updateRandomSeed(Math.random());
|
this.script.aoiScript.updateRandomSeed(Math.random());
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
} else if (this.value.action === 'pushEvent') {
|
} else if (this.value.action === 'pushEvent') {
|
||||||
this.$root.api('page-push', {
|
this.$root.api('page-push', {
|
||||||
@ -43,6 +43,8 @@ export default Vue.extend({
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: this.script.interpolate(this.value.message)
|
text: this.script.interpolate(this.value.message)
|
||||||
});
|
});
|
||||||
|
} else if (this.value.action === 'callAiScript') {
|
||||||
|
this.script.callAiScript(this.value.fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/client/components/page/page.canvas.vue
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ysrxegms">
|
||||||
|
<canvas ref="canvas" :width="value.width" :height="value.height"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
script: {
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.script.aoiScript.registerCanvas(this.value.name, this.$refs.canvas);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ysrxegms {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: bottom;
|
||||||
|
|
||||||
|
> canvas {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -27,7 +27,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -27,7 +27,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import Vue from 'vue';
|
|||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import MkTextarea from '../ui/textarea.vue';
|
import MkTextarea from '../ui/textarea.vue';
|
||||||
import MkButton from '../ui/button.vue';
|
import MkButton from '../ui/button.vue';
|
||||||
|
import { apiUrl } from '../../config';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
@ -41,10 +42,39 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
post() {
|
upload() {
|
||||||
|
return new Promise((ok) => {
|
||||||
|
const dialog = this.$root.dialog({
|
||||||
|
type: 'waiting',
|
||||||
|
text: this.$t('uploading') + '...',
|
||||||
|
showOkButton: false,
|
||||||
|
showCancelButton: false,
|
||||||
|
cancelableByBgClick: false
|
||||||
|
});
|
||||||
|
const canvas = this.script.aoiScript.canvases[this.value.canvasId];
|
||||||
|
canvas.toBlob(blob => {
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('file', blob);
|
||||||
|
data.append('i', this.$store.state.i.token);
|
||||||
|
|
||||||
|
fetch(apiUrl + '/drive/files/create', {
|
||||||
|
method: 'POST',
|
||||||
|
body: data
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(f => {
|
||||||
|
dialog.close();
|
||||||
|
ok(f);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async post() {
|
||||||
this.posting = true;
|
this.posting = true;
|
||||||
|
const file = this.value.attachCanvasImage ? await this.upload() : null;
|
||||||
this.$root.api('notes/create', {
|
this.$root.api('notes/create', {
|
||||||
text: this.text,
|
text: this.text,
|
||||||
|
fileIds: file ? [file.id] : undefined,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.posted = true;
|
this.posted = true;
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
@ -59,9 +89,11 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.ngbfujlo {
|
.ngbfujlo {
|
||||||
|
position: relative;
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
box-shadow: 0 2px 8px var(--shadow);
|
box-shadow: 0 2px 8px var(--shadow);
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
> .button {
|
> .button {
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
|
@ -28,7 +28,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
v() {
|
v() {
|
||||||
this.script.aiScript.updatePageVar(this.value.name, this.v);
|
this.script.aoiScript.updatePageVar(this.value.name, this.v);
|
||||||
this.script.eval();
|
this.script.eval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,30 +6,31 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../i18n';
|
import { AiScript, parse, values } from '@syuilo/aiscript';
|
||||||
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
|
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import i18n from '../../i18n';
|
||||||
import XBlock from './page.block.vue';
|
import XBlock from './page.block.vue';
|
||||||
import { ASEvaluator } from '../../scripts/aiscript/evaluator';
|
import { ASEvaluator } from '../../scripts/aoiscript/evaluator';
|
||||||
import { collectPageVars } from '../../scripts/collect-page-vars';
|
import { collectPageVars } from '../../scripts/collect-page-vars';
|
||||||
import { url } from '../../config';
|
import { url } from '../../config';
|
||||||
|
|
||||||
class Script {
|
class Script {
|
||||||
public aiScript: ASEvaluator;
|
public aoiScript: ASEvaluator;
|
||||||
private onError: any;
|
private onError: any;
|
||||||
public vars: Record<string, any>;
|
public vars: Record<string, any>;
|
||||||
public page: Record<string, any>;
|
public page: Record<string, any>;
|
||||||
|
|
||||||
constructor(page, aiScript, onError) {
|
constructor(page, aoiScript, onError) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.aiScript = aiScript;
|
this.aoiScript = aoiScript;
|
||||||
this.onError = onError;
|
this.onError = onError;
|
||||||
this.eval();
|
this.eval();
|
||||||
}
|
}
|
||||||
|
|
||||||
public eval() {
|
public eval() {
|
||||||
try {
|
try {
|
||||||
this.vars = this.aiScript.evaluateVars();
|
this.vars = this.aoiScript.evaluateVars();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
@ -38,10 +39,16 @@ class Script {
|
|||||||
public interpolate(str: string) {
|
public interpolate(str: string) {
|
||||||
if (str == null) return null;
|
if (str == null) return null;
|
||||||
return str.replace(/{(.+?)}/g, match => {
|
return str.replace(/{(.+?)}/g, match => {
|
||||||
const v = this.vars[match.slice(1, -1).trim()];
|
const v = this.vars ? this.vars[match.slice(1, -1).trim()] : null;
|
||||||
return v == null ? 'NULL' : v.toString();
|
return v == null ? 'NULL' : v.toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public callAiScript(fn: string) {
|
||||||
|
try {
|
||||||
|
if (this.aoiScript.aiscript) this.aoiScript.aiscript.execFn(this.aoiScript.aiscript.scope.get(fn), []);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
@ -67,14 +74,53 @@ export default Vue.extend({
|
|||||||
|
|
||||||
created() {
|
created() {
|
||||||
const pageVars = this.getPageVars();
|
const pageVars = this.getPageVars();
|
||||||
this.script = new Script(this.page, new ASEvaluator(this.page.variables, pageVars, {
|
|
||||||
|
this.script = new Script(this.page, new ASEvaluator(this, this.page.variables, pageVars, {
|
||||||
randomSeed: Math.random(),
|
randomSeed: Math.random(),
|
||||||
visitor: this.$store.state.i,
|
visitor: this.$store.state.i,
|
||||||
page: this.page,
|
page: this.page,
|
||||||
url: url
|
url: url,
|
||||||
|
enableAiScript: !this.$store.state.device.disablePagesScript
|
||||||
}), e => {
|
}), e => {
|
||||||
console.dir(e);
|
console.dir(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.script.aoiScript.aiscript) this.script.aoiScript.aiscript.scope.opts.onUpdated = (name, value) => {
|
||||||
|
this.script.eval();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.script.page.script && this.script.aoiScript.aiscript) {
|
||||||
|
let ast;
|
||||||
|
try {
|
||||||
|
ast = parse(this.script.page.script);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
/*this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: 'Syntax error :('
|
||||||
|
});*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.script.aoiScript.aiscript.exec(ast).then(() => {
|
||||||
|
this.script.eval();
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
/*this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e
|
||||||
|
});*/
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.script.eval();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.script.aoiScript.aiscript) this.script.aoiScript.aiscript.abort();
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<mk-emoji :emoji="reaction.startsWith(':') ? null : reaction" :name="reaction.startsWith(':') ? reaction.substr(1, reaction.length - 2) : null" :is-reaction="true" :normal="true" :no-style="noStyle"/>
|
<mk-emoji :emoji="reaction.startsWith(':') ? null : reaction" :name="reaction.startsWith(':') ? reaction.substr(1, reaction.length - 2) : null" :customEmojis="customEmojis" :is-reaction="true" :normal="true" :no-style="noStyle"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -12,6 +12,10 @@ export default Vue.extend({
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
customEmojis: {
|
||||||
|
required: false,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
noStyle: {
|
noStyle: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="hkzvhatu _button"
|
class="hkzvhatu _button"
|
||||||
:class="{ reacted: note.myReaction == reaction }"
|
:class="{ reacted: note.myReaction == reaction, canToggle }"
|
||||||
@click="toggleReaction(reaction)"
|
@click="toggleReaction(reaction)"
|
||||||
v-if="count > 0"
|
v-if="count > 0"
|
||||||
@mouseover="onMouseover"
|
@mouseover="onMouseover"
|
||||||
@ -9,7 +9,7 @@
|
|||||||
ref="reaction"
|
ref="reaction"
|
||||||
v-particle
|
v-particle
|
||||||
>
|
>
|
||||||
<x-reaction-icon :reaction="reaction" ref="icon"/>
|
<x-reaction-icon :reaction="reaction" :customEmojis="note.emojis" ref="icon"/>
|
||||||
<span>{{ count }}</span>
|
<span>{{ count }}</span>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
@ -40,11 +40,6 @@ export default Vue.extend({
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
canToggle: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -57,6 +52,9 @@ export default Vue.extend({
|
|||||||
isMe(): boolean {
|
isMe(): boolean {
|
||||||
return this.$store.getters.isSignedIn && this.$store.state.i.id === this.note.userId;
|
return this.$store.getters.isSignedIn && this.$store.state.i.id === this.note.userId;
|
||||||
},
|
},
|
||||||
|
canToggle(): boolean {
|
||||||
|
return !this.reaction.match(/@\w/);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (!this.isInitial) this.anime();
|
if (!this.isInitial) this.anime();
|
||||||
@ -144,15 +142,7 @@ export default Vue.extend({
|
|||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
&.reacted {
|
&.canToggle {
|
||||||
background: var(--accent);
|
|
||||||
|
|
||||||
> span {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.reacted) {
|
|
||||||
background: rgba(0, 0, 0, 0.05);
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -160,6 +150,22 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.canToggle) {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reacted {
|
||||||
|
background: var(--accent);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> span {
|
> span {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
<template #prefix><fa :icon="faLock"/></template>
|
<template #prefix><fa :icon="faLock"/></template>
|
||||||
</mk-input>
|
</mk-input>
|
||||||
<mk-button type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $t('loggingIn') : $t('login') }}</mk-button>
|
<mk-button type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $t('loggingIn') : $t('login') }}</mk-button>
|
||||||
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`"><fa :icon="faTwitter"/> {{ $t('signinWith', { x: 'Twitter' }) }}</a></p>
|
<a class="_panel _button" style="margin: 8px auto;" v-if="meta && meta.enableTwitterIntegration" :href="`${apiUrl}/signin/twitter`"><fa :icon="faTwitter" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Twitter' }) }}</a>
|
||||||
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`"><fa :icon="faGithub"/> {{ $t('signinWith', { x: 'GitHub' }) }}</a></p>
|
<a class="_panel _button" style="margin: 8px auto;" v-if="meta && meta.enableGithubIntegration" :href="`${apiUrl}/signin/github`"><fa :icon="faGithub" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'GitHub' }) }}</a>
|
||||||
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`"><fa :icon="faDiscord"/> {{ $t('signinWith', { x: 'Discord' }) }}</a></p>
|
<a class="_panel _button" style="margin: 8px auto;" v-if="meta && meta.enableDiscordIntegration" :href="`${apiUrl}/signin/discord`"><fa :icon="faDiscord" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Discord' }) }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="2fa-signin" v-if="totpLogin" :class="{ securityKeys: user && user.securityKeys }">
|
<div class="2fa-signin" v-if="totpLogin" :class="{ securityKeys: user && user.securityKeys }">
|
||||||
<div v-if="user && user.securityKeys" class="twofa-group tap-group">
|
<div v-if="user && user.securityKeys" class="twofa-group tap-group">
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
</mk-input>
|
</mk-input>
|
||||||
<mk-switch v-model="ToSAgreement" v-if="meta.tosUrl">
|
<mk-switch v-model="ToSAgreement" v-if="meta.tosUrl">
|
||||||
<i18n path="agreeTo">
|
<i18n path="agreeTo">
|
||||||
<a :href="meta.tosUrl" target="_blank">{{ $t('tos') }}</a>
|
<a :href="meta.tosUrl" class="_link" target="_blank">{{ $t('tos') }}</a>
|
||||||
</i18n>
|
</i18n>
|
||||||
</mk-switch>
|
</mk-switch>
|
||||||
<div v-if="meta.enableRecaptcha" class="g-recaptcha" :data-sitekey="meta.recaptchaSiteKey" style="margin: 16px 0;"></div>
|
<div v-if="meta.enableRecaptcha" class="g-recaptcha" :data-sitekey="meta.recaptchaSiteKey" style="margin: 16px 0;"></div>
|
||||||
|
@ -50,7 +50,8 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const prepend = note => {
|
const prepend = note => {
|
||||||
(this.$refs.tl as any).prepend(note);
|
const _note = JSON.parse(JSON.stringify(note)); // deepcopy
|
||||||
|
(this.$refs.tl as any).prepend(_note);
|
||||||
|
|
||||||
if (this.sound) {
|
if (this.sound) {
|
||||||
this.$root.sound(note.userId === this.$store.state.i.id ? 'noteMy' : 'note');
|
this.$root.sound(note.userId === this.$store.state.i.id ? 'noteMy' : 'note');
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fgmtyycl _panel" :style="{ top: top + 'px', left: left + 'px' }">
|
<div class="fgmtyycl _panel" :style="{ top: top + 'px', left: left + 'px' }">
|
||||||
<x-url-preview :url="url"/>
|
<mk-url-preview :url="url"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import XUrlPreview from './url-preview.vue';
|
import MkUrlPreview from './url-preview.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
XUrlPreview
|
MkUrlPreview
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -36,7 +36,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const rect = this.source.getBoundingClientRect();
|
const rect = this.source.getBoundingClientRect();
|
||||||
const x = ((rect.left + (this.source.offsetWidth / 2)) - (300 / 2)) + window.pageXOffset;
|
const x = Math.max((rect.left + (this.source.offsetWidth / 2)) - (300 / 2), 6) + window.pageXOffset;
|
||||||
const y = rect.top + this.source.offsetHeight + window.pageYOffset;
|
const y = rect.top + this.source.offsetHeight + window.pageYOffset;
|
||||||
|
|
||||||
this.top = y;
|
this.top = y;
|
||||||
@ -50,6 +50,7 @@ export default Vue.extend({
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 11000;
|
z-index: 11000;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
|
max-width: calc(90vw - 12px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ import Vue from 'vue';
|
|||||||
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { toUnicode as decodePunycode } from 'punycode';
|
import { toUnicode as decodePunycode } from 'punycode';
|
||||||
import { url as local } from '../config';
|
import { url as local } from '../config';
|
||||||
import XUrlPreview from './url-preview-popup.vue';
|
import MkUrlPreview from './url-preview-popup.vue';
|
||||||
|
import { isDeviceTouch } from '../scripts/is-device-touch';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: {
|
props: {
|
||||||
@ -70,7 +71,7 @@ export default Vue.extend({
|
|||||||
if (!document.body.contains(this.$el)) return;
|
if (!document.body.contains(this.$el)) return;
|
||||||
if (this.preview) return;
|
if (this.preview) return;
|
||||||
|
|
||||||
this.preview = new XUrlPreview({
|
this.preview = new MkUrlPreview({
|
||||||
parent: this,
|
parent: this,
|
||||||
propsData: {
|
propsData: {
|
||||||
url: this.url,
|
url: this.url,
|
||||||
@ -92,11 +93,13 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMouseover() {
|
onMouseover() {
|
||||||
|
if (isDeviceTouch()) return;
|
||||||
clearTimeout(this.showTimer);
|
clearTimeout(this.showTimer);
|
||||||
clearTimeout(this.hideTimer);
|
clearTimeout(this.hideTimer);
|
||||||
this.showTimer = setTimeout(this.showPreview, 500);
|
this.showTimer = setTimeout(this.showPreview, 500);
|
||||||
},
|
},
|
||||||
onMouseleave() {
|
onMouseleave() {
|
||||||
|
if (isDeviceTouch()) return;
|
||||||
clearTimeout(this.showTimer);
|
clearTimeout(this.showTimer);
|
||||||
clearTimeout(this.hideTimer);
|
clearTimeout(this.hideTimer);
|
||||||
this.hideTimer = setTimeout(this.closePreview, 500);
|
this.hideTimer = setTimeout(this.closePreview, 500);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<div class="efvhhmdq">
|
<div class="efvhhmdq">
|
||||||
<div class="no-users" v-if="empty">
|
<div class="no-users" v-if="empty">
|
||||||
<p>{{ $t('no-users') }}</p>
|
<p>{{ $t('noUsers') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="user" v-for="user in users" :key="user.id">
|
<div class="user" v-for="user in users" :key="user.id">
|
||||||
<mk-avatar class="avatar" :user="user"/>
|
<mk-avatar class="avatar" :user="user"/>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers } from '@fortawesome/free-solid-svg-icons';
|
import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import XMenu from './menu.vue';
|
import XMenu from './menu.vue';
|
||||||
@ -60,8 +60,12 @@ export default Vue.extend({
|
|||||||
action: this.toggleBlock
|
action: this.toggleBlock
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
if (this.$store.state.i.isAdmin) {
|
if (this.$store.getters.isSignedIn && (this.$store.state.i.isAdmin || this.$store.state.i.isModerator)) {
|
||||||
menu = menu.concat([null, {
|
menu = menu.concat([null, {
|
||||||
|
icon: faMicrophoneSlash,
|
||||||
|
text: this.user.isSilenced ? this.$t('unsilence') : this.$t('silence'),
|
||||||
|
action: this.toggleSilence
|
||||||
|
}, {
|
||||||
icon: faSnowflake,
|
icon: faSnowflake,
|
||||||
text: this.user.isSuspended ? this.$t('unsuspend') : this.$t('suspend'),
|
text: this.user.isSuspended ? this.$t('unsuspend') : this.$t('suspend'),
|
||||||
action: this.toggleSuspend
|
action: this.toggleSuspend
|
||||||
@ -194,6 +198,25 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async toggleSilence() {
|
||||||
|
if (!await this.getConfirmed(this.$t(this.user.isSilenced ? 'unsilenceConfirm' : 'silenceConfirm'))) return;
|
||||||
|
|
||||||
|
this.$root.api(this.user.isSilenced ? 'admin/unsilence-user' : 'admin/silence-user', {
|
||||||
|
userId: this.user.id
|
||||||
|
}).then(() => {
|
||||||
|
this.user.isSilenced = !this.user.isSilenced;
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
}, e => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
async toggleSuspend() {
|
async toggleSuspend() {
|
||||||
if (!await this.getConfirmed(this.$t(this.user.isSuspended ? 'unsuspendConfirm' : 'suspendConfirm'))) return;
|
if (!await this.getConfirmed(this.$t(this.user.isSuspended ? 'unsuspendConfirm' : 'suspendConfirm'))) return;
|
||||||
|
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
<template>
|
|
||||||
<x-window @closed="() => { $emit('closed'); destroyDom(); }" :avatar="user">
|
|
||||||
<template #header><mk-user-name :user="user"/></template>
|
|
||||||
<div class="vrcsvlkm">
|
|
||||||
<mk-button @click="resetPassword()" primary>{{ $t('resetPassword') }}</mk-button>
|
|
||||||
<mk-switch v-if="$store.state.i.isAdmin && (this.moderator || !user.isAdmin)" @change="toggleModerator()" v-model="moderator">{{ $t('moderator') }}</mk-switch>
|
|
||||||
<mk-switch @change="toggleSilence()" v-model="silenced">{{ $t('silence') }}</mk-switch>
|
|
||||||
<mk-switch @change="toggleSuspend()" v-model="suspended">{{ $t('suspend') }}</mk-switch>
|
|
||||||
</div>
|
|
||||||
</x-window>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import i18n from '../i18n';
|
|
||||||
import MkButton from './ui/button.vue';
|
|
||||||
import MkSwitch from './ui/switch.vue';
|
|
||||||
import XWindow from './window.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
i18n,
|
|
||||||
|
|
||||||
components: {
|
|
||||||
MkButton,
|
|
||||||
MkSwitch,
|
|
||||||
XWindow,
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
user: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
moderator: this.user.isModerator,
|
|
||||||
silenced: this.user.isSilenced,
|
|
||||||
suspended: this.user.isSuspended,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
async resetPassword() {
|
|
||||||
const dialog = this.$root.dialog({
|
|
||||||
type: 'waiting',
|
|
||||||
iconOnly: true
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$root.api('admin/reset-password', {
|
|
||||||
userId: this.user.id,
|
|
||||||
}).then(({ password }) => {
|
|
||||||
this.$root.dialog({
|
|
||||||
type: 'success',
|
|
||||||
text: this.$t('newPasswordIs', { password })
|
|
||||||
});
|
|
||||||
}).catch(e => {
|
|
||||||
this.$root.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: e
|
|
||||||
});
|
|
||||||
}).finally(() => {
|
|
||||||
dialog.close();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async toggleSilence() {
|
|
||||||
const confirm = await this.$root.dialog({
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
text: this.silenced ? this.$t('silenceConfirm') : this.$t('unsilenceConfirm'),
|
|
||||||
});
|
|
||||||
if (confirm.canceled) {
|
|
||||||
this.silenced = !this.silenced;
|
|
||||||
} else {
|
|
||||||
this.$root.api(this.silenced ? 'admin/silence-user' : 'admin/unsilence-user', { userId: this.user.id });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async toggleSuspend() {
|
|
||||||
const confirm = await this.$root.dialog({
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
text: this.suspended ? this.$t('suspendConfirm') : this.$t('unsuspendConfirm'),
|
|
||||||
});
|
|
||||||
if (confirm.canceled) {
|
|
||||||
this.suspended = !this.suspended;
|
|
||||||
} else {
|
|
||||||
this.$root.api(this.suspended ? 'admin/suspend-user' : 'admin/unsuspend-user', { userId: this.user.id });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async toggleModerator() {
|
|
||||||
this.$root.api(this.moderator ? 'admin/moderators/add' : 'admin/moderators/remove', { userId: this.user.id });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.vrcsvlkm {
|
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -18,7 +18,9 @@ import PostFormDialog from './components/post-form-dialog.vue';
|
|||||||
import Dialog from './components/dialog.vue';
|
import Dialog from './components/dialog.vue';
|
||||||
import Menu from './components/menu.vue';
|
import Menu from './components/menu.vue';
|
||||||
import { router } from './router';
|
import { router } from './router';
|
||||||
import { applyTheme, lightTheme, builtinThemes } from './theme';
|
import { applyTheme, lightTheme } from './theme';
|
||||||
|
import { isDeviceDarkmode } from './scripts/is-device-darkmode';
|
||||||
|
import createStore from './store';
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
Vue.use(VueHotkey);
|
Vue.use(VueHotkey);
|
||||||
@ -133,18 +135,39 @@ document.body.setAttribute('ontouchstart', '');
|
|||||||
// アプリ基底要素マウント
|
// アプリ基底要素マウント
|
||||||
document.body.innerHTML = '<div id="app"></div>';
|
document.body.innerHTML = '<div id="app"></div>';
|
||||||
|
|
||||||
const os = new MiOS();
|
const store = createStore();
|
||||||
|
|
||||||
|
const os = new MiOS(store);
|
||||||
|
|
||||||
os.init(async () => {
|
os.init(async () => {
|
||||||
window.addEventListener('storage', e => {
|
window.addEventListener('storage', e => {
|
||||||
if (e.key === 'vuex') {
|
if (e.key === 'vuex') {
|
||||||
os.store.replaceState(JSON.parse(localStorage['vuex']));
|
store.replaceState(JSON.parse(localStorage['vuex']));
|
||||||
} else if (e.key === 'i') {
|
} else if (e.key === 'i') {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
if ('Notification' in window && os.store.getters.isSignedIn) {
|
store.watch(state => state.device.darkMode, darkMode => {
|
||||||
|
import('./theme').then(({ builtinThemes }) => {
|
||||||
|
const themes = builtinThemes.concat(store.state.device.themes);
|
||||||
|
applyTheme(themes.find(x => x.id === (darkMode ? store.state.device.darkTheme : store.state.device.lightTheme)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//#region Sync dark mode
|
||||||
|
if (store.state.device.syncDeviceDarkMode) {
|
||||||
|
store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
|
||||||
|
}
|
||||||
|
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
|
||||||
|
if (store.state.device.syncDeviceDarkMode) {
|
||||||
|
store.commit('device/set', { key: 'darkMode', value: mql.matches });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
if ('Notification' in window && store.getters.isSignedIn) {
|
||||||
// 許可を得ていなかったらリクエスト
|
// 許可を得ていなかったらリクエスト
|
||||||
if (Notification.permission === 'default') {
|
if (Notification.permission === 'default') {
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
@ -152,7 +175,7 @@ os.init(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
store: os.store,
|
store: store,
|
||||||
metaInfo: {
|
metaInfo: {
|
||||||
title: null,
|
title: null,
|
||||||
titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey')
|
titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey')
|
||||||
@ -163,14 +186,8 @@ os.init(async () => {
|
|||||||
isMobile: isMobile
|
isMobile: isMobile
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
'$store.state.device.darkMode'() {
|
|
||||||
const themes = builtinThemes.concat(this.$store.state.device.themes);
|
|
||||||
applyTheme(themes.find(x => x.id === (this.$store.state.device.darkMode ? this.$store.state.device.darkTheme : this.$store.state.device.lightTheme)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
api: os.api,
|
api: (endpoint: string, data: { [x: string]: any } = {}, token?) => store.dispatch('api', { endpoint, data, token }),
|
||||||
signout: os.signout,
|
signout: os.signout,
|
||||||
new(vm, props) {
|
new(vm, props) {
|
||||||
const x = new vm({
|
const x = new vm({
|
||||||
@ -221,58 +238,63 @@ os.init(async () => {
|
|||||||
// マウント
|
// マウント
|
||||||
app.$mount('#app');
|
app.$mount('#app');
|
||||||
|
|
||||||
if (app.$store.getters.isSignedIn) {
|
os.stream.on('emojiAdded', data => {
|
||||||
|
// TODO
|
||||||
|
//store.commit('instance/set', );
|
||||||
|
});
|
||||||
|
|
||||||
|
if (store.getters.isSignedIn) {
|
||||||
const main = os.stream.useSharedConnection('main');
|
const main = os.stream.useSharedConnection('main');
|
||||||
|
|
||||||
// 自分の情報が更新されたとき
|
// 自分の情報が更新されたとき
|
||||||
main.on('meUpdated', i => {
|
main.on('meUpdated', i => {
|
||||||
app.$store.dispatch('mergeMe', i);
|
store.dispatch('mergeMe', i);
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllNotifications', () => {
|
main.on('readAllNotifications', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadNotification: false
|
hasUnreadNotification: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('unreadNotification', () => {
|
main.on('unreadNotification', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadNotification: true
|
hasUnreadNotification: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('unreadMention', () => {
|
main.on('unreadMention', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadMentions: true
|
hasUnreadMentions: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllUnreadMentions', () => {
|
main.on('readAllUnreadMentions', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadMentions: false
|
hasUnreadMentions: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('unreadSpecifiedNote', () => {
|
main.on('unreadSpecifiedNote', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadSpecifiedNotes: true
|
hasUnreadSpecifiedNotes: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllUnreadSpecifiedNotes', () => {
|
main.on('readAllUnreadSpecifiedNotes', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadSpecifiedNotes: false
|
hasUnreadSpecifiedNotes: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllMessagingMessages', () => {
|
main.on('readAllMessagingMessages', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadMessagingMessage: false
|
hasUnreadMessagingMessage: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('unreadMessagingMessage', () => {
|
main.on('unreadMessagingMessage', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadMessagingMessage: true
|
hasUnreadMessagingMessage: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -280,13 +302,13 @@ os.init(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllAntennas', () => {
|
main.on('readAllAntennas', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadAntenna: false
|
hasUnreadAntenna: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('unreadAntenna', () => {
|
main.on('unreadAntenna', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadAntenna: true
|
hasUnreadAntenna: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -294,13 +316,13 @@ os.init(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllAnnouncements', () => {
|
main.on('readAllAnnouncements', () => {
|
||||||
app.$store.dispatch('mergeMe', {
|
store.dispatch('mergeMe', {
|
||||||
hasUnreadAnnouncement: false
|
hasUnreadAnnouncement: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('clientSettingUpdated', x => {
|
main.on('clientSettingUpdated', x => {
|
||||||
app.$store.commit('settings/set', {
|
store.commit('settings/set', {
|
||||||
key: x.key,
|
key: x.key,
|
||||||
value: x.value
|
value: x.value
|
||||||
});
|
});
|
||||||
|
@ -2,16 +2,11 @@ import autobind from 'autobind-decorator';
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
|
||||||
import initStore from './store';
|
|
||||||
import { apiUrl, version } from './config';
|
import { apiUrl, version } from './config';
|
||||||
import Progress from './scripts/loading';
|
import Progress from './scripts/loading';
|
||||||
|
|
||||||
import Stream from './scripts/stream';
|
import Stream from './scripts/stream';
|
||||||
|
import store from './store';
|
||||||
//#region api requests
|
|
||||||
let spinner = null;
|
|
||||||
let pending = 0;
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Misskey Operating System
|
* Misskey Operating System
|
||||||
@ -19,7 +14,7 @@ let pending = 0;
|
|||||||
export default class MiOS extends EventEmitter {
|
export default class MiOS extends EventEmitter {
|
||||||
public app: Vue;
|
public app: Vue;
|
||||||
|
|
||||||
public store: ReturnType<typeof initStore>;
|
public store: ReturnType<typeof store>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A connection manager of home stream
|
* A connection manager of home stream
|
||||||
@ -31,6 +26,11 @@ export default class MiOS extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
private swRegistration: ServiceWorkerRegistration = null;
|
private swRegistration: ServiceWorkerRegistration = null;
|
||||||
|
|
||||||
|
constructor(vuex: MiOS['store']) {
|
||||||
|
super();
|
||||||
|
this.store = vuex;
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
public signout() {
|
public signout() {
|
||||||
this.store.dispatch('logout');
|
this.store.dispatch('logout');
|
||||||
@ -52,8 +52,6 @@ export default class MiOS extends EventEmitter {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.store = initStore(this);
|
|
||||||
|
|
||||||
// ユーザーをフェッチしてコールバックする
|
// ユーザーをフェッチしてコールバックする
|
||||||
const fetchme = (token, cb) => {
|
const fetchme = (token, cb) => {
|
||||||
let me = null;
|
let me = null;
|
||||||
@ -187,16 +185,19 @@ export default class MiOS extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register
|
// Register
|
||||||
this.api('sw/register', {
|
this.store.dispatch('api', {
|
||||||
|
endpoint: 'sw/register',
|
||||||
|
data: {
|
||||||
endpoint: subscription.endpoint,
|
endpoint: subscription.endpoint,
|
||||||
auth: encode(subscription.getKey('auth')),
|
auth: encode(subscription.getKey('auth')),
|
||||||
publickey: encode(subscription.getKey('p256dh'))
|
publickey: encode(subscription.getKey('p256dh'))
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
// When subscribe failed
|
// When subscribe failed
|
||||||
.catch(async (err: Error) => {
|
.catch(async (err: Error) => {
|
||||||
// 通知が許可されていなかったとき
|
// 通知が許可されていなかったとき
|
||||||
if (err.name == 'NotAllowedError') {
|
if (err.name === 'NotAllowedError') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,52 +215,6 @@ export default class MiOS extends EventEmitter {
|
|||||||
// Register service worker
|
// Register service worker
|
||||||
navigator.serviceWorker.register(sw);
|
navigator.serviceWorker.register(sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Misskey APIにリクエストします
|
|
||||||
* @param endpoint エンドポイント名
|
|
||||||
* @param data パラメータ
|
|
||||||
*/
|
|
||||||
@autobind
|
|
||||||
public api(endpoint: string, data: { [x: string]: any } = {}, token?): Promise<{ [x: string]: any }> {
|
|
||||||
if (++pending === 1) {
|
|
||||||
spinner = document.createElement('div');
|
|
||||||
spinner.setAttribute('id', 'wait');
|
|
||||||
document.body.appendChild(spinner);
|
|
||||||
}
|
|
||||||
|
|
||||||
const onFinally = () => {
|
|
||||||
if (--pending === 0) spinner.parentNode.removeChild(spinner);
|
|
||||||
};
|
|
||||||
|
|
||||||
const promise = new Promise((resolve, reject) => {
|
|
||||||
// Append a credential
|
|
||||||
if (this.store.getters.isSignedIn) (data as any).i = this.store.state.i.token;
|
|
||||||
if (token) (data as any).i = token;
|
|
||||||
|
|
||||||
// Send request
|
|
||||||
fetch(endpoint.indexOf('://') > -1 ? endpoint : `${apiUrl}/${endpoint}`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
credentials: 'omit',
|
|
||||||
cache: 'no-cache'
|
|
||||||
}).then(async (res) => {
|
|
||||||
const body = res.status === 204 ? null : await res.json();
|
|
||||||
|
|
||||||
if (res.status === 200) {
|
|
||||||
resolve(body);
|
|
||||||
} else if (res.status === 204) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject(body.error);
|
|
||||||
}
|
|
||||||
}).catch(reject);
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.then(onFinally, onFinally);
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="znqjceqz">
|
<div class="znqjceqz">
|
||||||
<portal to="title">🍀 {{ $t('aboutMisskey') }}</portal>
|
<portal to="title">{{ $t('aboutMisskey') }}</portal>
|
||||||
|
|
||||||
<section class="_card">
|
<section class="_card">
|
||||||
<div class="_title">🍀 {{ $t('aboutMisskey') }}</div>
|
<div class="_title">{{ $t('aboutMisskey') }}</div>
|
||||||
|
<div class="_content" style="text-align: center;">
|
||||||
|
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;"/>
|
||||||
|
<div style="margin-top: 0.75em;">Misskey</div>
|
||||||
|
<div style="opacity: 0.5;">v{{ version }}</div>
|
||||||
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<div style="margin-bottom: 1em;">{{ $t('aboutMisskeyText') }}</div>
|
<div style="margin-bottom: 1em;">{{ $t('aboutMisskeyText') }}</div>
|
||||||
<div>🛠️ {{ $t('misskeyMembers') }}</div>
|
<div>🛠️ {{ $t('misskeyMembers') }}</div>
|
||||||
@ -44,6 +49,9 @@
|
|||||||
<li>wara</li>
|
<li>wara</li>
|
||||||
<li>Takashi Shibuya</li>
|
<li>Takashi Shibuya</li>
|
||||||
<li>Noizeman</li>
|
<li>Noizeman</li>
|
||||||
|
<li>mydarkstar</li>
|
||||||
|
<li>nenohi</li>
|
||||||
|
<li>Eduardo Quiros</li>
|
||||||
</ul>
|
</ul>
|
||||||
<span>{{ $t('morePatrons') }}</span>
|
<span>{{ $t('morePatrons') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
107
src/client/pages/apps.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<portal to="icon"><fa :icon="faPlug"/></portal>
|
||||||
|
<portal to="title">{{ $t('installedApps') }}</portal>
|
||||||
|
|
||||||
|
<mk-pagination :pagination="pagination" class="bfomjevm" ref="list">
|
||||||
|
<template #empty>
|
||||||
|
<div class="_fullinfo">
|
||||||
|
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||||
|
<div>{{ $t('nothing') }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #default="{items}">
|
||||||
|
<div class="token _panel" v-for="token in items" :key="token.id">
|
||||||
|
<img class="icon" :src="token.iconUrl" alt=""/>
|
||||||
|
<div class="body">
|
||||||
|
<div class="name">{{ token.name }}</div>
|
||||||
|
<div class="description">{{ token.description }}</div>
|
||||||
|
<div class="_keyValue">
|
||||||
|
<div>{{ $t('installedDate') }}:</div>
|
||||||
|
<div><mk-time :time="token.createdAt"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="_keyValue">
|
||||||
|
<div>{{ $t('lastUsedDate') }}:</div>
|
||||||
|
<div><mk-time :time="token.lastUsedAt"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="_button" @click="revoke(token)"><fa :icon="faTrashAlt"/></button>
|
||||||
|
</div>
|
||||||
|
<details>
|
||||||
|
<summary>{{ $t('details') }}</summary>
|
||||||
|
<ul>
|
||||||
|
<li v-for="p in token.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</mk-pagination>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { faTrashAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import MkPagination from '../components/ui/pagination.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
metaInfo() {
|
||||||
|
return {
|
||||||
|
title: this.$t('installedApps') as string
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
MkPagination
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pagination: {
|
||||||
|
endpoint: 'i/apps',
|
||||||
|
limit: 100,
|
||||||
|
params: {
|
||||||
|
sort: '+lastUsedAt'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
faTrashAlt, faPlug
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
revoke(token) {
|
||||||
|
this.$root.api('i/revoke-token', { tokenId: token.id }).then(() => {
|
||||||
|
this.$refs.list.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bfomjevm {
|
||||||
|
> .token {
|
||||||
|
display: flex;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0 12px 0 0;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .body {
|
||||||
|
width: calc(100% - 62px);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -12,20 +12,18 @@
|
|||||||
@accepted="accepted"
|
@accepted="accepted"
|
||||||
/>
|
/>
|
||||||
<div class="denied _panel" v-if="state == 'denied'">
|
<div class="denied _panel" v-if="state == 'denied'">
|
||||||
<h1>{{ $t('denied') }}</h1>
|
<h1>{{ $t('_auth.denied') }}</h1>
|
||||||
<p>{{ $t('denied-paragraph') }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="accepted _panel" v-if="state == 'accepted'">
|
<div class="accepted _panel" v-if="state == 'accepted'">
|
||||||
<h1>{{ session.app.isAuthorized ? this.$t('already-authorized') : this.$t('allowed') }}</h1>
|
<h1>{{ session.app.isAuthorized ? this.$t('already-authorized') : this.$t('allowed') }}</h1>
|
||||||
<p v-if="session.app.callbackUrl">{{ $t('callback-url') }}<mk-ellipsis/></p>
|
<p v-if="session.app.callbackUrl">{{ $t('_auth.callback') }}<mk-ellipsis/></p>
|
||||||
<p v-if="!session.app.callbackUrl">{{ $t('please-go-back') }}</p>
|
<p v-if="!session.app.callbackUrl">{{ $t('_auth.pleaseGoBack') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="error _panel" v-if="state == 'fetch-session-error'">
|
<div class="error _panel" v-if="state == 'fetch-session-error'">
|
||||||
<p>{{ $t('error') }}</p>
|
<p>{{ $t('error') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="signin" v-else>
|
<div class="signin" v-else>
|
||||||
<h1>{{ $t('sign-in') }}</h1>
|
|
||||||
<mk-signin @login="onLogin"/>
|
<mk-signin @login="onLogin"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faFileAlt } from '@fortawesome/free-solid-svg-icons'
|
import { faFileAlt } from '@fortawesome/free-solid-svg-icons'
|
||||||
import MarkdownIt from 'markdown-it';
|
import MarkdownIt from 'markdown-it';
|
||||||
|
import MarkdownItAnchor from 'markdown-it-anchor';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import { url, lang } from '../config';
|
import { url, lang } from '../config';
|
||||||
import MkLink from '../components/link.vue';
|
import MkLink from '../components/link.vue';
|
||||||
@ -26,6 +27,10 @@ const markdown = MarkdownIt({
|
|||||||
html: true
|
html: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
markdown.use(MarkdownItAnchor, {
|
||||||
|
slugify: (s) => encodeURIComponent(String(s).trim().replace(/\s+/g, '-'))
|
||||||
|
});
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
|
||||||
@ -72,6 +77,9 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
parse(md: string) {
|
parse(md: string) {
|
||||||
|
// 変数置換
|
||||||
|
md = md.replace(/\{_URL_\}/g, url);
|
||||||
|
|
||||||
// markdown の全容をパースする
|
// markdown の全容をパースする
|
||||||
const parsed = markdown.parse(md, {});
|
const parsed = markdown.parse(md, {});
|
||||||
if (parsed.length === 0) return;
|
if (parsed.length === 0) return;
|
||||||
@ -115,6 +123,23 @@ export default Vue.extend({
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::v-deep a {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep blockquote {
|
||||||
|
display: block;
|
||||||
|
margin: 8px;
|
||||||
|
padding: 6px 0 6px 12px;
|
||||||
|
color: var(--fg);
|
||||||
|
border-left: solid 3px var(--fg);
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep h2 {
|
::v-deep h2 {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
padding: 0 0 0.5em 0;
|
padding: 0 0 0.5em 0;
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
<mk-pagination :pagination="pagination" class="mk-follow-requests" ref="list">
|
<mk-pagination :pagination="pagination" class="mk-follow-requests" ref="list">
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div class="tkdrhpxr">
|
<div class="_fullinfo">
|
||||||
<img src="https://xn--931a.moe/assets/info.png" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||||
<div>{{ $t('noFollowRequests') }}</div>
|
<div>{{ $t('noFollowRequests') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -75,18 +75,6 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.mk-follow-requests {
|
.mk-follow-requests {
|
||||||
.tkdrhpxr {
|
|
||||||
padding: 32px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 128px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .user {
|
> .user {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
@ -99,10 +99,19 @@
|
|||||||
<span class="label">{{ $t('operations') }}</span>
|
<span class="label">{{ $t('operations') }}</span>
|
||||||
<mk-switch v-model="isSuspended" class="switch">{{ $t('stopActivityDelivery') }}</mk-switch>
|
<mk-switch v-model="isSuspended" class="switch">{{ $t('stopActivityDelivery') }}</mk-switch>
|
||||||
<mk-switch :value="isBlocked" class="switch" @change="changeBlock">{{ $t('blockThisInstance') }}</mk-switch>
|
<mk-switch :value="isBlocked" class="switch" @change="changeBlock">{{ $t('blockThisInstance') }}</mk-switch>
|
||||||
|
<details>
|
||||||
|
<summary>{{ $t('deleteAllFiles') }}</summary>
|
||||||
|
<mk-button @click="deleteAllFiles()" style="margin: 0.5em 0 0.5em 0;"><fa :icon="faTrashAlt"/> {{ $t('deleteAllFiles') }}</mk-button>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>{{ $t('removeAllFollowing') }}</summary>
|
||||||
|
<mk-button @click="removeAllFollowing()" style="margin: 0.5em 0 0.5em 0;"><fa :icon="faMinusCircle"/> {{ $t('removeAllFollowing') }}</mk-button>
|
||||||
|
<mk-info warn>{{ $t('removeAllFollowingDescription', { host: instance.host }) }}</mk-info>
|
||||||
|
</details>
|
||||||
</div>
|
</div>
|
||||||
<details class="metadata">
|
<details class="metadata">
|
||||||
<summary class="label">{{ $t('metadata') }}</summary>
|
<summary class="label">{{ $t('metadata') }}</summary>
|
||||||
<pre><code>{{ JSON.stringify(instance.metadata, null, 2) }}</code></pre>
|
<pre><code>{{ JSON.stringify(instance, null, 2) }}</code></pre>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
</x-window>
|
</x-window>
|
||||||
@ -112,11 +121,13 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Chart from 'chart.js';
|
import Chart from 'chart.js';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import { faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown } from '@fortawesome/free-solid-svg-icons';
|
import { faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown, faMinusCircle, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import XWindow from '../../components/window.vue';
|
import XWindow from '../../components/window.vue';
|
||||||
import MkUsersDialog from '../../components/users-dialog.vue';
|
import MkUsersDialog from '../../components/users-dialog.vue';
|
||||||
import MkSelect from '../../components/ui/select.vue';
|
import MkSelect from '../../components/ui/select.vue';
|
||||||
|
import MkButton from '../../components/ui/button.vue';
|
||||||
import MkSwitch from '../../components/ui/switch.vue';
|
import MkSwitch from '../../components/ui/switch.vue';
|
||||||
|
import MkInfo from '../../components/ui/info.vue';
|
||||||
|
|
||||||
const chartLimit = 90;
|
const chartLimit = 90;
|
||||||
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
|
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
|
||||||
@ -135,7 +146,9 @@ export default Vue.extend({
|
|||||||
components: {
|
components: {
|
||||||
XWindow,
|
XWindow,
|
||||||
MkSelect,
|
MkSelect,
|
||||||
|
MkButton,
|
||||||
MkSwitch,
|
MkSwitch,
|
||||||
|
MkInfo,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -153,7 +166,7 @@ export default Vue.extend({
|
|||||||
chartInstance: null,
|
chartInstance: null,
|
||||||
chartSrc: 'requests',
|
chartSrc: 'requests',
|
||||||
chartSpan: 'hour',
|
chartSpan: 'hour',
|
||||||
faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown
|
faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown, faMinusCircle, faTrashAlt
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -239,6 +252,28 @@ export default Vue.extend({
|
|||||||
this.chartSrc = src;
|
this.chartSrc = src;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeAllFollowing() {
|
||||||
|
this.$root.api('admin/federation/remove-all-following', {
|
||||||
|
host: this.instance.host
|
||||||
|
}).then(() => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteAllFiles() {
|
||||||
|
this.$root.api('admin/federation/delete-all-files', {
|
||||||
|
host: this.instance.host
|
||||||
|
}).then(() => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
renderChart() {
|
renderChart() {
|
||||||
if (this.chartInstance) {
|
if (this.chartInstance) {
|
||||||
this.chartInstance.destroy();
|
this.chartInstance.destroy();
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-federation">
|
<div class="mk-federation">
|
||||||
|
<portal to="icon"><fa :icon="faGlobe"/></portal>
|
||||||
|
<portal to="title">{{ $t('federation') }}</portal>
|
||||||
|
|
||||||
<section class="_card instances">
|
<section class="_card instances">
|
||||||
<div class="_title"><fa :icon="faGlobe"/> {{ $t('instances') }}</div>
|
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
|
<mk-input v-model="host" :debounce="true"><span>{{ $t('host') }}</span></mk-input>
|
||||||
<div class="inputs" style="display: flex;">
|
<div class="inputs" style="display: flex;">
|
||||||
<mk-input v-model="host" :debounce="true" style="margin: 0; flex: 1;"><span>{{ $t('host') }}</span></mk-input>
|
<mk-select v-model="state" style="margin: 0; flex: 1;">
|
||||||
<mk-select v-model="state" style="margin: 0;">
|
<template #label>{{ $t('state') }}</template>
|
||||||
<option value="all">{{ $t('all') }}</option>
|
<option value="all">{{ $t('all') }}</option>
|
||||||
<option value="federating">{{ $t('federating') }}</option>
|
<option value="federating">{{ $t('federating') }}</option>
|
||||||
<option value="subscribing">{{ $t('subscribing') }}</option>
|
<option value="subscribing">{{ $t('subscribing') }}</option>
|
||||||
@ -14,11 +17,32 @@
|
|||||||
<option value="blocked">{{ $t('blocked') }}</option>
|
<option value="blocked">{{ $t('blocked') }}</option>
|
||||||
<option value="notResponding">{{ $t('notResponding') }}</option>
|
<option value="notResponding">{{ $t('notResponding') }}</option>
|
||||||
</mk-select>
|
</mk-select>
|
||||||
|
<mk-select v-model="sort" style="margin: 0; flex: 1;">
|
||||||
|
<template #label>{{ $t('sort') }}</template>
|
||||||
|
<option value="+pubSub">{{ $t('pubSub') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-pubSub">{{ $t('pubSub') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+notes">{{ $t('notes') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-notes">{{ $t('notes') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+users">{{ $t('users') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-users">{{ $t('users') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+following">{{ $t('following') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-following">{{ $t('following') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+followers">{{ $t('followers') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-followers">{{ $t('followers') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+caughtAt">{{ $t('caughtAt') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-caughtAt">{{ $t('caughtAt') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+lastCommunicatedAt">{{ $t('lastCommunicatedAt') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-lastCommunicatedAt">{{ $t('lastCommunicatedAt') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+driveUsage">{{ $t('driveUsage') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-driveUsage">{{ $t('driveUsage') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+driveFiles">{{ $t('driveFiles') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-driveFiles">{{ $t('driveFiles') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
</mk-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<mk-pagination :pagination="pagination" #default="{items}" class="instances" ref="instances" :key="host + state">
|
<mk-pagination :pagination="pagination" #default="{items}" class="instances" ref="instances" :key="host + state">
|
||||||
<div class="instance" v-for="(instance, i) in items" :key="instance.id" @click="info(instance)">
|
<div class="instance" v-for="instance in items" :key="instance.id" @click="info(instance)">
|
||||||
<div class="host"><fa :icon="faCircle" class="indicator" :class="getStatus(instance)"/><b>{{ instance.host }}</b></div>
|
<div class="host"><fa :icon="faCircle" class="indicator" :class="getStatus(instance)"/><b>{{ instance.host }}</b></div>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<span class="sub" v-if="instance.followersCount > 0"><fa :icon="faCaretDown" class="icon"/>Sub</span>
|
<span class="sub" v-if="instance.followersCount > 0"><fa :icon="faCaretDown" class="icon"/>Sub</span>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<portal to="icon"><fa :icon="faExchangeAlt"/></portal>
|
||||||
|
<portal to="title">{{ $t('jobQueue') }}</portal>
|
||||||
|
|
||||||
<x-queue :connection="connection" domain="inbox">
|
<x-queue :connection="connection" domain="inbox">
|
||||||
<template #title><fa :icon="faExchangeAlt"/> In</template>
|
<template #title><fa :icon="faExchangeAlt"/> In</template>
|
||||||
</x-queue>
|
</x-queue>
|
||||||
|
@ -116,6 +116,7 @@
|
|||||||
<mk-input v-model="objectStorageSecretKey" :disabled="!useObjectStorage"><template #icon><fa :icon="faKey"/></template>Secret key</mk-input>
|
<mk-input v-model="objectStorageSecretKey" :disabled="!useObjectStorage"><template #icon><fa :icon="faKey"/></template>Secret key</mk-input>
|
||||||
</div>
|
</div>
|
||||||
<mk-switch v-model="objectStorageUseSSL" :disabled="!useObjectStorage">{{ $t('objectStorageUseSSL') }}<template #desc>{{ $t('objectStorageUseSSLDesc') }}</template></mk-switch>
|
<mk-switch v-model="objectStorageUseSSL" :disabled="!useObjectStorage">{{ $t('objectStorageUseSSL') }}<template #desc>{{ $t('objectStorageUseSSLDesc') }}</template></mk-switch>
|
||||||
|
<mk-switch v-model="objectStorageUseProxy" :disabled="!useObjectStorage">{{ $t('objectStorageUseProxy') }}<template #desc>{{ $t('objectStorageUseProxyDesc') }}</template></mk-switch>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="_footer">
|
<div class="_footer">
|
||||||
@ -249,6 +250,7 @@ export default Vue.extend({
|
|||||||
objectStorageAccessKey: null,
|
objectStorageAccessKey: null,
|
||||||
objectStorageSecretKey: null,
|
objectStorageSecretKey: null,
|
||||||
objectStorageUseSSL: false,
|
objectStorageUseSSL: false,
|
||||||
|
objectStorageUseProxy: false,
|
||||||
enableTwitterIntegration: false,
|
enableTwitterIntegration: false,
|
||||||
twitterConsumerKey: null,
|
twitterConsumerKey: null,
|
||||||
twitterConsumerSecret: null,
|
twitterConsumerSecret: null,
|
||||||
@ -303,6 +305,7 @@ export default Vue.extend({
|
|||||||
this.objectStorageAccessKey = this.meta.objectStorageAccessKey;
|
this.objectStorageAccessKey = this.meta.objectStorageAccessKey;
|
||||||
this.objectStorageSecretKey = this.meta.objectStorageSecretKey;
|
this.objectStorageSecretKey = this.meta.objectStorageSecretKey;
|
||||||
this.objectStorageUseSSL = this.meta.objectStorageUseSSL;
|
this.objectStorageUseSSL = this.meta.objectStorageUseSSL;
|
||||||
|
this.objectStorageUseProxy = this.meta.objectStorageUseProxy;
|
||||||
this.enableTwitterIntegration = this.meta.enableTwitterIntegration;
|
this.enableTwitterIntegration = this.meta.enableTwitterIntegration;
|
||||||
this.twitterConsumerKey = this.meta.twitterConsumerKey;
|
this.twitterConsumerKey = this.meta.twitterConsumerKey;
|
||||||
this.twitterConsumerSecret = this.meta.twitterConsumerSecret;
|
this.twitterConsumerSecret = this.meta.twitterConsumerSecret;
|
||||||
@ -411,6 +414,7 @@ export default Vue.extend({
|
|||||||
objectStorageAccessKey: this.objectStorageAccessKey ? this.objectStorageAccessKey : null,
|
objectStorageAccessKey: this.objectStorageAccessKey ? this.objectStorageAccessKey : null,
|
||||||
objectStorageSecretKey: this.objectStorageSecretKey ? this.objectStorageSecretKey : null,
|
objectStorageSecretKey: this.objectStorageSecretKey ? this.objectStorageSecretKey : null,
|
||||||
objectStorageUseSSL: this.objectStorageUseSSL,
|
objectStorageUseSSL: this.objectStorageUseSSL,
|
||||||
|
objectStorageUseProxy: this.objectStorageUseProxy,
|
||||||
enableTwitterIntegration: this.enableTwitterIntegration,
|
enableTwitterIntegration: this.enableTwitterIntegration,
|
||||||
twitterConsumerKey: this.twitterConsumerKey,
|
twitterConsumerKey: this.twitterConsumerKey,
|
||||||
twitterConsumerSecret: this.twitterConsumerSecret,
|
twitterConsumerSecret: this.twitterConsumerSecret,
|
||||||
|
209
src/client/pages/instance/users.user.vue
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vrcsvlkm" v-if="user && info">
|
||||||
|
<portal to="title" v-if="user"><mk-user-name :user="user" :nowrap="false" class="name"/></portal>
|
||||||
|
<portal to="avatar" v-if="user"><mk-avatar class="avatar" :user="user" :disable-preview="true"/></portal>
|
||||||
|
|
||||||
|
<section class="_card">
|
||||||
|
<div class="_title">
|
||||||
|
<mk-avatar class="avatar" :user="user"/>
|
||||||
|
<mk-user-name class="name" :user="user"/>
|
||||||
|
<span class="acct">@{{ user | acct }}</span>
|
||||||
|
<span class="staff" v-if="user.isAdmin"><fa :icon="faBookmark"/></span>
|
||||||
|
<span class="staff" v-if="user.isModerator"><fa :icon="farBookmark"/></span>
|
||||||
|
<span class="punished" v-if="user.isSilenced"><fa :icon="faMicrophoneSlash"/></span>
|
||||||
|
<span class="punished" v-if="user.isSuspended"><fa :icon="faSnowflake"/></span>
|
||||||
|
</div>
|
||||||
|
<div class="_content actions">
|
||||||
|
<div style="flex: 1; padding-left: 1em;">
|
||||||
|
<mk-switch v-if="user.host == null && $store.state.i.isAdmin && (this.moderator || !user.isAdmin)" @change="toggleModerator()" v-model="moderator">{{ $t('moderator') }}</mk-switch>
|
||||||
|
<mk-switch @change="toggleSilence()" v-model="silenced">{{ $t('silence') }}</mk-switch>
|
||||||
|
<mk-switch @change="toggleSuspend()" v-model="suspended">{{ $t('suspend') }}</mk-switch>
|
||||||
|
</div>
|
||||||
|
<div style="flex: 1; padding-left: 1em;">
|
||||||
|
<mk-button @click="openProfile"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('profile')}}</mk-button>
|
||||||
|
<mk-button v-if="user.host != null" @click="updateRemoteUser"><fa :icon="faSync"/> {{ $t('updateRemoteUser') }}</mk-button>
|
||||||
|
<mk-button @click="resetPassword"><fa :icon="faKey"/> {{ $t('resetPassword') }}</mk-button>
|
||||||
|
<mk-button @click="deleteAllFiles"><fa :icon="faTrashAlt"/> {{ $t('deleteAllFiles') }}</mk-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="_content rawdata">
|
||||||
|
<pre><code>{{ JSON.stringify(info, null, 2) }}</code></pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { faTimes, faBookmark, faKey, faSync, faMicrophoneSlash, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faSnowflake, faTrashAlt, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import MkButton from '../../components/ui/button.vue';
|
||||||
|
import MkSwitch from '../../components/ui/switch.vue';
|
||||||
|
import i18n from '../../i18n';
|
||||||
|
import Progress from '../../scripts/loading';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n,
|
||||||
|
|
||||||
|
components: {
|
||||||
|
MkButton,
|
||||||
|
MkSwitch,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
user: null,
|
||||||
|
info: null,
|
||||||
|
moderator: false,
|
||||||
|
silenced: false,
|
||||||
|
suspended: false,
|
||||||
|
faTimes, faBookmark, farBookmark, faKey, faSync, faMicrophoneSlash, faSnowflake, faTrashAlt, faExternalLinkSquareAlt
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
$route: 'fetch'
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async fetch() {
|
||||||
|
Progress.start();
|
||||||
|
this.user = await this.$root.api('users/show', { userId: this.$route.params.user });
|
||||||
|
this.info = await this.$root.api('admin/show-user', { userId: this.$route.params.user });
|
||||||
|
this.moderator = this.info.isModerator;
|
||||||
|
this.silenced = this.info.isSilenced;
|
||||||
|
this.suspended = this.info.isSuspended;
|
||||||
|
Progress.done();
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 処理対象ユーザーの情報を更新する */
|
||||||
|
async refreshUser() {
|
||||||
|
this.user = await this.$root.api('users/show', { userId: this.user.id });
|
||||||
|
this.info = await this.$root.api('admin/show-user', { userId: this.user.id });
|
||||||
|
},
|
||||||
|
|
||||||
|
openProfile() {
|
||||||
|
window.open(Vue.filter('userPage')(this.user, null, true), '_blank');
|
||||||
|
},
|
||||||
|
|
||||||
|
async updateRemoteUser() {
|
||||||
|
await this.$root.api('admin/update-remote-user', { userId: this.user.id }).then(res => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await this.refreshUser();
|
||||||
|
},
|
||||||
|
|
||||||
|
async resetPassword() {
|
||||||
|
const dialog = this.$root.dialog({
|
||||||
|
type: 'waiting',
|
||||||
|
iconOnly: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$root.api('admin/reset-password', {
|
||||||
|
userId: this.user.id,
|
||||||
|
}).then(({ password }) => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
text: this.$t('newPasswordIs', { password })
|
||||||
|
});
|
||||||
|
}).catch(e => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e
|
||||||
|
});
|
||||||
|
}).finally(() => {
|
||||||
|
dialog.close();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async toggleSilence() {
|
||||||
|
const confirm = await this.$root.dialog({
|
||||||
|
type: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
text: this.silenced ? this.$t('silenceConfirm') : this.$t('unsilenceConfirm'),
|
||||||
|
});
|
||||||
|
if (confirm.canceled) {
|
||||||
|
this.silenced = !this.silenced;
|
||||||
|
} else {
|
||||||
|
await this.$root.api(this.silenced ? 'admin/silence-user' : 'admin/unsilence-user', { userId: this.user.id });
|
||||||
|
await this.refreshUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async toggleSuspend() {
|
||||||
|
const confirm = await this.$root.dialog({
|
||||||
|
type: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
text: this.suspended ? this.$t('suspendConfirm') : this.$t('unsuspendConfirm'),
|
||||||
|
});
|
||||||
|
if (confirm.canceled) {
|
||||||
|
this.suspended = !this.suspended;
|
||||||
|
} else {
|
||||||
|
await this.$root.api(this.suspended ? 'admin/suspend-user' : 'admin/unsuspend-user', { userId: this.user.id });
|
||||||
|
await this.refreshUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async toggleModerator() {
|
||||||
|
await this.$root.api(this.moderator ? 'admin/moderators/add' : 'admin/moderators/remove', { userId: this.user.id });
|
||||||
|
await this.refreshUser();
|
||||||
|
},
|
||||||
|
|
||||||
|
async deleteAllFiles() {
|
||||||
|
const confirm = await this.$root.dialog({
|
||||||
|
type: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
text: this.$t('deleteAllFilesConfirm'),
|
||||||
|
});
|
||||||
|
if (confirm.canceled) return;
|
||||||
|
const process = async () => {
|
||||||
|
await this.$root.api('admin/delete-all-files-of-a-user', { userId: this.user.id });
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
await process().catch(e => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await this.refreshUser();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.vrcsvlkm {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
> ._card {
|
||||||
|
> .actions {
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
text-align: left;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .rawdata {
|
||||||
|
> pre > code {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -12,19 +12,65 @@
|
|||||||
<mk-button @click="showUser()" primary><fa :icon="faSearch"/> {{ $t('lookup') }}</mk-button>
|
<mk-button @click="showUser()" primary><fa :icon="faSearch"/> {{ $t('lookup') }}</mk-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="_footer">
|
<div class="_footer">
|
||||||
<mk-button inline primary @click="search()"><fa :icon="faSearch"/> {{ $t('search') }}</mk-button>
|
<mk-button inline primary @click="searchUser()"><fa :icon="faSearch"/> {{ $t('search') }}</mk-button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="_card users">
|
<section class="_card users">
|
||||||
<div class="_title"><fa :icon="faUsers"/> {{ $t('users') }}</div>
|
<div class="_title"><fa :icon="faUsers"/> {{ $t('users') }}</div>
|
||||||
|
<div class="_content">
|
||||||
|
<div class="inputs" style="display: flex;">
|
||||||
|
<mk-select v-model="sort" style="margin: 0; flex: 1;">
|
||||||
|
<template #label>{{ $t('sort') }}</template>
|
||||||
|
<option value="-createdAt">{{ $t('registeredDate') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+createdAt">{{ $t('registeredDate') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
<option value="-updatedAt">{{ $t('lastUsed') }} ({{ $t('ascendingOrder') }})</option>
|
||||||
|
<option value="+updatedAt">{{ $t('lastUsed') }} ({{ $t('descendingOrder') }})</option>
|
||||||
|
</mk-select>
|
||||||
|
<mk-select v-model="state" style="margin: 0; flex: 1;">
|
||||||
|
<template #label>{{ $t('state') }}</template>
|
||||||
|
<option value="all">{{ $t('all') }}</option>
|
||||||
|
<option value="available">{{ $t('normal') }}</option>
|
||||||
|
<option value="admin">{{ $t('administrator') }}</option>
|
||||||
|
<option value="moderator">{{ $t('moderator') }}</option>
|
||||||
|
<option value="silenced">{{ $t('silence') }}</option>
|
||||||
|
<option value="suspended">{{ $t('suspend') }}</option>
|
||||||
|
</mk-select>
|
||||||
|
<mk-select v-model="origin" style="margin: 0; flex: 1;">
|
||||||
|
<template #label>{{ $t('instance') }}</template>
|
||||||
|
<option value="combined">{{ $t('all') }}</option>
|
||||||
|
<option value="local">{{ $t('local') }}</option>
|
||||||
|
<option value="remote">{{ $t('remote') }}</option>
|
||||||
|
</mk-select>
|
||||||
|
</div>
|
||||||
|
<div class="inputs" style="display: flex; padding-top: 1.2em;">
|
||||||
|
<mk-input v-model="searchUsername" style="margin: 0; flex: 1;" type="text" spellcheck="false" @input="$refs.users.reload()">
|
||||||
|
<span>{{ $t('username') }}</span>
|
||||||
|
</mk-input>
|
||||||
|
<mk-input v-model="searchHost" style="margin: 0; flex: 1;" type="text" spellcheck="false" @input="$refs.users.reload()" :disabled="pagination.params().origin === 'local'">
|
||||||
|
<span>{{ $t('host') }}</span>
|
||||||
|
</mk-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="_content _list">
|
<div class="_content _list">
|
||||||
<mk-pagination :pagination="pagination" #default="{items}" class="users" ref="users" :auto-margin="false">
|
<mk-pagination :pagination="pagination" #default="{items}" class="users" ref="users" :auto-margin="false">
|
||||||
<button class="user _button _listItem" v-for="(user, i) in items" :key="user.id" @click="show(user)">
|
<button class="user _button _listItem" v-for="(user, i) in items" :key="user.id" @click="show(user)">
|
||||||
<mk-avatar :user="user" class="avatar"/>
|
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<mk-user-name :user="user" class="name"/>
|
<header>
|
||||||
<mk-acct :user="user" class="acct"/>
|
<mk-user-name class="name" :user="user"/>
|
||||||
|
<span class="acct">@{{ user | acct }}</span>
|
||||||
|
<span class="staff" v-if="user.isAdmin"><fa :icon="faBookmark"/></span>
|
||||||
|
<span class="staff" v-if="user.isModerator"><fa :icon="farBookmark"/></span>
|
||||||
|
<span class="punished" v-if="user.isSilenced"><fa :icon="faMicrophoneSlash"/></span>
|
||||||
|
<span class="punished" v-if="user.isSuspended"><fa :icon="faSnowflake"/></span>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<span>{{ $t('lastUsed') }}: <mk-time :time="user.updatedAt" mode="detail"/></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>{{ $t('registeredDate') }}: <mk-time :time="user.createdAt" mode="detail"/></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</mk-pagination>
|
</mk-pagination>
|
||||||
@ -38,12 +84,13 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faPlus, faUsers, faSearch } from '@fortawesome/free-solid-svg-icons';
|
import { faPlus, faUsers, faSearch, faBookmark, faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faSnowflake, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
|
||||||
import parseAcct from '../../../misc/acct/parse';
|
import parseAcct from '../../../misc/acct/parse';
|
||||||
import MkButton from '../../components/ui/button.vue';
|
import MkButton from '../../components/ui/button.vue';
|
||||||
import MkInput from '../../components/ui/input.vue';
|
import MkInput from '../../components/ui/input.vue';
|
||||||
|
import MkSelect from '../../components/ui/select.vue';
|
||||||
import MkPagination from '../../components/ui/pagination.vue';
|
import MkPagination from '../../components/ui/pagination.vue';
|
||||||
import MkUserModerateDialog from '../../components/user-moderate-dialog.vue';
|
|
||||||
import MkUserSelect from '../../components/user-select.vue';
|
import MkUserSelect from '../../components/user-select.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
@ -56,21 +103,46 @@ export default Vue.extend({
|
|||||||
components: {
|
components: {
|
||||||
MkButton,
|
MkButton,
|
||||||
MkInput,
|
MkInput,
|
||||||
|
MkSelect,
|
||||||
MkPagination,
|
MkPagination,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
target: '',
|
||||||
|
sort: '+createdAt',
|
||||||
|
state: 'all',
|
||||||
|
origin: 'local',
|
||||||
|
searchUsername: '',
|
||||||
|
searchHost: '',
|
||||||
pagination: {
|
pagination: {
|
||||||
endpoint: 'admin/show-users',
|
endpoint: 'admin/show-users',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
params: () => ({
|
||||||
|
sort: this.sort,
|
||||||
|
state: this.state,
|
||||||
|
origin: this.origin,
|
||||||
|
username: this.searchUsername,
|
||||||
|
hostname: this.searchHost,
|
||||||
|
}),
|
||||||
offsetMode: true
|
offsetMode: true
|
||||||
},
|
},
|
||||||
target: '',
|
faPlus, faUsers, faSearch, faBookmark, farBookmark, faMicrophoneSlash, faSnowflake
|
||||||
faPlus, faUsers, faSearch
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
sort() {
|
||||||
|
this.$refs.users.reload();
|
||||||
|
},
|
||||||
|
state() {
|
||||||
|
this.$refs.users.reload();
|
||||||
|
},
|
||||||
|
origin() {
|
||||||
|
this.$refs.users.reload();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/** テキストエリアのユーザーを解決する */
|
/** テキストエリアのユーザーを解決する */
|
||||||
fetchUser() {
|
fetchUser() {
|
||||||
@ -102,12 +174,16 @@ export default Vue.extend({
|
|||||||
/** テキストエリアから処理対象ユーザーを設定する */
|
/** テキストエリアから処理対象ユーザーを設定する */
|
||||||
async showUser() {
|
async showUser() {
|
||||||
const user = await this.fetchUser();
|
const user = await this.fetchUser();
|
||||||
this.$root.api('admin/show-user', { userId: user.id }).then(info => {
|
this.show(user);
|
||||||
this.show(user, info);
|
|
||||||
});
|
|
||||||
this.target = '';
|
this.target = '';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
searchUser() {
|
||||||
|
this.$root.new(MkUserSelect, {}).$once('selected', user => {
|
||||||
|
this.show(user);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
async addUser() {
|
async addUser() {
|
||||||
const { canceled: canceled1, result: username } = await this.$root.dialog({
|
const { canceled: canceled1, result: username } = await this.$root.dialog({
|
||||||
title: this.$t('username'),
|
title: this.$t('username'),
|
||||||
@ -145,19 +221,8 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async show(user, info) {
|
async show(user) {
|
||||||
if (info == null) info = await this.$root.api('admin/show-user', { userId: user.id });
|
this.$router.push('./users/' + user.id);
|
||||||
this.$root.new(MkUserModerateDialog, {
|
|
||||||
user: { ...user, ...info }
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
search() {
|
|
||||||
this.$root.new(MkUserSelect, {}).$once('selected', user => {
|
|
||||||
this.$root.api('admin/show-user', { userId: user.id }).then(info => {
|
|
||||||
this.show(user, info);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -179,20 +244,38 @@ export default Vue.extend({
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
width: 50px;
|
width: 64px;
|
||||||
height: 50px;
|
height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .body {
|
> .body {
|
||||||
|
margin-left: 0.3em;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
@media (max-width 500px) {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> header {
|
||||||
> .name {
|
> .name {
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .acct {
|
> .acct {
|
||||||
opacity: 0.5;
|
margin-left: 8px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .staff {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
color: var(--badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .punished {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
color: #4dabf7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="no-history" v-if="!fetching && messages.length == 0">
|
<div class="_fullinfo" v-if="!fetching && messages.length == 0">
|
||||||
<img src="https://xn--931a.moe/assets/info.png" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||||
<div>{{ $t('noHistory') }}</div>
|
<div>{{ $t('noHistory') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<mk-loading v-if="fetching"/>
|
<mk-loading v-if="fetching"/>
|
||||||
@ -42,10 +42,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faUser, faUsers, faComments, faPlus } from '@fortawesome/free-solid-svg-icons';
|
import { faUser, faUsers, faComments, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../../i18n';
|
||||||
import getAcct from '../../misc/acct/render';
|
import getAcct from '../../../misc/acct/render';
|
||||||
import MkButton from '../components/ui/button.vue';
|
import MkButton from '../../components/ui/button.vue';
|
||||||
import MkUserSelect from '../components/user-select.vue';
|
import MkUserSelect from '../../components/user-select.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
@ -287,18 +287,6 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .no-history {
|
|
||||||
padding: 32px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
vertical-align: bottom;
|
|
||||||
height: 128px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 400px) {
|
@media (max-width: 400px) {
|
||||||
> .history {
|
> .history {
|
||||||
> .message {
|
> .message {
|
@ -27,14 +27,14 @@ import Vue from 'vue';
|
|||||||
import { faPaperPlane, faPhotoVideo, faLaughSquint } from '@fortawesome/free-solid-svg-icons';
|
import { faPaperPlane, faPhotoVideo, faLaughSquint } from '@fortawesome/free-solid-svg-icons';
|
||||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||||
import * as autosize from 'autosize';
|
import * as autosize from 'autosize';
|
||||||
import i18n from '../i18n';
|
import i18n from '../../i18n';
|
||||||
import { formatTimeString } from '../../misc/format-time-string';
|
import { formatTimeString } from '../../../misc/format-time-string';
|
||||||
import { selectFile } from '../scripts/select-file';
|
import { selectFile } from '../../scripts/select-file';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
components: {
|
components: {
|
||||||
XUploader: () => import('../components/uploader.vue').then(m => m.default),
|
XUploader: () => import('../../components/uploader.vue').then(m => m.default),
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
user: {
|
user: {
|
||||||
@ -221,7 +221,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async insertEmoji(ev) {
|
async insertEmoji(ev) {
|
||||||
const vm = this.$root.new(await import('../components/emoji-picker.vue').then(m => m.default), {
|
const vm = this.$root.new(await import('../../components/emoji-picker.vue').then(m => m.default), {
|
||||||
source: ev.currentTarget || ev.target
|
source: ev.currentTarget || ev.target
|
||||||
}).$once('chosen', emoji => {
|
}).$once('chosen', emoji => {
|
||||||
insertTextAtCursor(this.$refs.text, emoji);
|
insertTextAtCursor(this.$refs.text, emoji);
|
@ -21,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
<div></div>
|
||||||
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
|
<mk-url-preview v-for="url in urls" :url="url" :key="url" style="margin: 8px 0;"/>
|
||||||
<footer>
|
<footer>
|
||||||
<template v-if="isGroup">
|
<template v-if="isGroup">
|
||||||
<span class="read" v-if="message.reads.length > 0">{{ $t('messageRead') }} {{ message.reads.length }}</span>
|
<span class="read" v-if="message.reads.length > 0">{{ $t('messageRead') }} {{ message.reads.length }}</span>
|
||||||
@ -38,12 +38,16 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../i18n';
|
import i18n from '../../i18n';
|
||||||
import { parse } from '../../mfm/parse';
|
import { parse } from '../../../mfm/parse';
|
||||||
import { unique } from '../../prelude/array';
|
import { unique } from '../../../prelude/array';
|
||||||
|
import MkUrlPreview from '../../components/url-preview.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
components: {
|
||||||
|
MkUrlPreview
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
message: {
|
message: {
|
||||||
required: true
|
required: true
|
||||||
@ -210,6 +214,7 @@ export default Vue.extend({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 512px;
|
max-height: 512px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p {
|
> p {
|
||||||
@ -223,10 +228,6 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .mk-url-preview {
|
|
||||||
margin: 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
> footer {
|
> footer {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 2px 0 0 0;
|
margin: 2px 0 0 0;
|
@ -19,7 +19,7 @@
|
|||||||
<button class="more _button" :class="{ fetching: fetchingMoreMessages }" v-if="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages">
|
<button class="more _button" :class="{ fetching: fetchingMoreMessages }" v-if="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages">
|
||||||
<template v-if="fetchingMoreMessages"><fa icon="spinner" pulse fixed-width/></template>{{ fetchingMoreMessages ? $t('loading') : $t('loadMore') }}
|
<template v-if="fetchingMoreMessages"><fa icon="spinner" pulse fixed-width/></template>{{ fetchingMoreMessages ? $t('loading') : $t('loadMore') }}
|
||||||
</button>
|
</button>
|
||||||
<x-list class="messages" :items="messages" v-slot="{ item: message, i }" direction="up" reversed>
|
<x-list class="messages" :items="messages" v-slot="{ item: message }" direction="up" reversed>
|
||||||
<x-message :message="message" :is-group="group != null" :key="message.id"/>
|
<x-message :message="message" :is-group="group != null" :key="message.id"/>
|
||||||
</x-list>
|
</x-list>
|
||||||
</div>
|
</div>
|
||||||
@ -37,12 +37,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faArrowCircleDown, faFlag, faUsers, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faArrowCircleDown, faFlag, faUsers, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../../i18n';
|
||||||
import XList from '../components/date-separated-list.vue';
|
import XList from '../../components/date-separated-list.vue';
|
||||||
import XMessage from './messaging-room.message.vue';
|
import XMessage from './messaging-room.message.vue';
|
||||||
import XForm from './messaging-room.form.vue';
|
import XForm from './messaging-room.form.vue';
|
||||||
import { url } from '../config';
|
import { url } from '../../config';
|
||||||
import parseAcct from '../../misc/acct/parse';
|
import parseAcct from '../../../misc/acct/parse';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
103
src/client/pages/miauth.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="$store.getters.isSignedIn">
|
||||||
|
<div class="waiting _card" v-if="state == 'waiting'">
|
||||||
|
<div class="_content">
|
||||||
|
<mk-loading/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="denied _card" v-if="state == 'denied'">
|
||||||
|
<div class="_content">
|
||||||
|
<p>{{ $t('_auth.denied') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accepted _card" v-else-if="state == 'accepted'">
|
||||||
|
<div class="_content">
|
||||||
|
<p v-if="callback">{{ $t('_auth.callback') }}<mk-ellipsis/></p>
|
||||||
|
<p v-else>{{ $t('_auth.pleaseGoBack') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="_card" v-else>
|
||||||
|
<div class="_title" v-if="name">{{ $t('_auth.shareAccess', { name: name }) }}</div>
|
||||||
|
<div class="_title" v-else>{{ $t('_auth.shareAccessAsk') }}</div>
|
||||||
|
<div class="_content">
|
||||||
|
<p>{{ $t('_auth.permissionAsk') }}</p>
|
||||||
|
<ul>
|
||||||
|
<template v-for="p in permission">
|
||||||
|
<li :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="_footer">
|
||||||
|
<mk-button @click="deny" inline>{{ $t('cancel') }}</mk-button>
|
||||||
|
<mk-button @click="accept" inline primary>{{ $t('accept') }}</mk-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="signin" v-else>
|
||||||
|
<mk-signin @login="onLogin"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../i18n';
|
||||||
|
import MkSignin from '../components/signin.vue';
|
||||||
|
import MkButton from '../components/ui/button.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n,
|
||||||
|
components: {
|
||||||
|
MkSignin,
|
||||||
|
MkButton,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
state: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
session(): string {
|
||||||
|
return this.$route.params.session;
|
||||||
|
},
|
||||||
|
callback(): string {
|
||||||
|
return this.$route.query.callback;
|
||||||
|
},
|
||||||
|
name(): string {
|
||||||
|
return this.$route.query.name;
|
||||||
|
},
|
||||||
|
icon(): string {
|
||||||
|
return this.$route.query.icon;
|
||||||
|
},
|
||||||
|
permission(): string[] {
|
||||||
|
return this.$route.query.permission ? this.$route.query.permission.split(',') : [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async accept() {
|
||||||
|
this.state = 'waiting';
|
||||||
|
await this.$root.api('miauth/gen-token', {
|
||||||
|
session: this.session,
|
||||||
|
name: this.name,
|
||||||
|
iconUrl: this.icon,
|
||||||
|
permission: this.permission,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.state = 'accepted';
|
||||||
|
if (this.callback) {
|
||||||
|
location.href = `${this.callback}?session=${this.session}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deny() {
|
||||||
|
this.state = 'denied';
|
||||||
|
},
|
||||||
|
onLogin(res) {
|
||||||
|
localStorage.setItem('i', res.i);
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -32,7 +32,9 @@
|
|||||||
<x-integration/>
|
<x-integration/>
|
||||||
<x-api/>
|
<x-api/>
|
||||||
|
|
||||||
<mk-button @click="$root.signout()" primary style="margin: var(--margin) auto;">{{ $t('logout') }}</mk-button>
|
<router-link class="_panel _buttonPrimary" to="/my/apps" style="margin: var(--margin) auto;">{{ $t('installedApps') }}</router-link>
|
||||||
|
|
||||||
|
<button class="_panel _buttonPrimary" @click="$root.signout()" style="margin: var(--margin) auto;">{{ $t('logout') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<section class="_card">
|
<section class="_card">
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<img src="https://xn--931a.moe/assets/not-found.png" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/not-found.jpg" class="_ghost"/>
|
||||||
<div>{{ $t('notFoundDescription') }}</div>
|
<div>{{ $t('notFoundDescription') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<x-notes v-if="showNext" ref="next" :pagination="next"/>
|
<x-notes v-if="showNext" ref="next" :pagination="next"/>
|
||||||
<hr v-if="showNext"/>
|
<hr v-if="showNext"/>
|
||||||
|
|
||||||
<mk-remote-caution v-if="note.user.host != null" :href="note.uri" style="margin-bottom: var(--margin)"/>
|
<mk-remote-caution v-if="note.user.host != null" :href="note.url || note.uri" style="margin-bottom: var(--margin)"/>
|
||||||
<x-note :note="note" :key="note.id" :detail="true"/>
|
<x-note :note="note" :key="note.id" :detail="true"/>
|
||||||
<div v-if="error">
|
<div v-if="error">
|
||||||
<mk-error @retry="fetch()"/>
|
<mk-error @retry="fetch()"/>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<option value="dialog">{{ $t('_pages.blocks._button._action.dialog') }}</option>
|
<option value="dialog">{{ $t('_pages.blocks._button._action.dialog') }}</option>
|
||||||
<option value="resetRandom">{{ $t('_pages.blocks._button._action.resetRandom') }}</option>
|
<option value="resetRandom">{{ $t('_pages.blocks._button._action.resetRandom') }}</option>
|
||||||
<option value="pushEvent">{{ $t('_pages.blocks._button._action.pushEvent') }}</option>
|
<option value="pushEvent">{{ $t('_pages.blocks._button._action.pushEvent') }}</option>
|
||||||
|
<option value="callAiScript">{{ $t('_pages.blocks._button._action.callAiScript') }}</option>
|
||||||
</mk-select>
|
</mk-select>
|
||||||
<template v-if="value.action === 'dialog'">
|
<template v-if="value.action === 'dialog'">
|
||||||
<mk-input v-model="value.content"><span>{{ $t('_pages.blocks._button._action._dialog.content') }}</span></mk-input>
|
<mk-input v-model="value.content"><span>{{ $t('_pages.blocks._button._action._dialog.content') }}</span></mk-input>
|
||||||
@ -20,15 +21,18 @@
|
|||||||
<mk-select v-model="value.var">
|
<mk-select v-model="value.var">
|
||||||
<template #label>{{ $t('_pages.blocks._button._action._pushEvent.variable') }}</template>
|
<template #label>{{ $t('_pages.blocks._button._action._pushEvent.variable') }}</template>
|
||||||
<option :value="null">{{ $t('_pages.blocks._button._action._pushEvent.no-variable') }}</option>
|
<option :value="null">{{ $t('_pages.blocks._button._action._pushEvent.no-variable') }}</option>
|
||||||
<option v-for="v in aiScript.getVarsByType()" :value="v.name">{{ v.name }}</option>
|
<option v-for="v in aoiScript.getVarsByType()" :value="v.name">{{ v.name }}</option>
|
||||||
<optgroup :label="$t('_pages.script.pageVariables')">
|
<optgroup :label="$t('_pages.script.pageVariables')">
|
||||||
<option v-for="v in aiScript.getPageVarsByType()" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getPageVarsByType()" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
||||||
<option v-for="v in aiScript.getEnvVarsByType()" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getEnvVarsByType()" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</mk-select>
|
</mk-select>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="value.action === 'callAiScript'">
|
||||||
|
<mk-input v-model="value.fn"><span>{{ $t('_pages.blocks._button._action._callAiScript.functionName') }}</span></mk-input>
|
||||||
|
</template>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
</template>
|
</template>
|
||||||
@ -53,7 +57,7 @@ export default Vue.extend({
|
|||||||
value: {
|
value: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
aiScript: {
|
aoiScript: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -72,6 +76,7 @@ export default Vue.extend({
|
|||||||
if (this.value.message == null) Vue.set(this.value, 'message', null);
|
if (this.value.message == null) Vue.set(this.value, 'message', null);
|
||||||
if (this.value.primary == null) Vue.set(this.value, 'primary', false);
|
if (this.value.primary == null) Vue.set(this.value, 'primary', false);
|
||||||
if (this.value.var == null) Vue.set(this.value, 'var', null);
|
if (this.value.var == null) Vue.set(this.value, 'var', null);
|
||||||
|
if (this.value.fn == null) Vue.set(this.value, 'fn', null);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
45
src/client/pages/page-editor/els/page-editor.el.canvas.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<x-container @remove="() => $emit('remove')" :draggable="true">
|
||||||
|
<template #header><fa :icon="faPaintBrush"/> {{ $t('_pages.blocks.canvas') }}</template>
|
||||||
|
|
||||||
|
<section style="padding: 0 16px 0 16px;">
|
||||||
|
<mk-input v-model="value.name"><template #prefix><fa :icon="faMagic"/></template><span>{{ $t('_pages.blocks._canvas.id') }}</span></mk-input>
|
||||||
|
<mk-input v-model="value.width" type="number"><span>{{ $t('_pages.blocks._canvas.width') }}</span><template #suffix>px</template></mk-input>
|
||||||
|
<mk-input v-model="value.height" type="number"><span>{{ $t('_pages.blocks._canvas.height') }}</span><template #suffix>px</template></mk-input>
|
||||||
|
</section>
|
||||||
|
</x-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { faPaintBrush, faMagic } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import XContainer from '../page-editor.container.vue';
|
||||||
|
import MkInput from '../../../components/ui/input.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n,
|
||||||
|
|
||||||
|
components: {
|
||||||
|
XContainer, MkInput
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faPaintBrush, faMagic
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (this.value.name == null) Vue.set(this.value, 'name', '');
|
||||||
|
if (this.value.width == null) Vue.set(this.value, 'width', 300);
|
||||||
|
if (this.value.height == null) Vue.set(this.value, 'height', 200);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
@ -2,7 +2,7 @@
|
|||||||
<x-container @remove="() => $emit('remove')" :draggable="true">
|
<x-container @remove="() => $emit('remove')" :draggable="true">
|
||||||
<template #header><fa :icon="faQuestion"/> {{ $t('_pages.blocks.if') }}</template>
|
<template #header><fa :icon="faQuestion"/> {{ $t('_pages.blocks.if') }}</template>
|
||||||
<template #func>
|
<template #func>
|
||||||
<button @click="add()">
|
<button @click="add()" class="_button">
|
||||||
<fa :icon="faPlus"/>
|
<fa :icon="faPlus"/>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
@ -10,16 +10,16 @@
|
|||||||
<section class="romcojzs">
|
<section class="romcojzs">
|
||||||
<mk-select v-model="value.var">
|
<mk-select v-model="value.var">
|
||||||
<template #label>{{ $t('_pages.blocks._if.variable') }}</template>
|
<template #label>{{ $t('_pages.blocks._if.variable') }}</template>
|
||||||
<option v-for="v in aiScript.getVarsByType('boolean')" :value="v.name">{{ v.name }}</option>
|
<option v-for="v in aoiScript.getVarsByType('boolean')" :value="v.name">{{ v.name }}</option>
|
||||||
<optgroup :label="$t('_pages.script.pageVariables')">
|
<optgroup :label="$t('_pages.script.pageVariables')">
|
||||||
<option v-for="v in aiScript.getPageVarsByType('boolean')" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getPageVarsByType('boolean')" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
||||||
<option v-for="v in aiScript.getEnvVarsByType('boolean')" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getEnvVarsByType('boolean')" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</mk-select>
|
</mk-select>
|
||||||
|
|
||||||
<x-blocks class="children" v-model="value.children" :ai-script="aiScript"/>
|
<x-blocks class="children" v-model="value.children" :aoi-script="aoiScript"/>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
</template>
|
</template>
|
||||||
@ -45,7 +45,7 @@ export default Vue.extend({
|
|||||||
value: {
|
value: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
aiScript: {
|
aoiScript: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
<x-container @remove="() => $emit('remove')" :draggable="true">
|
<x-container @remove="() => $emit('remove')" :draggable="true">
|
||||||
<template #header><fa :icon="faPaperPlane"/> {{ $t('_pages.blocks.post') }}</template>
|
<template #header><fa :icon="faPaperPlane"/> {{ $t('_pages.blocks.post') }}</template>
|
||||||
|
|
||||||
<section style="padding: 0 16px 16px 16px;">
|
<section style="padding: 16px;">
|
||||||
<mk-textarea v-model="value.text">{{ $t('_pages.blocks._post.text') }}</mk-textarea>
|
<mk-textarea v-model="value.text">{{ $t('_pages.blocks._post.text') }}</mk-textarea>
|
||||||
|
<mk-switch v-model="value.attachCanvasImage"><span>{{ $t('_pages.blocks._post.attachCanvasImage') }}</span></mk-switch>
|
||||||
|
<mk-input v-if="value.attachCanvasImage" v-model="value.canvasId"><span>{{ $t('_pages.blocks._post.canvasId') }}</span></mk-input>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
</template>
|
</template>
|
||||||
@ -14,12 +16,14 @@ import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
|
|||||||
import i18n from '../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XContainer from '../page-editor.container.vue';
|
import XContainer from '../page-editor.container.vue';
|
||||||
import MkTextarea from '../../../components/ui/textarea.vue';
|
import MkTextarea from '../../../components/ui/textarea.vue';
|
||||||
|
import MkInput from '../../../components/ui/input.vue';
|
||||||
|
import MkSwitch from '../../../components/ui/switch.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
XContainer, MkTextarea
|
XContainer, MkTextarea, MkInput, MkSwitch
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -36,6 +40,8 @@ export default Vue.extend({
|
|||||||
|
|
||||||
created() {
|
created() {
|
||||||
if (this.value.text == null) Vue.set(this.value, 'text', '');
|
if (this.value.text == null) Vue.set(this.value, 'text', '');
|
||||||
|
if (this.value.attachCanvasImage == null) Vue.set(this.value, 'attachCanvasImage', false);
|
||||||
|
if (this.value.canvasId == null) Vue.set(this.value, 'canvasId', '');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
<x-container @remove="() => $emit('remove')" :draggable="true">
|
<x-container @remove="() => $emit('remove')" :draggable="true">
|
||||||
<template #header><fa :icon="faStickyNote"/> {{ value.title }}</template>
|
<template #header><fa :icon="faStickyNote"/> {{ value.title }}</template>
|
||||||
<template #func>
|
<template #func>
|
||||||
<button @click="rename()">
|
<button @click="rename()" class="_button">
|
||||||
<fa :icon="faPencilAlt"/>
|
<fa :icon="faPencilAlt"/>
|
||||||
</button>
|
</button>
|
||||||
<button @click="add()">
|
<button @click="add()" class="_button">
|
||||||
<fa :icon="faPlus"/>
|
<fa :icon="faPlus"/>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<section class="ilrvjyvi">
|
<section class="ilrvjyvi">
|
||||||
<x-blocks class="children" v-model="value.children" :ai-script="aiScript"/>
|
<x-blocks class="children" v-model="value.children" :aoi-script="aoiScript"/>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
</template>
|
</template>
|
||||||
@ -37,7 +37,7 @@ export default Vue.extend({
|
|||||||
value: {
|
value: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
aiScript: {
|
aoiScript: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<x-container @remove="() => $emit('remove')" :draggable="true">
|
<x-container @remove="() => $emit('remove')" :draggable="true">
|
||||||
<template #header><fa :icon="faAlignLeft"/> {{ $t('_pages.blocks.text') }}</template>
|
<template #header><fa :icon="faAlignLeft"/> {{ $t('_pages.blocks.text') }}</template>
|
||||||
|
|
||||||
<section class="ihymsbbe">
|
<section class="vckmsadr">
|
||||||
<textarea v-model="value.text"></textarea>
|
<textarea v-model="value.text"></textarea>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
@ -40,7 +40,7 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.ihymsbbe {
|
.vckmsadr {
|
||||||
> textarea {
|
> textarea {
|
||||||
display: block;
|
display: block;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@ -55,6 +55,7 @@ export default Vue.extend({
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -55,6 +55,7 @@ export default Vue.extend({
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-draggable tag="div" :list="blocks" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150" swap-threshold="0.5">
|
<x-draggable tag="div" :list="blocks" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150" swap-threshold="0.5">
|
||||||
<component v-for="block in blocks" :is="'x-' + block.type" :value="block" @input="updateItem" @remove="() => removeItem(block)" :key="block.id" :ai-script="aiScript"/>
|
<component v-for="block in blocks" :is="'x-' + block.type" :value="block" @input="updateItem" @remove="() => removeItem(block)" :key="block.id" :aoi-script="aoiScript"/>
|
||||||
</x-draggable>
|
</x-draggable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -20,10 +20,11 @@ import XIf from './els/page-editor.el.if.vue';
|
|||||||
import XPost from './els/page-editor.el.post.vue';
|
import XPost from './els/page-editor.el.post.vue';
|
||||||
import XCounter from './els/page-editor.el.counter.vue';
|
import XCounter from './els/page-editor.el.counter.vue';
|
||||||
import XRadioButton from './els/page-editor.el.radio-button.vue';
|
import XRadioButton from './els/page-editor.el.radio-button.vue';
|
||||||
|
import XCanvas from './els/page-editor.el.canvas.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XDraggable, XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost, XCounter, XRadioButton
|
XDraggable, XSection, XText, XImage, XButton, XTextarea, XTextInput, XTextareaInput, XNumberInput, XSwitch, XIf, XPost, XCounter, XRadioButton, XCanvas
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -31,7 +32,7 @@ export default Vue.extend({
|
|||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
aiScript: {
|
aoiScript: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</header>
|
</header>
|
||||||
<p v-show="showBody" class="error" v-if="error != null">{{ $t('_pages.script.typeError', { slot: error.arg + 1, expect: $t(`script.types.${error.expect}`), actual: $t(`script.types.${error.actual}`) }) }}</p>
|
<p v-show="showBody" class="error" v-if="error != null">{{ $t('_pages.script.typeError', { slot: error.arg + 1, expect: $t(`script.types.${error.expect}`), actual: $t(`script.types.${error.actual}`) }) }}</p>
|
||||||
<p v-show="showBody" class="warn" v-if="warn != null">{{ $t('_pages.script.thereIsEmptySlot', { slot: warn.slot + 1 }) }}</p>
|
<p v-show="showBody" class="warn" v-if="warn != null">{{ $t('_pages.script.thereIsEmptySlot', { slot: warn.slot + 1 }) }}</p>
|
||||||
<div v-show="showBody">
|
<div v-show="showBody" class="body">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -148,5 +148,17 @@ export default Vue.extend({
|
|||||||
padding: 16px 16px 0 16px;
|
padding: 16px 16px 0 16px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .body {
|
||||||
|
::v-deep .juejbjww, ::v-deep .eiipwacr {
|
||||||
|
&:not(.inline):first-child {
|
||||||
|
margin-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.inline):last-child {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<x-container :removable="removable" @remove="() => $emit('remove')" :error="error" :warn="warn" :draggable="draggable">
|
<x-container :removable="removable" @remove="() => $emit('remove')" :error="error" :warn="warn" :draggable="draggable">
|
||||||
<template #header><fa v-if="icon" :icon="icon"/> <template v-if="title">{{ title }} <span class="turmquns" v-if="typeText">({{ typeText }})</span></template><template v-else-if="typeText">{{ typeText }}</template></template>
|
<template #header><fa v-if="icon" :icon="icon"/> <template v-if="title">{{ title }} <span class="turmquns" v-if="typeText">({{ typeText }})</span></template><template v-else-if="typeText">{{ typeText }}</template></template>
|
||||||
<template #func>
|
<template #func>
|
||||||
<button @click="changeType()">
|
<button @click="changeType()" class="_button">
|
||||||
<fa :icon="faPencilAlt"/>
|
<fa :icon="faPencilAlt"/>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
@ -24,30 +24,33 @@
|
|||||||
</section>
|
</section>
|
||||||
<section v-else-if="value.type === 'ref'" class="hpdwcrvs">
|
<section v-else-if="value.type === 'ref'" class="hpdwcrvs">
|
||||||
<select v-model="value.value">
|
<select v-model="value.value">
|
||||||
<option v-for="v in aiScript.getVarsByType(getExpectedType ? getExpectedType() : null).filter(x => x.name !== name)" :value="v.name">{{ v.name }}</option>
|
<option v-for="v in aoiScript.getVarsByType(getExpectedType ? getExpectedType() : null).filter(x => x.name !== name)" :value="v.name">{{ v.name }}</option>
|
||||||
<optgroup :label="$t('_pages.script.argVariables')">
|
<optgroup :label="$t('_pages.script.argVariables')">
|
||||||
<option v-for="v in fnSlots" :value="v.name">{{ v.name }}</option>
|
<option v-for="v in fnSlots" :value="v.name">{{ v.name }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup :label="$t('_pages.script.pageVariables')">
|
<optgroup :label="$t('_pages.script.pageVariables')">
|
||||||
<option v-for="v in aiScript.getPageVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getPageVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
<optgroup :label="$t('_pages.script.enviromentVariables')">
|
||||||
<option v-for="v in aiScript.getEnvVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
|
<option v-for="v in aoiScript.getEnvVarsByType(getExpectedType ? getExpectedType() : null)" :value="v">{{ v }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</section>
|
</section>
|
||||||
|
<section v-else-if="value.type === 'aiScriptVar'" class="tbwccoaw">
|
||||||
|
<input v-model="value.value"/>
|
||||||
|
</section>
|
||||||
<section v-else-if="value.type === 'fn'" class="" style="padding:0 16px 16px 16px;">
|
<section v-else-if="value.type === 'fn'" class="" style="padding:0 16px 16px 16px;">
|
||||||
<mk-textarea v-model="slots">
|
<mk-textarea v-model="slots">
|
||||||
<span>{{ $t('_pages.script.blocks._fn.slots') }}</span>
|
<span>{{ $t('_pages.script.blocks._fn.slots') }}</span>
|
||||||
<template #desc>{{ $t('_pages.script.blocks._fn.slots-info') }}</template>
|
<template #desc>{{ $t('_pages.script.blocks._fn.slots-info') }}</template>
|
||||||
</mk-textarea>
|
</mk-textarea>
|
||||||
<x-v v-if="value.value.expression" v-model="value.value.expression" :title="$t(`_pages.script.blocks._fn.arg1`)" :get-expected-type="() => null" :ai-script="aiScript" :fn-slots="value.value.slots" :name="name"/>
|
<x-v v-if="value.value.expression" v-model="value.value.expression" :title="$t(`_pages.script.blocks._fn.arg1`)" :get-expected-type="() => null" :aoi-script="aoiScript" :fn-slots="value.value.slots" :name="name"/>
|
||||||
</section>
|
</section>
|
||||||
<section v-else-if="value.type.startsWith('fn:')" class="" style="padding:16px;">
|
<section v-else-if="value.type.startsWith('fn:')" class="" style="padding:16px;">
|
||||||
<x-v v-for="(x, i) in value.args" v-model="value.args[i]" :title="aiScript.getVarByName(value.type.split(':')[1]).value.slots[i].name" :get-expected-type="() => null" :ai-script="aiScript" :name="name" :key="i"/>
|
<x-v v-for="(x, i) in value.args" v-model="value.args[i]" :title="aoiScript.getVarByName(value.type.split(':')[1]).value.slots[i].name" :get-expected-type="() => null" :aoi-script="aoiScript" :name="name" :key="i"/>
|
||||||
</section>
|
</section>
|
||||||
<section v-else class="" style="padding:16px;">
|
<section v-else class="" style="padding:16px;">
|
||||||
<x-v v-for="(x, i) in value.args" v-model="value.args[i]" :title="$t(`_pages.script.blocks._${value.type}.arg${i + 1}`)" :get-expected-type="() => _getExpectedType(i)" :ai-script="aiScript" :name="name" :fn-slots="fnSlots" :key="i"/>
|
<x-v v-for="(x, i) in value.args" v-model="value.args[i]" :title="$t(`_pages.script.blocks._${value.type}.arg${i + 1}`)" :get-expected-type="() => _getExpectedType(i)" :aoi-script="aoiScript" :name="name" :fn-slots="fnSlots" :key="i"/>
|
||||||
</section>
|
</section>
|
||||||
</x-container>
|
</x-container>
|
||||||
</template>
|
</template>
|
||||||
@ -59,7 +62,7 @@ import { v4 as uuid } from 'uuid';
|
|||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import XContainer from './page-editor.container.vue';
|
import XContainer from './page-editor.container.vue';
|
||||||
import MkTextarea from '../../components/ui/textarea.vue';
|
import MkTextarea from '../../components/ui/textarea.vue';
|
||||||
import { isLiteralBlock, funcDefs, blockDefs } from '../../scripts/aiscript/index';
|
import { isLiteralBlock, funcDefs, blockDefs } from '../../scripts/aoiscript/index';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
@ -85,7 +88,7 @@ export default Vue.extend({
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
aiScript: {
|
aoiScript: {
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
@ -153,7 +156,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
if (this.value.type && this.value.type.startsWith('fn:')) {
|
if (this.value.type && this.value.type.startsWith('fn:')) {
|
||||||
const fnName = this.value.type.split(':')[1];
|
const fnName = this.value.type.split(':')[1];
|
||||||
const fn = this.aiScript.getVarByName(fnName);
|
const fn = this.aoiScript.getVarByName(fnName);
|
||||||
|
|
||||||
const empties = [];
|
const empties = [];
|
||||||
for (let i = 0; i < fn.value.slots.length; i++) {
|
for (let i = 0; i < fn.value.slots.length; i++) {
|
||||||
@ -199,9 +202,9 @@ export default Vue.extend({
|
|||||||
deep: true
|
deep: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$watch('aiScript.variables', () => {
|
this.$watch('aoiScript.variables', () => {
|
||||||
if (this.type != null && this.value) {
|
if (this.type != null && this.value) {
|
||||||
this.error = this.aiScript.typeCheck(this.value);
|
this.error = this.aoiScript.typeCheck(this.value);
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
deep: true
|
deep: true
|
||||||
@ -223,7 +226,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_getExpectedType(slot: number) {
|
_getExpectedType(slot: number) {
|
||||||
return this.aiScript.getExpectedType(this.value, slot);
|
return this.aoiScript.getExpectedType(this.value, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -258,6 +261,7 @@ export default Vue.extend({
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
> textarea {
|
> textarea {
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<x-blocks class="content" v-model="content" :ai-script="aiScript"/>
|
<x-blocks class="content" v-model="content" :aoi-script="aoiScript"/>
|
||||||
|
|
||||||
<mk-button @click="add()" v-if="!readonly"><fa :icon="faPlus"/></mk-button>
|
<mk-button @click="add()" v-if="!readonly"><fa :icon="faPlus"/></mk-button>
|
||||||
</section>
|
</section>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
@input="v => updateVariable(v)"
|
@input="v => updateVariable(v)"
|
||||||
@remove="() => removeVariable(variable)"
|
@remove="() => removeVariable(variable)"
|
||||||
:key="variable.name"
|
:key="variable.name"
|
||||||
:ai-script="aiScript"
|
:aoi-script="aoiScript"
|
||||||
:name="variable.name"
|
:name="variable.name"
|
||||||
:title="variable.name"
|
:title="variable.name"
|
||||||
:draggable="true"
|
:draggable="true"
|
||||||
@ -73,11 +73,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</mk-container>
|
</mk-container>
|
||||||
|
|
||||||
<mk-container :body-togglable="true" :expanded="false">
|
<mk-container :body-togglable="true" :expanded="true">
|
||||||
<template #header><fa :icon="faCode"/> {{ $t('_pages.inspector') }}</template>
|
<template #header><fa :icon="faCode"/> {{ $t('script') }}</template>
|
||||||
<div style="padding:0 32px 32px 32px;">
|
<div>
|
||||||
<mk-textarea :value="JSON.stringify(content, null, 2)" readonly tall>{{ $t('_pages.content') }}</mk-textarea>
|
<prism-editor v-model="script" :line-numbers="false" language="js"/>
|
||||||
<mk-textarea :value="JSON.stringify(variables, null, 2)" readonly tall>{{ $t('_pages.variables') }}</mk-textarea>
|
|
||||||
</div>
|
</div>
|
||||||
</mk-container>
|
</mk-container>
|
||||||
</div>
|
</div>
|
||||||
@ -86,6 +85,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import * as XDraggable from 'vuedraggable';
|
import * as XDraggable from 'vuedraggable';
|
||||||
|
import "prismjs";
|
||||||
|
import 'prismjs/themes/prism-okaidia.css';
|
||||||
|
import PrismEditor from 'vue-prism-editor';
|
||||||
import { faICursor, faPlus, faMagic, faCog, faCode, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faICursor, faPlus, faMagic, faCog, faCode, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faSave, faStickyNote, faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
import { faSave, faStickyNote, faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
@ -98,16 +100,17 @@ import MkButton from '../../components/ui/button.vue';
|
|||||||
import MkSelect from '../../components/ui/select.vue';
|
import MkSelect from '../../components/ui/select.vue';
|
||||||
import MkSwitch from '../../components/ui/switch.vue';
|
import MkSwitch from '../../components/ui/switch.vue';
|
||||||
import MkInput from '../../components/ui/input.vue';
|
import MkInput from '../../components/ui/input.vue';
|
||||||
import { blockDefs } from '../../scripts/aiscript/index';
|
import { blockDefs } from '../../scripts/aoiscript/index';
|
||||||
import { ASTypeChecker } from '../../scripts/aiscript/type-checker';
|
import { ASTypeChecker } from '../../scripts/aoiscript/type-checker';
|
||||||
import { url } from '../../config';
|
import { url } from '../../config';
|
||||||
import { collectPageVars } from '../../scripts/collect-page-vars';
|
import { collectPageVars } from '../../scripts/collect-page-vars';
|
||||||
|
import { selectDriveFile } from '../../scripts/select-drive-file';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
XDraggable, XVariable, XBlocks, MkTextarea, MkContainer, MkButton, MkSelect, MkSwitch, MkInput
|
XDraggable, XVariable, XBlocks, MkTextarea, MkContainer, MkButton, MkSelect, MkSwitch, MkInput, PrismEditor
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -142,7 +145,8 @@ export default Vue.extend({
|
|||||||
alignCenter: false,
|
alignCenter: false,
|
||||||
hideTitleWhenPinned: false,
|
hideTitleWhenPinned: false,
|
||||||
variables: [],
|
variables: [],
|
||||||
aiScript: null,
|
aoiScript: null,
|
||||||
|
script: '',
|
||||||
showOptions: false,
|
showOptions: false,
|
||||||
url,
|
url,
|
||||||
faPlus, faICursor, faSave, faStickyNote, faMagic, faCog, faTrashAlt, faExternalLinkSquareAlt, faCode
|
faPlus, faICursor, faSave, faStickyNote, faMagic, faCog, faTrashAlt, faExternalLinkSquareAlt, faCode
|
||||||
@ -162,14 +166,14 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async created() {
|
async created() {
|
||||||
this.aiScript = new ASTypeChecker();
|
this.aoiScript = new ASTypeChecker();
|
||||||
|
|
||||||
this.$watch('variables', () => {
|
this.$watch('variables', () => {
|
||||||
this.aiScript.variables = this.variables;
|
this.aoiScript.variables = this.variables;
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
|
|
||||||
this.$watch('content', () => {
|
this.$watch('content', () => {
|
||||||
this.aiScript.pageVars = collectPageVars(this.content);
|
this.aoiScript.pageVars = collectPageVars(this.content);
|
||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
|
|
||||||
if (this.initPageId) {
|
if (this.initPageId) {
|
||||||
@ -192,6 +196,7 @@ export default Vue.extend({
|
|||||||
this.currentName = this.page.name;
|
this.currentName = this.page.name;
|
||||||
this.summary = this.page.summary;
|
this.summary = this.page.summary;
|
||||||
this.font = this.page.font;
|
this.font = this.page.font;
|
||||||
|
this.script = this.page.script;
|
||||||
this.hideTitleWhenPinned = this.page.hideTitleWhenPinned;
|
this.hideTitleWhenPinned = this.page.hideTitleWhenPinned;
|
||||||
this.alignCenter = this.page.alignCenter;
|
this.alignCenter = this.page.alignCenter;
|
||||||
this.content = this.page.content;
|
this.content = this.page.content;
|
||||||
@ -222,6 +227,7 @@ export default Vue.extend({
|
|||||||
name: this.name.trim(),
|
name: this.name.trim(),
|
||||||
summary: this.summary,
|
summary: this.summary,
|
||||||
font: this.font,
|
font: this.font,
|
||||||
|
script: this.script,
|
||||||
hideTitleWhenPinned: this.hideTitleWhenPinned,
|
hideTitleWhenPinned: this.hideTitleWhenPinned,
|
||||||
alignCenter: this.alignCenter,
|
alignCenter: this.alignCenter,
|
||||||
content: this.content,
|
content: this.content,
|
||||||
@ -316,7 +322,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
name = name.trim();
|
name = name.trim();
|
||||||
|
|
||||||
if (this.aiScript.isUsedName(name)) {
|
if (this.aoiScript.isUsedName(name)) {
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('_pages.variableNameIsAlreadyUsed')
|
text: this.$t('_pages.variableNameIsAlreadyUsed')
|
||||||
@ -345,6 +351,7 @@ export default Vue.extend({
|
|||||||
{ value: 'text', text: this.$t('_pages.blocks.text') },
|
{ value: 'text', text: this.$t('_pages.blocks.text') },
|
||||||
{ value: 'image', text: this.$t('_pages.blocks.image') },
|
{ value: 'image', text: this.$t('_pages.blocks.image') },
|
||||||
{ value: 'textarea', text: this.$t('_pages.blocks.textarea') },
|
{ value: 'textarea', text: this.$t('_pages.blocks.textarea') },
|
||||||
|
{ value: 'canvas', text: this.$t('_pages.blocks.canvas') },
|
||||||
]
|
]
|
||||||
}, {
|
}, {
|
||||||
label: this.$t('_pages.inputBlocks'),
|
label: this.$t('_pages.inputBlocks'),
|
||||||
@ -381,7 +388,7 @@ export default Vue.extend({
|
|||||||
} else {
|
} else {
|
||||||
list.push({
|
list.push({
|
||||||
category: block.category,
|
category: block.category,
|
||||||
label: this.$t(`script.categories.${block.category}`),
|
label: this.$t(`_pages.script.categories.${block.category}`),
|
||||||
items: [{
|
items: [{
|
||||||
value: block.type,
|
value: block.type,
|
||||||
text: this.$t(`_pages.script.blocks.${block.type}`)
|
text: this.$t(`_pages.script.blocks.${block.type}`)
|
||||||
@ -393,7 +400,7 @@ export default Vue.extend({
|
|||||||
const userFns = this.variables.filter(x => x.type === 'fn');
|
const userFns = this.variables.filter(x => x.type === 'fn');
|
||||||
if (userFns.length > 0) {
|
if (userFns.length > 0) {
|
||||||
list.unshift({
|
list.unshift({
|
||||||
label: this.$t(`script.categories.fn`),
|
label: this.$t(`_pages.script.categories.fn`),
|
||||||
items: userFns.map(v => ({
|
items: userFns.map(v => ({
|
||||||
value: 'fn:' + v.name,
|
value: 'fn:' + v.name,
|
||||||
text: v.name
|
text: v.name
|
||||||
@ -405,9 +412,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
setEyeCatchingImage() {
|
setEyeCatchingImage() {
|
||||||
this.$chooseDriveFile({
|
selectDriveFile(this.$root, false).then(file => {
|
||||||
multiple: false
|
|
||||||
}).then(file => {
|
|
||||||
this.eyeCatchingImageId = file.id;
|
this.eyeCatchingImageId = file.id;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -424,8 +429,6 @@ export default Vue.extend({
|
|||||||
margin-bottom: var(--margin);
|
margin-bottom: var(--margin);
|
||||||
|
|
||||||
> header {
|
> header {
|
||||||
background: var(--faceHeader);
|
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -433,8 +436,7 @@ export default Vue.extend({
|
|||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--faceHeaderText);
|
box-shadow: 0 1px rgba(#000, 0.07);
|
||||||
box-shadow: 0 var(--lineWidth) rgba(#000, 0.07);
|
|
||||||
|
|
||||||
> [data-icon] {
|
> [data-icon] {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
<div class="_card" v-if="page" :key="page.id">
|
<div class="_card" v-if="page" :key="page.id">
|
||||||
<div class="_title">{{ page.title }}</div>
|
<div class="_title">{{ page.title }}</div>
|
||||||
|
<div class="banner">
|
||||||
|
<img :src="page.eyeCatchingImage.url" v-if="page.eyeCatchingImageId"/>
|
||||||
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<x-page :page="page"/>
|
<x-page :page="page"/>
|
||||||
</div>
|
</div>
|
||||||
@ -115,6 +118,21 @@ export default Vue.extend({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.xcukqgmh {
|
.xcukqgmh {
|
||||||
|
> ._card {
|
||||||
|
> .banner {
|
||||||
|
> img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> ._footer {
|
||||||
|
> * {
|
||||||
|
margin: 0 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<portal to="icon"><fa :icon="faStickyNote"/></portal>
|
||||||
|
<portal to="title">{{ $t('pages') }}</portal>
|
||||||
|
|
||||||
<mk-container :body-togglable="true">
|
<mk-container :body-togglable="true">
|
||||||
<template #header><fa :icon="faEdit" fixed-width/>{{ $t('_pages.my') }}</template>
|
<template #header><fa :icon="faEdit" fixed-width/>{{ $t('_pages.my') }}</template>
|
||||||
<div class="rknalgpo my">
|
<div class="rknalgpo my">
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
<portal to="icon"><fa :icon="faCog"/></portal>
|
<portal to="icon"><fa :icon="faCog"/></portal>
|
||||||
<portal to="title">{{ $t('clinetSettings') }}</portal>
|
<portal to="title">{{ $t('clinetSettings') }}</portal>
|
||||||
|
|
||||||
|
<router-link v-if="$store.getters.isSignedIn" class="_panel _buttonPrimary" to="/my/settings" style="margin-bottom: var(--margin);">{{ $t('accountSettings') }}</router-link>
|
||||||
|
|
||||||
<x-theme/>
|
<x-theme/>
|
||||||
|
|
||||||
<section class="_card">
|
<section class="_card">
|
||||||
@ -63,6 +65,7 @@
|
|||||||
<template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template>
|
<template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template>
|
||||||
</mk-switch>
|
</mk-switch>
|
||||||
<mk-switch v-model="showFixedPostForm">{{ $t('showFixedPostForm') }}</mk-switch>
|
<mk-switch v-model="showFixedPostForm">{{ $t('showFixedPostForm') }}</mk-switch>
|
||||||
|
<mk-switch v-model="disablePagesScript">{{ $t('disablePagesScript') }}</mk-switch>
|
||||||
</div>
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<mk-select v-model="lang">
|
<mk-select v-model="lang">
|
||||||
@ -169,6 +172,11 @@ export default Vue.extend({
|
|||||||
set(value) { this.$store.commit('device/set', { key: 'imageNewTab', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'imageNewTab', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
disablePagesScript: {
|
||||||
|
get() { return this.$store.state.device.disablePagesScript; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'disablePagesScript', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
showFixedPostForm: {
|
showFixedPostForm: {
|
||||||
get() { return this.$store.state.device.showFixedPostForm; },
|
get() { return this.$store.state.device.showFixedPostForm; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); }
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</mk-select>
|
</mk-select>
|
||||||
|
<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<mk-switch v-model="syncDeviceDarkMode">{{ $t('syncDeviceDarkMode') }}</mk-switch>
|
<mk-switch v-model="syncDeviceDarkMode">{{ $t('syncDeviceDarkMode') }}</mk-switch>
|
||||||
@ -50,18 +51,44 @@
|
|||||||
<mk-button primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</mk-button>
|
<mk-button primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</mk-button>
|
||||||
<mk-button primary v-else @click="wallpaper = null">{{ $t('removeWallpaper') }}</mk-button>
|
<mk-button primary v-else @click="wallpaper = null">{{ $t('removeWallpaper') }}</mk-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<details>
|
||||||
|
<summary><fa :icon="faDownload"/> {{ $t('_theme.install') }}</summary>
|
||||||
|
<mk-textarea v-model="installThemeCode">
|
||||||
|
<span>{{ $t('_theme.code') }}</span>
|
||||||
|
</mk-textarea>
|
||||||
|
<mk-button @click="() => install(this.installThemeCode)" :disabled="installThemeCode == null" primary inline><fa :icon="faCheck"/> {{ $t('install') }}</mk-button>
|
||||||
|
<mk-button @click="() => preview(this.installThemeCode)" :disabled="installThemeCode == null" inline><fa :icon="faEye"/> {{ $t('preview') }}</mk-button>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<details>
|
||||||
|
<summary><fa :icon="faFolderOpen"/> {{ $t('_theme.manage') }}</summary>
|
||||||
|
<mk-select v-model="selectedThemeId">
|
||||||
|
<option v-for="x in installedThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</mk-select>
|
||||||
|
<template v-if="selectedTheme">
|
||||||
|
<mk-textarea readonly tall :value="selectedThemeCode">
|
||||||
|
<span>{{ $t('_theme.code') }}</span>
|
||||||
|
</mk-textarea>
|
||||||
|
<mk-button @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><fa :icon="faTrashAlt"/> {{ $t('uninstall') }}</mk-button>
|
||||||
|
</template>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { faPalette } from '@fortawesome/free-solid-svg-icons';
|
import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as JSON5 from 'json5';
|
||||||
import MkInput from '../../components/ui/input.vue';
|
import MkInput from '../../components/ui/input.vue';
|
||||||
import MkButton from '../../components/ui/button.vue';
|
import MkButton from '../../components/ui/button.vue';
|
||||||
import MkSelect from '../../components/ui/select.vue';
|
import MkSelect from '../../components/ui/select.vue';
|
||||||
import MkSwitch from '../../components/ui/switch.vue';
|
import MkSwitch from '../../components/ui/switch.vue';
|
||||||
|
import MkTextarea from '../../components/ui/textarea.vue';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import { Theme, builtinThemes, applyTheme } from '../../theme';
|
import { Theme, builtinThemes, applyTheme, validateTheme } from '../../theme';
|
||||||
import { selectFile } from '../../scripts/select-file';
|
import { selectFile } from '../../scripts/select-file';
|
||||||
import { isDeviceDarkmode } from '../../scripts/is-device-darkmode';
|
import { isDeviceDarkmode } from '../../scripts/is-device-darkmode';
|
||||||
|
|
||||||
@ -73,12 +100,16 @@ export default Vue.extend({
|
|||||||
MkButton,
|
MkButton,
|
||||||
MkSelect,
|
MkSelect,
|
||||||
MkSwitch,
|
MkSwitch,
|
||||||
|
MkTextarea,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
builtinThemes,
|
||||||
|
installThemeCode: null,
|
||||||
|
selectedThemeId: null,
|
||||||
wallpaper: localStorage.getItem('wallpaper'),
|
wallpaper: localStorage.getItem('wallpaper'),
|
||||||
faPalette
|
faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -118,6 +149,16 @@ export default Vue.extend({
|
|||||||
get() { return this.$store.state.device.syncDeviceDarkMode; },
|
get() { return this.$store.state.device.syncDeviceDarkMode; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'syncDeviceDarkMode', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'syncDeviceDarkMode', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
selectedTheme() {
|
||||||
|
if (this.selectedThemeId == null) return null;
|
||||||
|
return this.themes.find(x => x.id === this.selectedThemeId);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedThemeCode() {
|
||||||
|
if (this.selectedTheme == null) return null;
|
||||||
|
return JSON5.stringify(this.selectedTheme, null, '\t');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -155,6 +196,66 @@ export default Vue.extend({
|
|||||||
this.wallpaper = file.url;
|
this.wallpaper = file.url;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parseThemeCode(code) {
|
||||||
|
let theme;
|
||||||
|
|
||||||
|
try {
|
||||||
|
theme = JSON5.parse(code);
|
||||||
|
} catch (e) {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: this.$t('_theme.invalid')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!validateTheme(theme)) {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: this.$t('_theme.invalid')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.$store.state.device.themes.some(t => t.id === theme.id)) {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'info',
|
||||||
|
text: this.$t('_theme.alreadyInstalled')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return theme;
|
||||||
|
},
|
||||||
|
|
||||||
|
preview(code) {
|
||||||
|
const theme = this.parseThemeCode(code);
|
||||||
|
if (theme) applyTheme(theme, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
install(code) {
|
||||||
|
const theme = this.parseThemeCode(code);
|
||||||
|
if (!theme) return;
|
||||||
|
const themes = this.$store.state.device.themes.concat(theme);
|
||||||
|
this.$store.commit('device/set', {
|
||||||
|
key: 'themes', value: themes
|
||||||
|
});
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
text: this.$t('_theme.installed', { name: theme.name })
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
uninstall() {
|
||||||
|
const theme = this.selectedTheme;
|
||||||
|
const themes = this.$store.state.device.themes.filter(t => t.id != theme.id);
|
||||||
|
this.$store.commit('device/set', {
|
||||||
|
key: 'themes', value: themes
|
||||||
|
});
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'info',
|
||||||
|
iconOnly: true, autoClose: true
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -179,7 +280,7 @@ export default Vue.extend({
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0 200px;
|
padding: 0 100px;
|
||||||
transform: translate3d(-50%, -50%, 0);
|
transform: translate3d(-50%, -50%, 0);
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
140
src/client/pages/scratchpad.vue
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<div class="">
|
||||||
|
<portal to="icon"><fa :icon="faTerminal"/></portal>
|
||||||
|
<portal to="title">{{ $t('scratchpad') }}</portal>
|
||||||
|
|
||||||
|
<div class="_panel">
|
||||||
|
<prism-editor v-model="code" :line-numbers="false" language="js"/>
|
||||||
|
<mk-button style="position: absolute; top: 8px; right: 8px;" @click="run()" primary><fa :icon="faPlay"/></mk-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<mk-container :body-togglable="true">
|
||||||
|
<template #header><fa fixed-width/>{{ $t('output') }}</template>
|
||||||
|
<div class="bepmlvbi">
|
||||||
|
<div v-for="log in logs" class="log" :key="log.id" :class="{ print: log.print }">{{ log.text }}</div>
|
||||||
|
</div>
|
||||||
|
</mk-container>
|
||||||
|
|
||||||
|
<section class="_card" style="margin-top: var(--margin);">
|
||||||
|
<div class="_content">{{ $t('scratchpadDescription') }}</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { faTerminal, faPlay } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import "prismjs";
|
||||||
|
import 'prismjs/themes/prism-okaidia.css';
|
||||||
|
import PrismEditor from 'vue-prism-editor';
|
||||||
|
import { AiScript, parse, utils, values } from '@syuilo/aiscript';
|
||||||
|
import i18n from '../i18n';
|
||||||
|
import MkContainer from '../components/ui/container.vue';
|
||||||
|
import MkButton from '../components/ui/button.vue';
|
||||||
|
import { createAiScriptEnv } from '../scripts/create-aiscript-env';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n,
|
||||||
|
|
||||||
|
metaInfo() {
|
||||||
|
return {
|
||||||
|
title: this.$t('scratchpad') as string
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
MkContainer,
|
||||||
|
MkButton,
|
||||||
|
PrismEditor,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
code: '',
|
||||||
|
logs: [],
|
||||||
|
faTerminal, faPlay
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
code() {
|
||||||
|
localStorage.setItem('scratchpad', this.code);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
const saved = localStorage.getItem('scratchpad');
|
||||||
|
if (saved) {
|
||||||
|
this.code = saved;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async run() {
|
||||||
|
this.logs = [];
|
||||||
|
const aiscript = new AiScript(createAiScriptEnv(this, {
|
||||||
|
storageKey: 'scratchpad'
|
||||||
|
}), {
|
||||||
|
in: (q) => {
|
||||||
|
return new Promise(ok => {
|
||||||
|
this.$root.dialog({
|
||||||
|
title: q,
|
||||||
|
input: {}
|
||||||
|
}).then(({ canceled, result: a }) => {
|
||||||
|
ok(a);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
out: (value) => {
|
||||||
|
this.logs.push({
|
||||||
|
id: Math.random(),
|
||||||
|
text: value.type === 'str' ? value.value : utils.valToString(value),
|
||||||
|
print: true
|
||||||
|
});
|
||||||
|
},
|
||||||
|
log: (type, params) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'end': this.logs.push({
|
||||||
|
id: Math.random(),
|
||||||
|
text: utils.valToString(params.val, true),
|
||||||
|
print: false
|
||||||
|
}); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let ast;
|
||||||
|
try {
|
||||||
|
ast = parse(this.code);
|
||||||
|
} catch (e) {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: 'Syntax error :('
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await aiscript.exec(ast);
|
||||||
|
} catch (e) {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bepmlvbi {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
> .log {
|
||||||
|
&:not(.print) {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -8,7 +8,7 @@
|
|||||||
:href="image.note | notePage"
|
:href="image.note | notePage"
|
||||||
></a>
|
></a>
|
||||||
</div>
|
</div>
|
||||||
<p class="empty" v-if="!fetching && images.length == 0">{{ $t('no-photos') }}</p>
|
<p class="empty" v-if="!fetching && images.length == 0">{{ $t('nothing') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|