Compare commits

..

180 Commits

Author SHA1 Message Date
f00ceedae4 Merge branch 'develop' 2021-08-21 17:59:29 +09:00
7387e010c2 12.89.0 2021-08-21 17:59:13 +09:00
a59dfff12f New Crowdin updates (#7646)
* New translations mute-and-block.md (Ukrainian)

* New translations mute-and-block.md (Czech)

* New translations mute-and-block.md (Danish)

* New translations mute-and-block.md (German)

* New translations mute-and-block.md (Italian)

* New translations mute-and-block.md (Korean)

* New translations mute-and-block.md (Dutch)

* New translations mute-and-block.md (Norwegian)

* New translations mute-and-block.md (Polish)

* New translations mute-and-block.md (Portuguese)

* New translations mute-and-block.md (Russian)

* New translations mute-and-block.md (Chinese Simplified)

* New translations mute-and-block.md (Spanish)

* New translations mute-and-block.md (Chinese Traditional)

* New translations mute-and-block.md (English)

* New translations mute-and-block.md (Indonesian)

* New translations mute-and-block.md (Thai)

* New translations mute-and-block.md (Esperanto)

* New translations mute-and-block.md (Uyghur)

* New translations mute-and-block.md (Lojban)

* New translations mute-and-block.md (Kannada)

* New translations mute-and-block.md (Haitian Creole)

* New translations mute-and-block.md (Kabyle)

* New translations mute-and-block.md (Arabic)

* New translations mute-and-block.md (French)

* New translations mute-and-block.md (Japanese, Kansai)

* New translations glossary.md (German)

* New translations links.md (German)

* New translations links.md (English)

* New translations report-issue.md (German)

* New translations changelog.md (German)

* New translations apps.md (German)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations disable-timelines.md (Japanese, Kansai)

* New translations disable-timelines.md (Japanese, Kansai)

* New translations faq.md (Japanese, Kansai)

* New translations aiscript.md (Japanese, Kansai)

* New translations faq.md (Japanese, Kansai)

* New translations misskey.md (Japanese, Kansai)

* New translations aiscript.md (Japanese, Kansai)

* New translations reaction.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations glossary.md (Japanese, Kansai)

* New translations glossary.md (Kabyle)

* New translations glossary.md (Haitian Creole)

* New translations glossary.md (Kannada)

* New translations glossary.md (Lojban)

* New translations glossary.md (Uyghur)

* New translations glossary.md (Esperanto)

* New translations glossary.md (Indonesian)

* New translations misskey.md (English)

* New translations glossary.md (Thai)

* New translations glossary.md (English)

* New translations glossary.md (Chinese Traditional)

* New translations glossary.md (Dutch)

* New translations glossary.md (Chinese Simplified)

* New translations glossary.md (Ukrainian)

* New translations glossary.md (Russian)

* New translations glossary.md (Portuguese)

* New translations glossary.md (Polish)

* New translations glossary.md (Norwegian)

* New translations glossary.md (Korean)

* New translations glossary.md (French)

* New translations glossary.md (Italian)

* New translations glossary.md (German)

* New translations glossary.md (Danish)

* New translations glossary.md (Czech)

* New translations glossary.md (Arabic)

* New translations glossary.md (Spanish)

* New translations note.md (French)

* New translations glossary.md (Chinese Simplified)

* New translations faq.md (French)

* New translations faq.md (Chinese Simplified)

* New translations faq.md (Kabyle)

* New translations faq.md (Haitian Creole)

* New translations faq.md (Kannada)

* New translations faq.md (Lojban)

* New translations faq.md (Uyghur)

* New translations faq.md (Esperanto)

* New translations faq.md (Thai)

* New translations faq.md (Indonesian)

* New translations faq.md (English)

* New translations faq.md (Chinese Traditional)

* New translations faq.md (Ukrainian)

* New translations faq.md (Spanish)

* New translations faq.md (Russian)

* New translations faq.md (Portuguese)

* New translations faq.md (Polish)

* New translations faq.md (Norwegian)

* New translations faq.md (Dutch)

* New translations faq.md (Korean)

* New translations faq.md (Italian)

* New translations faq.md (German)

* New translations faq.md (Danish)

* New translations faq.md (Czech)

* New translations faq.md (Arabic)

* New translations faq.md (Japanese, Kansai)

* New translations faq.md (French)

* New translations misskey.md (French)

* New translations faq.md (French)

* New translations misskey.md (French)

* New translations faq.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (French)

* New translations word-mute.md (Ukrainian)

* New translations word-mute.md (Czech)

* New translations word-mute.md (Danish)

* New translations word-mute.md (German)

* New translations word-mute.md (Italian)

* New translations word-mute.md (Korean)

* New translations word-mute.md (Dutch)

* New translations word-mute.md (Norwegian)

* New translations word-mute.md (Polish)

* New translations word-mute.md (Portuguese)

* New translations word-mute.md (Russian)

* New translations word-mute.md (Chinese Simplified)

* New translations word-mute.md (Spanish)

* New translations word-mute.md (Chinese Traditional)

* New translations word-mute.md (English)

* New translations word-mute.md (Indonesian)

* New translations word-mute.md (Thai)

* New translations word-mute.md (Esperanto)

* New translations word-mute.md (Uyghur)

* New translations word-mute.md (Lojban)

* New translations word-mute.md (Kannada)

* New translations word-mute.md (Haitian Creole)

* New translations word-mute.md (Kabyle)

* New translations word-mute.md (Arabic)

* New translations word-mute.md (French)

* New translations word-mute.md (Japanese, Kansai)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations faq.md (English)

* New translations faq.md (English)

* New translations glossary.md (English)

* New translations word-mute.md (English)

* New translations word-mute.md (English)

* New translations word-mute.md (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)
2021-08-21 17:58:32 +09:00
f6128dd3ff 🎨 2021-08-21 17:40:15 +09:00
eeff88ece2 Update CHANGELOG.md 2021-08-21 14:52:41 +09:00
bae1282f74 clean up 2021-08-21 14:47:39 +09:00
d2007add75 feat: Implement api sw/unregister (#7611)
* Implement api sw/unregister

* remove all mode

* add changelog

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-08-21 14:47:18 +09:00
802db92d98 Update setup.en.md (#7675)
Updated PostgreSQL version to 12  

See https://github.com/misskey-dev/misskey/issues/7632#issuecomment-901653826
2021-08-21 14:24:03 +09:00
a53e1e4ec3 enhance: Improve account deletion experience 2021-08-21 12:48:50 +09:00
fd1ef4a62d enhance(server): Use job queue for account delete (#7668)
* enhance(server): Use job queue for account delete

Fix #5336

* ジョブをひとつに

* remove done call

* clean up

* add User.isDeleted

* コミット忘れ

* Update 1629512953000-user-is-deleted.ts

* show dialog

* lint

* Update 1629512953000-user-is-deleted.ts
2021-08-21 12:41:56 +09:00
8ab9068d8e fix bug 2021-08-21 11:51:46 +09:00
47dd30d3b2 fix(client): ノートの「削除して編集」をするとアンケートの選択肢が[object Object]になる問題を修正
Fix #7037
2021-08-21 11:16:56 +09:00
fcdd042b02 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-08-21 10:29:30 +09:00
04855f9201 enhance(client): Improve emoji autocomplete behaviour
cherry picked from 4b2c215e25
2021-08-21 10:29:26 +09:00
cf0a5d5735 Bump @redocly/openapi-core from 1.0.0-beta.44 to 1.0.0-beta.54 (#7665)
Bumps [@redocly/openapi-core](https://github.com/Redocly/openapi-cli) from 1.0.0-beta.44 to 1.0.0-beta.54.
- [Release notes](https://github.com/Redocly/openapi-cli/releases)
- [Changelog](https://github.com/Redocly/openapi-cli/blob/master/docs/changelog.md)
- [Commits](https://github.com/Redocly/openapi-cli/compare/v1.0.0-beta.44...v1.0.0-beta.54)

---
updated-dependencies:
- dependency-name: "@redocly/openapi-core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-20 23:15:17 +09:00
bb2db1cf76 perf: Tune AP job queue timings (#7635)
* perf: Tune AP job queue timings

* CHANGELOG

* chore: add reference

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-08-20 21:59:03 +09:00
0e69091455 doc: add features/word-mute (#7672) 2021-08-20 21:40:45 +09:00
3cb5ed167a fix: meta.jsonをimportしないように
Fix #7671
2021-08-20 21:34:56 +09:00
1ffee15b83 fix: use correct query generate function (#7657)
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-08-20 20:55:12 +09:00
75b9f31acf fix: import syslog-pro 2021-08-20 20:18:24 +09:00
fc56b12690 refactor: localStorageのaccountsはindexedDBで保持するように (#7609)
* accountsストアはindexedDBで保持するように

* fix lint

* fix indexeddb available detection

* remove debugging code

* fix lint

* resolve ba756204b7 (diff-f565878e8202f0037b830c780b7c0932dc1bb5fd3d05ede14d72d10efbc3740c)
Firefoxでの動作を改善

* fix lint

* fix lint

* add changelog
2021-08-20 19:38:16 +09:00
60e768436e Create dependabot.yml 2021-08-20 00:22:29 +09:00
84f2192cde update deps 2021-08-19 22:40:39 +09:00
97f2675d40 refactor: use path alias to improve readability 2021-08-19 22:04:15 +09:00
6d881d4570 fix import 2021-08-19 21:57:36 +09:00
42cc93dd0f fix: mochaが動かないため拡張子なしに戻した 2021-08-19 21:55:45 +09:00
e9f34a0f09 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-08-19 18:33:59 +09:00
b9cb6d1c10 refactor: refactoring imports
将来ESMに移行しやすいように
Related: #7658

なんかmochaが起動しなくなってるけど理由不明
すぐ直したい
2021-08-19 18:33:41 +09:00
7bf517e990 Remove unused packages (#7661)
* Remove unused packages

* Remove unused babel things

* Remove more unused packages
2021-08-19 18:07:32 +09:00
ab54e147f2 Remove is-root dependencies (#7660) 2021-08-19 16:27:12 +09:00
e677540fd6 Update faq.md 2021-08-19 15:42:53 +09:00
31e3aaeda0 Update glossary.md 2021-08-19 11:35:42 +09:00
938fc317c9 Update glossary.md 2021-08-19 11:32:25 +09:00
4c431c5432 refactor 2021-08-19 11:26:26 +09:00
881b914c6a チャンネルを作成しているとアカウントを削除できないのを修正 (#7653)
* チャンネルを作成しているとアカウントを削除できないのを修正

* CHANGELOG

* nullable
2021-08-18 22:04:04 +09:00
df67836c1a Merge branch 'develop' 2021-08-17 22:01:46 +09:00
6a3a8ba4d0 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-08-17 22:01:12 +09:00
9e535c341e 12.88.0 2021-08-17 22:00:52 +09:00
17fa4ba804 update vue 2021-08-17 22:00:39 +09:00
dd9a3c91fc New Crowdin updates (#7622)
* New translations create-plugin.md (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations glossary.md (Esperanto)

* New translations glossary.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations glossary.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations misskey.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations glossary.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations keyboard-shortcut.md (Esperanto)

* New translations timeline.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations keyboard-shortcut.md (Esperanto)

* New translations timeline.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations disable-timelines.md (Esperanto)

* New translations glossary.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations note.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Indonesian)

* New translations troubleshooting.md (Indonesian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (German)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations misskey.md (French)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations ja-JP.yml (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Simplified)

* New translations antenna.md (French)

* New translations antenna.md (French)

* New translations changelog.md (French)

* New translations report-issue.md (French)

* New translations changelog.md (French)

* New translations links.md (French)

* New translations report-issue.md (French)

* New translations links.md (French)

* New translations links.md (French)

* New translations links.md (French)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations links.md (French)

* New translations links.md (French)

* New translations apps.md (French)

* New translations links.md (French)

* New translations troubleshooting.md (French)

* New translations ja-JP.yml (French)

* New translations report-issue.md (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (French)

* New translations glossary.md (French)

* New translations misskey.md (Ukrainian)

* New translations misskey.md (Czech)

* New translations misskey.md (Danish)

* New translations misskey.md (German)

* New translations misskey.md (Italian)

* New translations misskey.md (Korean)

* New translations misskey.md (Dutch)

* New translations misskey.md (Norwegian)

* New translations misskey.md (Polish)

* New translations misskey.md (Portuguese)

* New translations misskey.md (Russian)

* New translations misskey.md (Chinese Simplified)

* New translations misskey.md (Spanish)

* New translations misskey.md (Chinese Traditional)

* New translations misskey.md (Indonesian)

* New translations misskey.md (Thai)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Uyghur)

* New translations misskey.md (Lojban)

* New translations misskey.md (Kannada)

* New translations misskey.md (Haitian Creole)

* New translations misskey.md (Kabyle)

* New translations misskey.md (Arabic)

* New translations misskey.md (French)

* New translations glossary.md (Spanish)

* New translations glossary.md (Russian)

* New translations glossary.md (Arabic)

* New translations glossary.md (Czech)

* New translations glossary.md (Danish)

* New translations glossary.md (German)

* New translations glossary.md (Italian)

* New translations glossary.md (Korean)

* New translations glossary.md (Dutch)

* New translations glossary.md (Norwegian)

* New translations glossary.md (Polish)

* New translations glossary.md (Portuguese)

* New translations glossary.md (Ukrainian)

* New translations glossary.md (Japanese, Kansai)

* New translations glossary.md (Chinese Simplified)

* New translations glossary.md (Chinese Traditional)

* New translations glossary.md (Indonesian)

* New translations glossary.md (Thai)

* New translations glossary.md (Uyghur)

* New translations glossary.md (Lojban)

* New translations glossary.md (Kannada)

* New translations glossary.md (Haitian Creole)

* New translations glossary.md (Kabyle)

* New translations misskey.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations note.md (Esperanto)

* New translations note.md (Esperanto)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Esperanto)

* New translations api.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations drive.md (Esperanto)

* New translations glossary.md (Esperanto)

* New translations report-issue.md (French)

* New translations troubleshooting.md (French)

* New translations faq.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations faq.md (Esperanto)

* New translations troubleshooting.md (French)

* New translations ja-JP.yml (Esperanto)

* New translations misskey.md (Esperanto)

* New translations troubleshooting.md (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations troubleshooting.md (French)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations misskey.md (Russian)

* New translations faq.md (French)

* New translations faq.md (Spanish)

* New translations faq.md (Russian)

* New translations faq.md (Arabic)

* New translations faq.md (Czech)

* New translations faq.md (Danish)

* New translations faq.md (German)

* New translations faq.md (Italian)

* New translations faq.md (Korean)

* New translations faq.md (Dutch)

* New translations faq.md (Norwegian)

* New translations faq.md (Polish)

* New translations faq.md (Portuguese)

* New translations faq.md (Ukrainian)

* New translations faq.md (Japanese, Kansai)

* New translations faq.md (Chinese Simplified)

* New translations faq.md (Chinese Traditional)

* New translations faq.md (English)

* New translations faq.md (Indonesian)

* New translations faq.md (Thai)

* New translations faq.md (Esperanto)

* New translations faq.md (Uyghur)

* New translations faq.md (Lojban)

* New translations faq.md (Kannada)

* New translations faq.md (Haitian Creole)

* New translations faq.md (Kabyle)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations antenna.md (Esperanto)

* New translations glossary.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations apps.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations deck.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations antenna.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations antenna.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations api.md (Esperanto)

* New translations custom-emoji.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations deck.md (Japanese, Kansai)

* New translations deck.md (Japanese, Kansai)

* New translations faq.md (French)

* New translations faq.md (English)

* New translations faq.md (English)

* New translations faq.md (English)

* New translations faq.md (English)

* New translations faq.md (French)

* New translations misskey.md (French)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations faq.md (English)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations faq.md (French)

* New translations faq.md (Chinese Simplified)
2021-08-17 21:51:23 +09:00
7015df37e3 enhance(server): Improve user block (#7640)
* enhance(server): Improve user block

* Update CHANGELOG.md

* ユーザーリスト対応

* 相手から見れなくなるように

* Update 1629004542760-chart-reindex.ts

2365761ba5 (commitcomment-54919821)

* update test

* add test

* add todos

* Update 1629004542760-chart-reindex.ts
2021-08-17 21:48:59 +09:00
7ebdd4739a Fix truncate (#7642) 2021-08-17 17:25:19 +09:00
c4bcb31a00 Update 1629004542760-chart-reindex.ts 2021-08-17 13:40:15 +09:00
0a18ee24ac Update 1629004542760-chart-reindex.ts
2365761ba5 (commitcomment-54919821)
2021-08-17 13:37:16 +09:00
37d10b108e Update faq.md 2021-08-17 11:52:27 +09:00
b5cadeca2e fix(client): コントロールパネルでファイルを削除した際の表示を修正
Fix #7631
2021-08-16 20:07:54 +09:00
c8e93054bc fix(client): タッチ操作でウィンドウを閉じることができない問題を修正 2021-08-16 18:11:15 +09:00
def32107af perf: Improve network request performance (#7636)
* perf: Improve fetch

* CHANGELOG

* lifo
2021-08-16 17:44:43 +09:00
1b84ae9f3f chore: yarn.lockがおかしかったらCIでコケるように (#7634) 2021-08-16 16:33:45 +09:00
73ce1f61a8 Tweak client style 2021-08-16 15:21:58 +09:00
8661cd1ee7 Renoteされた時刻が投稿された時刻のように表示される問題を修正
Fix #7620
2021-08-16 15:20:23 +09:00
53f55defda fix typo 2021-08-16 12:28:12 +09:00
d60dc60bc9 fix(server): use insert instead of save 2021-08-15 22:10:05 +09:00
bf1d7e6252 fix(server): ja-JPのような形式にDeepLが対応してない 2021-08-15 21:52:58 +09:00
c96b2767b9 fix typo 2021-08-15 21:44:00 +09:00
6c1f03eefd enhance(client): Improve stability of version comparison 2021-08-15 20:34:06 +09:00
cced83024b feat: ノートの翻訳機能
Resolve #5213
2021-08-15 20:26:44 +09:00
1cd6ba3c1d chore: Remove vips from Dockerfile (#7633) 2021-08-15 18:12:46 +09:00
2365761ba5 perf(server): Optimize db indexes of chart tables 2021-08-15 17:13:23 +09:00
d3b4b70bfc 🎨 2021-08-14 22:35:15 +09:00
f95d5701a2 feat(client): ジョブキューウィジェットに警報音を鳴らす設定を追加 2021-08-14 18:36:22 +09:00
a8c56afd0f add sound 2021-08-14 18:19:25 +09:00
4de30aa47e Update CHANGELOG.md 2021-08-14 18:13:41 +09:00
f05f7c920e fix: truncate user information if it is too long (#7629)
* truncate user information if it is too long

Some AP software allows for user names or summaries to be very long.
Misskey can not handle this and the profile page can not be opened and
no activities from such users can be seen.

Instead, the user name and summary are cut off after the maximum length
so misskey can still process the activities of the profile.

Co-authored-by: Toast <toast@toast.cafe>

* fix code style

Co-authored-by: Toast <toast@toast.cafe>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2021-08-14 18:11:47 +09:00
5f86509abc Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-08-13 17:59:57 +09:00
1561391293 feat(client): Misskey更新時にダイアログを表示するように 2021-08-13 17:59:54 +09:00
60553a8a5e Update PULL_REQUEST_TEMPLATE.md 2021-08-12 23:46:13 +09:00
e656074de4 Update PULL_REQUEST_TEMPLATE.md 2021-08-12 23:45:46 +09:00
b81ff340b1 Introduce e2e test 2021-08-12 19:05:07 +09:00
77456ae0bc Create config.yml 2021-08-12 15:44:16 +09:00
9fd0e90850 Merge branch 'develop' 2021-08-12 12:48:58 +09:00
ab01cf1881 12.87.0 2021-08-12 12:48:53 +09:00
0d10ca02db New Crowdin updates (#7619)
* New translations disable-timelines.md (Chinese Simplified)

* New translations api.md (Chinese Simplified)

* New translations api.md (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations api.md (Chinese Simplified)

* New translations api.md (Chinese Simplified)

* New translations api.md (Chinese Simplified)

* New translations create-plugin.md (Chinese Simplified)

* New translations stream.md (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations note.md (English)

* New translations links.md (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Russian)

* New translations troubleshooting.md (Russian)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Simplified)
2021-08-12 12:48:24 +09:00
0627df8116 improve(client): Improve emoji autocomplete 2021-08-12 12:41:57 +09:00
c88ea7150c fix(client): 更新時にテーマキャッシュをクリアするように 2021-08-12 12:02:41 +09:00
555954c71e Improve about-misskey page 2021-08-12 11:48:06 +09:00
f231f02329 Update vue-loader 2021-08-12 11:38:21 +09:00
b8af5dfde0 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2021-08-12 11:33:03 +09:00
ef3710fdc2 Update deps 2021-08-12 11:33:00 +09:00
bde114ad13 Update node 2021-08-12 11:28:51 +09:00
9d138aa282 Update CHANGELOG.md 2021-08-11 22:40:58 +09:00
42c4ea38cc Merge branch 'develop' 2021-08-11 22:36:59 +09:00
c0ba71c368 12.86.0 2021-08-11 22:36:51 +09:00
7b2cb30a9d New Crowdin updates (#7617)
* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations silence.md (Esperanto)

* New translations glossary.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations troubleshooting.md (French)

* New translations troubleshooting.md (Chinese Simplified)

* New translations troubleshooting.md (Kabyle)

* New translations troubleshooting.md (Haitian Creole)

* New translations troubleshooting.md (Kannada)

* New translations troubleshooting.md (Lojban)

* New translations troubleshooting.md (Uyghur)

* New translations troubleshooting.md (Esperanto)

* New translations troubleshooting.md (Thai)

* New translations troubleshooting.md (Indonesian)

* New translations troubleshooting.md (English)

* New translations troubleshooting.md (Chinese Traditional)

* New translations troubleshooting.md (Ukrainian)

* New translations troubleshooting.md (Spanish)

* New translations troubleshooting.md (Russian)

* New translations troubleshooting.md (Portuguese)

* New translations troubleshooting.md (Polish)

* New translations troubleshooting.md (Norwegian)

* New translations troubleshooting.md (Dutch)

* New translations troubleshooting.md (Korean)

* New translations troubleshooting.md (Italian)

* New translations troubleshooting.md (German)

* New translations troubleshooting.md (Danish)

* New translations troubleshooting.md (Czech)

* New translations troubleshooting.md (Arabic)

* New translations troubleshooting.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations theme.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations changelog.md (French)

* New translations changelog.md (Chinese Simplified)

* New translations changelog.md (Kabyle)

* New translations changelog.md (Haitian Creole)

* New translations changelog.md (Kannada)

* New translations changelog.md (Lojban)

* New translations changelog.md (Uyghur)

* New translations changelog.md (Esperanto)

* New translations changelog.md (Thai)

* New translations changelog.md (Indonesian)

* New translations changelog.md (English)

* New translations changelog.md (Chinese Traditional)

* New translations changelog.md (Ukrainian)

* New translations changelog.md (Spanish)

* New translations changelog.md (Russian)

* New translations changelog.md (Portuguese)

* New translations changelog.md (Polish)

* New translations changelog.md (Norwegian)

* New translations changelog.md (Dutch)

* New translations changelog.md (Korean)

* New translations changelog.md (Italian)

* New translations changelog.md (German)

* New translations changelog.md (Danish)

* New translations changelog.md (Czech)

* New translations changelog.md (Arabic)

* New translations changelog.md (Japanese, Kansai)

* New translations links.md (Ukrainian)

* New translations links.md (Czech)

* New translations links.md (Danish)

* New translations links.md (German)

* New translations links.md (Italian)

* New translations links.md (Korean)

* New translations links.md (Dutch)

* New translations links.md (Norwegian)

* New translations links.md (Polish)

* New translations links.md (Portuguese)

* New translations links.md (Russian)

* New translations links.md (Chinese Simplified)

* New translations links.md (Spanish)

* New translations links.md (Chinese Traditional)

* New translations links.md (English)

* New translations links.md (Indonesian)

* New translations links.md (Thai)

* New translations links.md (Esperanto)

* New translations links.md (Uyghur)

* New translations links.md (Lojban)

* New translations links.md (Kannada)

* New translations links.md (Haitian Creole)

* New translations links.md (Kabyle)

* New translations links.md (Arabic)

* New translations links.md (French)

* New translations ja-JP.yml (English)

* New translations links.md (Japanese, Kansai)

* New translations disable-timelines.md (English)

* New translations disable-timelines.md (English)

* New translations disable-timelines.md (English)

* New translations faq.md (English)

* New translations faq.md (English)

* New translations misskey.md (English)

* New translations ja-JP.yml (English)

* New translations faq.md (English)

* New translations apps.md (English)

* New translations apps.md (English)

* New translations faq.md (English)

* New translations misskey.md (English)

* New translations changelog.md (English)

* New translations faq.md (English)

* New translations misskey.md (English)

* New translations faq.md (English)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations glossary.md (English)

* New translations links.md (English)

* New translations links.md (English)

* New translations report-issue.md (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations antenna.md (English)

* New translations drive.md (English)

* New translations drive.md (English)

* New translations faq.md (English)

* New translations antenna.md (English)

* New translations drive.md (English)

* New translations favorite.md (English)

* New translations silence.md (English)

* New translations glossary.md (English)

* New translations silence.md (English)

* New translations widgets.md (English)

* New translations ja-JP.yml (English)

* New translations misskey.md (English)

* New translations faq.md (English)

* New translations antenna.md (English)

* New translations drive.md (English)

* New translations favorite.md (English)

* New translations glossary.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations troubleshooting.md (English)

* New translations troubleshooting.md (English)

* New translations troubleshooting.md (English)

* New translations troubleshooting.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations misskey.md (English)

* New translations ja-JP.yml (Chinese Simplified)

* New translations disable-timelines.md (Chinese Simplified)

* New translations links.md (Chinese Simplified)

* New translations note.md (English)

* New translations silence.md (English)

* New translations note.md (English)

* New translations note.md (English)

* New translations note.md (English)

* New translations note.md (English)

* New translations note.md (Ukrainian)

* New translations note.md (Czech)

* New translations note.md (Danish)

* New translations note.md (German)

* New translations note.md (Italian)

* New translations note.md (Korean)

* New translations note.md (Dutch)

* New translations note.md (Norwegian)

* New translations note.md (Polish)

* New translations note.md (Portuguese)

* New translations note.md (Russian)

* New translations note.md (Chinese Simplified)

* New translations note.md (Spanish)

* New translations note.md (Chinese Traditional)

* New translations note.md (English)

* New translations note.md (Indonesian)

* New translations note.md (Thai)

* New translations note.md (Esperanto)

* New translations note.md (Uyghur)

* New translations note.md (Lojban)

* New translations note.md (Kannada)

* New translations note.md (Haitian Creole)

* New translations note.md (Kabyle)

* New translations note.md (Arabic)

* New translations note.md (French)

* New translations note.md (Japanese, Kansai)

* New translations ja-JP.yml (Esperanto)

* New translations links.md (Ukrainian)

* New translations links.md (Kabyle)

* New translations links.md (Haitian Creole)

* New translations links.md (Kannada)

* New translations links.md (Lojban)

* New translations links.md (Uyghur)

* New translations links.md (Esperanto)

* New translations links.md (Thai)

* New translations links.md (Indonesian)

* New translations links.md (English)

* New translations links.md (Chinese Traditional)

* New translations links.md (Chinese Simplified)

* New translations links.md (Russian)

* New translations links.md (French)

* New translations links.md (Portuguese)

* New translations links.md (Polish)

* New translations links.md (Norwegian)

* New translations links.md (Dutch)

* New translations links.md (Korean)

* New translations links.md (Italian)

* New translations links.md (German)

* New translations links.md (Danish)

* New translations links.md (Czech)

* New translations links.md (Arabic)

* New translations links.md (Spanish)

* New translations links.md (Japanese, Kansai)

* New translations note.md (Esperanto)

* New translations disable-timelines.md (Chinese Simplified)
2021-08-11 22:36:36 +09:00
0f55e65701 ぼかし効果の切り替え機能 2021-08-11 22:34:45 +09:00
aeb24b96eb Add discord link 2021-08-11 21:13:17 +09:00
ad4700b3b1 Improve doc 2021-08-11 21:10:48 +09:00
b2e5ade5ac フォロー通知のEメール通知を修正 2021-08-11 21:08:05 +09:00
90a7b9b551 🎨 2021-08-11 21:05:26 +09:00
31b6ab9b23 fix chore error 2021-08-11 00:21:48 +09:00
4149c7782f 🎨 2021-08-11 00:21:24 +09:00
227f52d758 Improve docs 2021-08-10 19:51:56 +09:00
baa2a871f1 Update patrons list 2021-08-10 19:34:53 +09:00
5bb619fe7b Improve doc 2021-08-10 19:19:02 +09:00
fff3c552e2 perf(client): use function for render slot to improve performance
See: https://forum.vuejs.org/t/how-to-avoid-non-function-value-encountered-for-default-slot-warning/107039
2021-08-10 18:19:59 +09:00
e19cc8bebf ハッシュタグ入力が空のときに#が付くのを修正 2021-08-10 16:06:14 +09:00
f4f8debb92 🎨 2021-08-10 15:29:30 +09:00
ea6b8b599f Update html comment 2021-08-10 15:28:01 +09:00
c30f02ae4c Update vue to 3.2.1 2021-08-10 15:07:15 +09:00
09450ba544 Update troubleshooting.md 2021-08-09 22:35:22 +09:00
df53968306 Merge branch 'develop' 2021-08-09 21:47:52 +09:00
19f753c15c 12.85.1 2021-08-09 21:47:43 +09:00
df530bb66d Merge branch 'develop' 2021-08-09 21:47:23 +09:00
fa49427df0 🎨 2021-08-09 21:45:46 +09:00
6678d97cc4 🎨 2021-08-09 21:41:20 +09:00
e3642a8d10 🎨 2021-08-09 18:55:39 +09:00
f9022fdf16 🎨 2021-08-09 18:05:32 +09:00
1c764139bf 🎨 2021-08-09 18:01:12 +09:00
048ed26f41 連合インスタンス設定ダイアログ 2021-08-09 12:28:23 +09:00
c52e30e8e0 Merge branch 'develop' 2021-08-08 23:25:21 +09:00
0cb04ded36 12.85.0 2021-08-08 23:25:13 +09:00
6cfad65ac7 🎨 2021-08-08 21:59:18 +09:00
ed20805b10 New Crowdin updates (#7616)
* New translations troubleshooting.md (Indonesian)

* New translations troubleshooting.md (Chinese Traditional)

* New translations troubleshooting.md (German)

* New translations troubleshooting.md (Chinese Simplified)

* New translations troubleshooting.md (Ukrainian)

* New translations troubleshooting.md (Russian)

* New translations troubleshooting.md (Portuguese)

* New translations troubleshooting.md (Polish)

* New translations troubleshooting.md (Norwegian)

* New translations troubleshooting.md (Dutch)

* New translations troubleshooting.md (Korean)

* New translations troubleshooting.md (Italian)

* New translations report-issue.md (Korean)

* New translations report-issue.md (German)

* New translations links.md (Portuguese)

* New translations links.md (Kannada)

* New translations misskey.md (German)

* New translations misskey.md (Danish)

* New translations misskey.md (Czech)

* New translations misskey.md (Arabic)

* New translations misskey.md (Spanish)

* New translations misskey.md (French)

* New translations links.md (Japanese, Kansai)

* New translations links.md (Kabyle)

* New translations links.md (Haitian Creole)

* New translations links.md (Lojban)

* New translations misskey.md (Korean)

* New translations links.md (Uyghur)

* New translations links.md (Esperanto)

* New translations links.md (Thai)

* New translations links.md (Indonesian)

* New translations links.md (English)

* New translations links.md (Chinese Traditional)

* New translations links.md (Chinese Simplified)

* New translations links.md (Ukrainian)

* New translations links.md (Russian)

* New translations misskey.md (Italian)

* New translations misskey.md (Dutch)

* New translations report-issue.md (Danish)

* New translations misskey.md (Uyghur)

* New translations report-issue.md (Czech)

* New translations report-issue.md (Arabic)

* New translations report-issue.md (Spanish)

* New translations report-issue.md (French)

* New translations misskey.md (Japanese, Kansai)

* New translations misskey.md (Kabyle)

* New translations misskey.md (Haitian Creole)

* New translations misskey.md (Kannada)

* New translations misskey.md (Lojban)

* New translations misskey.md (Esperanto)

* New translations misskey.md (Norwegian)

* New translations misskey.md (Thai)

* New translations misskey.md (Indonesian)

* New translations misskey.md (English)

* New translations misskey.md (Chinese Traditional)

* New translations misskey.md (Chinese Simplified)

* New translations misskey.md (Ukrainian)

* New translations misskey.md (Russian)

* New translations misskey.md (Portuguese)

* New translations misskey.md (Polish)

* New translations widgets.md (Lojban)

* New translations reaction.md (Polish)

* New translations widgets.md (Esperanto)

* New translations pages.md (Esperanto)

* New translations reaction.md (Spanish)

* New translations reaction.md (French)

* New translations pages.md (Japanese, Kansai)

* New translations pages.md (Kabyle)

* New translations pages.md (Haitian Creole)

* New translations pages.md (Kannada)

* New translations pages.md (Lojban)

* New translations pages.md (Uyghur)

* New translations pages.md (Thai)

* New translations reaction.md (Czech)

* New translations pages.md (Indonesian)

* New translations pages.md (English)

* New translations pages.md (Chinese Traditional)

* New translations pages.md (Chinese Simplified)

* New translations pages.md (Ukrainian)

* New translations pages.md (Russian)

* New translations pages.md (Portuguese)

* New translations pages.md (Polish)

* New translations pages.md (Norwegian)

* New translations reaction.md (Arabic)

* New translations reaction.md (Danish)

* New translations pages.md (Korean)

* New translations reaction.md (Indonesian)

* New translations silence.md (French)

* New translations reaction.md (Japanese, Kansai)

* New translations reaction.md (Kabyle)

* New translations reaction.md (Haitian Creole)

* New translations reaction.md (Kannada)

* New translations reaction.md (Lojban)

* New translations reaction.md (Uyghur)

* New translations reaction.md (Esperanto)

* New translations reaction.md (Thai)

* New translations reaction.md (English)

* New translations reaction.md (German)

* New translations reaction.md (Chinese Traditional)

* New translations reaction.md (Chinese Simplified)

* New translations reaction.md (Ukrainian)

* New translations reaction.md (Russian)

* New translations reaction.md (Portuguese)

* New translations reaction.md (Norwegian)

* New translations reaction.md (Dutch)

* New translations reaction.md (Korean)

* New translations reaction.md (Italian)

* New translations pages.md (Dutch)

* New translations pages.md (Italian)

* New translations silence.md (Arabic)

* New translations mute.md (Kabyle)

* New translations note.md (Italian)

* New translations note.md (German)

* New translations note.md (Danish)

* New translations note.md (Czech)

* New translations note.md (Arabic)

* New translations note.md (Spanish)

* New translations note.md (French)

* New translations mute.md (Japanese, Kansai)

* New translations mute.md (Haitian Creole)

* New translations note.md (Dutch)

* New translations mute.md (Kannada)

* New translations mute.md (Lojban)

* New translations mute.md (Uyghur)

* New translations mute.md (Esperanto)

* New translations mute.md (Thai)

* New translations mute.md (Indonesian)

* New translations mute.md (English)

* New translations mute.md (Chinese Traditional)

* New translations mute.md (Chinese Simplified)

* New translations note.md (Korean)

* New translations note.md (Norwegian)

* New translations pages.md (German)

* New translations note.md (Lojban)

* New translations pages.md (Danish)

* New translations pages.md (Czech)

* New translations pages.md (Arabic)

* New translations pages.md (Spanish)

* New translations pages.md (French)

* New translations note.md (Japanese, Kansai)

* New translations note.md (Kabyle)

* New translations note.md (Haitian Creole)

* New translations note.md (Kannada)

* New translations note.md (Uyghur)

* New translations note.md (Polish)

* New translations note.md (Esperanto)

* New translations note.md (Thai)

* New translations note.md (Indonesian)

* New translations note.md (English)

* New translations note.md (Chinese Traditional)

* New translations note.md (Chinese Simplified)

* New translations note.md (Ukrainian)

* New translations note.md (Russian)

* New translations note.md (Portuguese)

* New translations silence.md (Spanish)

* New translations silence.md (Czech)

* New translations widgets.md (Thai)

* New translations timeline.md (Portuguese)

* New translations timeline.md (Esperanto)

* New translations timeline.md (Thai)

* New translations timeline.md (Indonesian)

* New translations timeline.md (English)

* New translations timeline.md (Chinese Traditional)

* New translations timeline.md (Chinese Simplified)

* New translations timeline.md (Ukrainian)

* New translations timeline.md (Russian)

* New translations timeline.md (Polish)

* New translations timeline.md (Lojban)

* New translations timeline.md (Norwegian)

* New translations timeline.md (Dutch)

* New translations timeline.md (Korean)

* New translations timeline.md (Italian)

* New translations timeline.md (German)

* New translations timeline.md (Danish)

* New translations timeline.md (Czech)

* New translations timeline.md (Arabic)

* New translations timeline.md (Spanish)

* New translations timeline.md (Uyghur)

* New translations timeline.md (Kannada)

* New translations theme.md (Japanese, Kansai)

* New translations widgets.md (Dutch)

* New translations widgets.md (Indonesian)

* New translations widgets.md (English)

* New translations widgets.md (Chinese Traditional)

* New translations widgets.md (Chinese Simplified)

* New translations widgets.md (Ukrainian)

* New translations widgets.md (Russian)

* New translations widgets.md (Portuguese)

* New translations widgets.md (Polish)

* New translations widgets.md (Norwegian)

* New translations widgets.md (Korean)

* New translations timeline.md (Haitian Creole)

* New translations widgets.md (Italian)

* New translations widgets.md (German)

* New translations widgets.md (Danish)

* New translations widgets.md (Czech)

* New translations widgets.md (Arabic)

* New translations widgets.md (Spanish)

* New translations widgets.md (French)

* New translations timeline.md (Japanese, Kansai)

* New translations timeline.md (Kabyle)

* New translations timeline.md (French)

* New translations theme.md (Kabyle)

* New translations silence.md (Danish)

* New translations silence.md (Chinese Traditional)

* New translations silence.md (Kabyle)

* New translations silence.md (Haitian Creole)

* New translations silence.md (Kannada)

* New translations silence.md (Lojban)

* New translations silence.md (Uyghur)

* New translations silence.md (Esperanto)

* New translations silence.md (Thai)

* New translations silence.md (Indonesian)

* New translations silence.md (English)

* New translations silence.md (Chinese Simplified)

* New translations theme.md (French)

* New translations silence.md (Ukrainian)

* New translations silence.md (Russian)

* New translations silence.md (Portuguese)

* New translations silence.md (Polish)

* New translations silence.md (Norwegian)

* New translations silence.md (Dutch)

* New translations silence.md (Korean)

* New translations silence.md (Italian)

* New translations silence.md (German)

* New translations silence.md (Japanese, Kansai)

* New translations theme.md (Spanish)

* New translations theme.md (Haitian Creole)

* New translations theme.md (Ukrainian)

* New translations theme.md (Kannada)

* New translations theme.md (Lojban)

* New translations theme.md (Uyghur)

* New translations theme.md (Esperanto)

* New translations theme.md (Thai)

* New translations theme.md (Indonesian)

* New translations theme.md (English)

* New translations theme.md (Chinese Traditional)

* New translations theme.md (Chinese Simplified)

* New translations theme.md (Russian)

* New translations theme.md (Arabic)

* New translations theme.md (Portuguese)

* New translations theme.md (Polish)

* New translations theme.md (Norwegian)

* New translations theme.md (Dutch)

* New translations theme.md (Korean)

* New translations theme.md (Italian)

* New translations theme.md (German)

* New translations theme.md (Danish)

* New translations theme.md (Czech)

* New translations troubleshooting.md (Japanese, Kansai)
2021-08-08 21:39:45 +09:00
576303cd72 Update crowdin.yml 2021-08-08 18:57:07 +09:00
0062e084f8 New Crowdin updates (#7614)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Japanese, Kansai)
2021-08-08 18:55:15 +09:00
b90d76dcfe Update links.md 2021-08-08 18:47:57 +09:00
c95619b2bf Update ja-JP.yml 2021-08-08 17:23:16 +09:00
82150bd5b8 🎨 2021-08-08 16:30:30 +09:00
9e03335ff8 Improve client 2021-08-08 13:02:58 +09:00
b3c5c3f0ea Improve usability 2021-08-08 12:45:44 +09:00
65858dab3e Improve client 2021-08-08 12:19:10 +09:00
c968633d15 Update misskey.md 2021-08-07 23:43:42 +09:00
39a8942daf 🎨 2021-08-07 22:06:50 +09:00
7705a7928e fix bug that docs not loading 2021-08-07 20:39:27 +09:00
d2c14b844e New Crowdin updates (#7610)
* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations mute.md (Esperanto)

* New translations stream.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations keyboard-shortcut.md (Esperanto)

* New translations timelines.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations follow.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations custom-emoji.md (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Esperanto)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)
2021-08-07 19:25:54 +09:00
3e45e6c165 Clean up 2021-08-07 19:21:17 +09:00
fe8334931f user page 🎨 2021-08-07 19:19:43 +09:00
f565c5f730 Improve chat UI (wip) 2021-08-07 19:19:31 +09:00
c03e2febb0 🎨 2021-08-07 19:09:06 +09:00
c2f4fb7ba7 Update troubleshooting.md 2021-08-07 18:10:33 +09:00
5f869e5d87 Improve client 2021-08-07 17:55:16 +09:00
65f1afc4e0 Improve docs 2021-08-07 16:54:51 +09:00
aec2762bf1 🎨 2021-08-07 16:12:42 +09:00
a41144a00f Improve docs 2021-08-07 15:13:38 +09:00
aa28e8a7a6 Update stream.md 2021-08-07 14:42:51 +09:00
a1a51ce518 Improve docs 2021-08-07 14:05:12 +09:00
90999e0ef9 Improve docs 2021-08-07 13:56:18 +09:00
2ceeb17056 Add doc for admin 2021-08-07 13:41:14 +09:00
18afdd6040 Improve docs 2021-08-07 13:35:18 +09:00
b9972ec6bd 🎨 2021-08-07 13:19:00 +09:00
ebb53e87f3 ハッシュタグ入力エリア
Resolve #7600
2021-08-07 12:47:01 +09:00
9f9d7325fd インスタンス一覧ページ 2021-08-07 10:24:50 +09:00
742a005523 カスタム絵文字一覧ページ 2021-08-07 10:23:59 +09:00
3a28c06534 🎨 2021-08-06 22:47:26 +09:00
46d5711071 🎨 2021-08-06 22:29:19 +09:00
48113f3afd Improve doc 2021-08-06 14:28:40 +09:00
be29972ddf Update doc.vue 2021-08-06 13:55:26 +09:00
49b3a83f76 Improve docs 2021-08-06 11:04:17 +09:00
342794c728 Update mfm.md 2021-08-06 10:49:04 +09:00
3739638c81 Improve docs 2021-08-06 03:28:47 +09:00
401351d9c8 Improve docs 2021-08-06 02:38:45 +09:00
6073a03967 Improve docs 2021-08-06 00:33:25 +09:00
3e3d294188 Improve docs 2021-08-06 00:17:40 +09:00
f6f96ae5bf Imorive client 2021-08-05 22:43:14 +09:00
62ccb53c24 Add rainbow function for MFM 2021-08-05 21:55:41 +09:00
e410e22980 Update misskey.md 2021-08-05 18:46:43 +09:00
fc5ceea335 Improve doc 2021-08-05 18:34:59 +09:00
38af8d4737 Update glossary.md 2021-08-05 16:34:24 +09:00
33b0cab596 refactor 2021-08-05 16:34:18 +09:00
2a47e4a1e1 Update misskey.md 2021-08-05 16:29:34 +09:00
46f53868c5 Improve docs 2021-08-05 16:04:31 +09:00
eac7f11aa7 Update glossary.md 2021-08-05 15:48:12 +09:00
e219188f46 Update misskey.md 2021-08-05 15:38:20 +09:00
3df8c701a7 Improve docs 2021-08-05 15:19:55 +09:00
1186813c75 Update glossary.md 2021-08-05 15:08:10 +09:00
645b6fdc8a Improve docs 2021-08-05 13:58:44 +09:00
ae0596a729 improve docs 2021-08-05 13:43:57 +09:00
bb5fd3c1f2 Update misskey.md 2021-08-05 13:02:44 +09:00
532fa9c5f9 🎨 2021-08-05 12:20:27 +09:00
80a4aa6fa6 Update misskey.md 2021-08-05 12:20:21 +09:00
4f218f544f Update misskey.md 2021-08-05 12:14:14 +09:00
f261f8d7d1 Update misskey.md 2021-08-05 10:45:19 +09:00
e044d11782 Improve docs 2021-08-05 00:15:51 +09:00
d2da459dd8 refactor 2021-08-01 14:45:40 +09:00
b1e6a33d6b tweak style 2021-07-29 23:59:45 +09:00
0d276d0d61 Improve usability 2021-07-29 17:10:16 +09:00
998936651a fix style 2021-07-28 14:46:25 +09:00
1bec25e8e6 パスワードリセットしても新しいパスワードが表示されない問題を修正 2021-07-28 14:45:56 +09:00
f220e4183f 🎨 2021-07-27 21:37:32 +09:00
e965b57dc2 Update PULL_REQUEST_TEMPLATE.md 2021-07-27 00:01:21 +09:00
1737 changed files with 44035 additions and 5949 deletions

View File

@ -1,13 +0,0 @@
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": {
"version": 3,
"proposals": true
}
}
]
]
}

7
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,7 @@
contact_links:
- name: 👪 Misskey Forum
url: https://forum.misskey.io/
about: Ask questions and share knowledge
- name: 💬 Misskey official Discord
url: https://discord.gg/Wp8gVStHW3
about: Chat freely about Misskey

View File

@ -1,13 +1,40 @@
## Summary
<!-- お読みください
PRありがとうございます PRを作成する前に、以下をご確認ください:
- 可能であればタイトルに、以下で示すようなPRの種類が分かるキーワードをプリフィクスしてください。
- fix / refactor / feat / enhance / perf / chore
- また、PRの粒度が適切であることを確認してください。ひとつのPRに複数の種類の変更や関心を含めることは避けてください。
- このPRによって解決されるIssueがある場合は、そのIssueへの参照を本文内に含めてください。
- CHANGELOG.mdに変更点を追記してください。リファクタリングなど、利用者に影響を与えない変更についてはこの限りではありません。
- この変更により新たに作成、もしくは更新すべきドキュメントがないか確認してください。
- 機能追加やバグ修正をした場合は、可能であればテストケースを追加してください。
- テスト、Lintが通っていることを予め確認してください。
- `npm run test``npm run lint`でぞれぞれ実施可能です
- UIに変更がある場合はスクリーンショットを本文内に添付してください。
ご協力ありがとうございます🤗
-->
<!-- README
Thank you for your PR! Before creating a PR, please check the following:
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
- fix / refactor / feat / enhance / perf / chore
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
- Please add the summary of the changes to CHANGELOG.md. However, this is not necessary for changes that do not affect the users, such as refactoring.
- Check if there are any documents that need to be created or updated due to this change.
- If you have added a feature or fixed a bug, please add a test case if possible.
- Please make sure that tests and Lint are passed in advance.
- You can run it with `npm run test` and `npm run lint`.
- If this PR includes UI changes, please attach a screenshot in the text.
Thanks for your cooperation 🤗
-->
<!--
-
- * Please describe your changes here *
-
- If you are going to resolve some issue, please add this context.
- Resolve #ISSUE_NUMBER
-
- If you are going to fix some bug issue, please add this context.
- Fix #ISSUE_NUMBER
-
-->
# What
<!-- このPRで何をしたのか どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
# Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
# Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->

11
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@ -35,6 +35,8 @@ jobs:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn install
- name: Check yarn.lock
run: git diff --exit-code yarn.lock
- name: Copy Configure
run: cp .circleci/misskey/*.yml .config
- name: Build

View File

@ -1 +1 @@
v16.2.0
v16.6.2

View File

@ -1 +1,73 @@
see [releases](https://github.com/misskey-dev/misskey/releases)
<!--
## 12.x.x (unreleased)
### Improvements
### Bugfixes
-->
## 12.89.0 (2021/08/21)
### Improvements
- アカウント削除の安定性を向上
- 絵文字オートコンプリートの挙動を改修
- localStorageのaccountsはindexedDBで保持するように
- ActivityPub: ジョブキューの試行タイミングを調整 (#7635)
- API: sw/unregisterを追加
- ワードミュートのドキュメントを追加
- クライアントのデザインの調整
- 依存関係の更新
### Bugfixes
- チャンネルを作成しているとアカウントを削除できないのを修正
- ノートの「削除して編集」をするとアンケートの選択肢が[object Object]になる問題を修正
## 12.88.0 (2021/08/17)
### Features
- ノートの翻訳機能を追加
- 有効にするには、サーバー管理者がDeepLの無料アカウントを登録し、取得した認証キーを「インスタンス設定 > その他 > DeepL Auth Key」に設定する必要があります。
- Misskey更新時にダイアログを表示するように
- ジョブキューウィジェットに警報音を鳴らす設定を追加
### Improvements
- ブロックの挙動を改修
- ブロックされたユーザーがブロックしたユーザーに対してアクション出来ないようになりました。詳細はドキュメントをご確認ください。
- UIデザインの調整
- データベースのインデックスを最適化
- Proxy使用時にKeep-Aliveをサポート
- DNSキャッシュでネガティブキャッシュをサポート
- 依存関係の更新
### Bugfixes
- タッチ操作でウィンドウを閉じることができない問題を修正
- Renoteされた時刻が投稿された時刻のように表示される問題を修正
- コントロールパネルでファイルを削除した際の表示を修正
- ActivityPub: 長いユーザーの名前や自己紹介の対応
## 12.87.0 (2021/08/12)
### Improvements
- 絵文字オートコンプリートで一文字目は最近使った絵文字をサジェストするように
- 絵文字オートコンプリートのパフォーマンスを改善
- about-misskeyページにドキュメントへのリンクを追加
- Docker: Node.jsを16.6.2に
- 依存関係の更新
- 翻訳の更新
### Bugfixes
- Misskey更新時、テーマキャッシュの影響でスタイルがおかしくなる問題を修正
## 12.86.0 (2021/08/11)
### Improvements
- ドキュメントの更新
- ドキュメントにchangelogを追加
- ぼかし効果のオプションを追加
- Vueを3.2.1に更新
- UIの調整
### Bugfixes
- ハッシュタグ入力が空のときに#が付くのを修正
- フォローリクエストのEメール通知を修正

View File

@ -35,6 +35,11 @@ If your language is not listed in Crowdin, please open an issue.
## Test
* Test codes are located in [`/test`](/test).
### Run specify test
```
npx cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT="./test/tsconfig.json" npx mocha test/foo.ts --require ts-node/register
```
## Continuous integration
Misskey uses GitHub Actions for executing automated tests.
Configuration files are located in [`/.github/workflows`](/.github/workflows).
@ -245,6 +250,9 @@ npx ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前
### コネクションには`markRaw`せよ
**Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。
### JSONのimportに気を付けよう
TypeScriptでjsonをimportすると、tscでコンパイルするときにそのjsonファイルも一緒にdistディレクトリに吐き出されてしまう。この挙動により、意図せずファイルの書き換えが発生することがあるので、jsonをimportするときは書き換えられても良いものかどうか確認すること。書き換えされて欲しくない場合は、importで読み込むのではなく、`fs.readFileSync`などの関数を使って読み込むようにすればよい。
## その他
### HTMLのクラス名で follow という単語は使わない
広告ブロッカーで誤ってブロックされる

View File

@ -1,4 +1,4 @@
FROM node:16.2.0-alpine3.13 AS base
FROM node:16.6.2-alpine3.13 AS base
ENV NODE_ENV=production
@ -18,9 +18,7 @@ RUN apk add --no-cache \
nasm \
pkgconfig \
python3 \
zlib-dev \
vips-dev \
vips
zlib-dev
COPY package.json yarn.lock .yarnrc ./
RUN yarn install
@ -31,8 +29,7 @@ FROM base AS runner
RUN apk add --no-cache \
ffmpeg \
tini \
vips
tini
ENTRYPOINT ["/sbin/tini", "--"]

Binary file not shown.

View File

@ -2,6 +2,6 @@ files:
- source: /locales/ja-JP.yml
translation: /locales/%locale%.yml
update_option: update_as_unapproved
- source: /src/docs/ja-JP/*.md
translation: /src/docs/%locale%/%original_file_name%
- source: /src/docs/ja-JP/**/*.md
translation: /src/docs/%locale%/**/%original_file_name%
update_option: update_as_unapproved

3
cypress.json Normal file
View File

@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost"
}

View File

@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@ -0,0 +1,69 @@
describe('Basic', () => {
before(() => {
cy.request('POST', '/api/reset-db');
});
beforeEach(() => {
cy.reload(true);
});
it('successfully loads', () => {
cy.visit('/');
});
it('setup instance', () => {
cy.visit('/');
cy.get('[data-cy-admin-username] input').type('admin');
cy.get('[data-cy-admin-password] input').type('admin1234');
cy.get('[data-cy-admin-ok]').click();
});
it('signup', () => {
cy.visit('/');
cy.get('[data-cy-signup]').click();
cy.get('[data-cy-signup-username] input').type('alice');
cy.get('[data-cy-signup-password] input').type('alice1234');
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
cy.get('[data-cy-signup-submit]').click();
});
it('signin', () => {
cy.visit('/');
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice');
// Enterキーでサインインできるかの確認も兼ねる
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
});
it('note', () => {
cy.visit('/');
//#region TODO: この辺はUI操作ではなくAPI操作でログインする
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice');
// Enterキーでサインインできるかの確認も兼ねる
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
//#endregion
cy.get('[data-cy-open-post-form]').click();
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
cy.get('[data-cy-open-post-form-submit]').click();
// TODO: 投稿した文字列が画面内にあるか(=タイムラインに流れてきたか)のテスト
});
});

22
cypress/plugins/index.js Normal file
View File

@ -0,0 +1,22 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })

20
cypress/support/index.js Normal file
View File

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -24,7 +24,7 @@ Please install and setup these softwares:
#### Dependencies :package:
* **[Node.js](https://nodejs.org/en/)** (12.x, 14.x)
* **[PostgreSQL](https://www.postgresql.org/)** (>= 10)
* **[PostgreSQL](https://www.postgresql.org/)** (12.x / 13.x is preferred)
* **[Redis](https://redis.io/)**
##### Optional

View File

@ -1,3 +1,13 @@
/*
import * as fs from 'fs';
if (fs.existsSync('./built')) {
import('./built/index.js').then(built => built());
} else {
console.log('Built code is not found. Probably an error occurred during a build or you just forgot to build.');
}
*/
const fs = require('fs');
if (fs.existsSync('./built')) {

View File

@ -427,9 +427,13 @@ inUse: "مستخدم"
info: "عن"
user: "المستخدمون"
administration: "إدارة "
postToGallery: "انشر في المعرض"
gallery: "المعرض"
expiration: "ينتهي استطلاع الرأي في"
middle: "متوسط"
global: "الشامل"
_docs:
admin: "إدارة "
_email:
_follow:
title: "يتابعك"

View File

@ -111,6 +111,7 @@ editWidgets: "Upravit widget"
editWidgetsExit: "Hotovo"
customEmojis: "Vlastní emoji"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Jméno emoji"
emojiUrl: "URL obrázku"
addEmoji: "Přidat emoji"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
---
_lang_: "Esperanto"
headlineMisskey: "Reto ligiĝas per notoj"
introMisskey: "Bonvenon! Miskejo estas malferma kodaの分散型マイクロブログサービスです。\nBonvolu Krei「noto」、いま起こっていることを共有したり、あなたについて皆に発信しよう📡\n「 reaktigoj 」機能で、皆のnotojに素早く反応を追加することもできます👍\n新しい世界を探検しよう🚀"
headlineMisskey: "Reto ligata per notoj"
introMisskey: "Bonvenon! Misskey estas malfermitkoda malcentraliza mikrobloga servo.\nKreu \"noto\"n por diskonigu tion ke nun okazas, aŭ por dissendu pri vi. 📡\nPer la funkcio \"reago\", vi ankaŭ povas rapide esprimi vian senton pri ĉies noto. 👍\nOni esploru novan mondon. 🚀"
monthAndDay: "{day}-a/{month}"
search: "Serĉi"
notifications: "Sciigoj"
username: "Uzantonomo"
username: "Uzantnomo"
password: "Pasvorto"
forgotPassword: "Ĉu vi forgesis pasvorton?"
fetchingAsApObject: "Informpetado de fediverso..."
ok: "Okej"
gotIt: "Mi konprenas!"
fetchingAsApObject: "Informpetado de Fediverso..."
ok: "Akcepteble"
gotIt: "Mi komprenas"
cancel: "Nuligi"
enterUsername: "Entajpu uzantonomon"
renotedBy: "Renotigojn faras {user}"
enterUsername: "Entajpu uzantnomon"
renotedBy: "Renoto farita de {user}"
noNotes: "Neniu noto!"
noNotifications: "Vi ne havas sciigojn."
instance: "Ekzemplo"
@ -22,7 +22,8 @@ basicSettings: "Ĝeneralaj agordoj"
otherSettings: "Aliaj agordoj"
openInWindow: "Malfermi en nova fenestro"
profile: "Profilo"
timeline: "Tempolinio"
timeline: "Templinio"
noAccountDescription: "Tiu uzanto ankoraŭ ne skribis biografieton"
login: "Ensaluti"
loggingIn: "Ensalutado..."
logout: "Elsaluti"
@ -42,31 +43,33 @@ unpin: "Depingli"
copyContent: "Kopii enhavon"
copyLink: "Kopii ligilon"
delete: "Forviŝi"
deleteAndEdit: "Forviŝi kaj redakti"
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forviŝi la noton? La reaktigoj, renotigoj, kaj respondoj ankaŭ forigiĝos."
addToList: "Aldoni al listo"
deleteAndEdit: "Forigi kaj redakti"
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forigi kaj redakti la noton? Ankaŭ ĉiuj reagoj, renotoj, kaj respondoj al ĝi foriĝos."
addToList: "Aldoni al la listo"
sendMessage: "Sendi mesaĝon"
copyUsername: "Kopii uzantonomon"
copyUsername: "Kopii uzantnomon"
searchUser: "Serĉi uzanton"
reply: "Respondi"
loadMore: "Vidu plu"
showMore: "Vidi plu"
youGotNewFollower: "Vi estas eksekvita."
loadMore: "Vidu pli"
showMore: "Vidi pli"
youGotNewFollower: "sksekvis vin"
receiveFollowRequest: "Peto de sekvado estas ricevita"
followRequestAccepted: "La peto de sekvado akceptita"
mention: "Mencioj"
mentions: "Mencioj"
directNotes: "Senperaj notoj"
importAndExport: "Importaĵo / Eksportaĵo"
mentions: "Al vi"
directNotes: "Rektaj notoj"
importAndExport: "Importi/eksporti"
import: "Importi"
export: "Eksporti"
files: "Dosieroj"
download: "Elŝuti"
driveFileDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la dosieron \"{name}\"? La notoj kun la aldonaĵo ankaŭ forviŝiĝos."
unfollowConfirm: "Ĉu vi certas, ke vi volas ne plu sekvi {name}?"
driveFileDeleteConfirm: "Ĉu vi certas, ke vi volas forviŝi la dosieron \"{name}\"? Ankaŭ notoj kiu enhavas ĝin forviŝiĝos."
unfollowConfirm: "Ĉu vi certas, ke vi volas ne plu sekvi {name}'(o)n?"
lists: "Listoj"
noLists: "Neniu listo"
note: "Elsendi noto"
notes: "Notoj"
following: "Sekvi"
following: "Sekvatoj"
followers: "Sekvantoj"
followsYou: "Sekvas vin"
createList: "Kreii liston"
@ -76,13 +79,15 @@ retry: "Reprovi"
enterListName: "Entajpu nomon de la listo"
privacy: "Privateco"
follow: "Sekvi"
followRequest: "Peti eksekvi"
followRequests: "Eksekvopetoj"
unfollow: "Ne plu sekvi"
renote: "Renotici"
unrenote: "Forigi renotici"
cantRenote: "Tiu noto estas renototebla."
cantReRenote: "Renotigo ne estas renotigebla."
followRequest: "Peti de sekvado"
followRequests: "Petoj de sekvado"
unfollow: "Malsekvi"
enterEmoji: "Entajpu emoĵion"
renote: "Fari renoton"
unrenote: "Malfari renoton"
renoted: "Renoton fariĝis."
cantRenote: "Tiu noto ne estas renototebla."
cantReRenote: "Oni ne povas fari renoton kiu enhavas renoto."
quote: "Citi"
pinnedNote: "Pinglita noto"
pinned: "Alpingli sur la profilo"
@ -91,7 +96,7 @@ clickToShow: "Klaku por malkaŝu"
sensitive: "Enhavo ne estas deca por laborejo (NSFW)"
add: "Aldoni"
reaction: "Reagoj"
enterFileName: "Entajpu dosiernomon"
enterFileName: "Entajpu nomon de dosiero"
mute: "Silentigi"
unmute: "Malsilentigi"
block: "Bloki"
@ -103,201 +108,549 @@ unblockConfirm: "Ĉu vi certas ke vi volas malbloki la uzanton?"
suspendConfirm: "Ĉu vi certas ke vi volas frostigi la uzanton?"
unsuspendConfirm: "Ĉu vi certas ke vi volas fandi la uzanton?"
selectList: "Elekti liston"
emojiUrl: "Retadreso de la emoĵio"
selectAntenna: "Elekti antenon"
selectWidget: "Elekti enestraĵon"
editWidgets: "Redakti fenestraĵon"
editWidgetsExit: "Fini la redaktadon"
customEmojis: "Personecigitaj emoĵioj"
emoji: "Emoĵio"
emojis: "Emoĵio"
emojiName: "Nomo de emoĵio"
emojiUrl: "URL de la emoĵio"
addEmoji: "Aldoni emoĵion"
settingGuide: "Rekomendaj agordoj"
cacheRemoteFiles: "Havi staplon de transaj dosieroj"
flagAsBot: "Tiu uzanto estas roboto"
flagAsCat: "Tiu uzanto estas kato"
addAccount: "Aldoni konton"
showOnRemote: "Vidi sur la transa ekzemplo"
showOnRemote: "Vidi sur la fora ekzemplo"
general: "Ĝenerala"
wallpaper: "Ekranfonoj"
setWallpaper: "Apliki ekranfonon"
removeWallpaper: "Forviŝi ekranfonon. "
searchWith: "Serĉi: {q}"
youHaveNoLists: "Vi ne havas listojn."
followConfirm: "Ĉu vi certas, ke vi volas sekvi {name}'n?"
followConfirm: "Ĉu vi certas ke vi volas sekvi {name}'(o)n?"
selectUser: "Elekti uzanton"
annotation: "Komentarioj"
federation: "Fediverso"
federation: "Kunfederaĵo"
instances: "Ekzemplo"
perHour: "Po horo"
perDay: "Po tago"
blockThisInstance: "Bloki tiu ekzemplo"
version: "Versio"
withNFiles: "{n} dosiero(j)"
disk: "Diskilo"
blockedInstances: "Blokitaj ekzemploj"
muteAndBlock: "Silentitaj / Blokitaj"
mutedUsers: "Silentigitaj uzantoj"
blockedUsers: "Blokitaj uzantoj"
instanceInfo: "Informo pri la ekzemplo"
clearCachedFiles: "Malplenigi la staplon"
clearCachedFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn transajn dosierojn en la staplo?"
blockedInstances: "Blokataj ekzemploj"
muteAndBlock: "Silentigatoj kaj blokatoj"
mutedUsers: "Silentigataj uzantoj"
blockedUsers: "Blokataj uzantoj"
noUsers: "Sen uzantoj"
editProfile: "Redakti profilon"
noteDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la noton?"
pinLimitExceeded: "Vi ne plu povas alpingli noton."
pinLimitExceeded: "Vi povas alpingli ne pli noton."
processing: "Traktado..."
noCustomEmojis: "Neniu emoĵio"
federating: "Konfederado"
blocked: "Blokita"
federating: "Kunfederado"
blocked: "Blokata"
all: "Ĉiuj"
subscribing: "Abonita"
publishing: "Dissendado"
notResponding: "Alvokato ne disponeblas"
instanceFollowing: "Sekvi ekzemplon"
instanceFollowers: "Sekvantoj de la ekzemplo"
instanceFollowing: "Sekvatoj el la ekzemplo"
instanceFollowers: "Sekvantoj el la ekzemplo"
instanceUsers: "Uzantoj de la ekzemplo"
changePassword: "Ŝanĝi pasvorton"
security: "Sekureco"
currentPassword: "Aktuala pasvorto"
newPassword: "Nova pasvorto"
newPasswordRetype: "Reentajpu la novan pasvorton"
attachFile: "Aldoni dosieron"
more: "Plu!"
usernameOrUserId: "Uzantonomo aŭ ID de uzanto"
more: "Plu !"
featured: "Maksimumi"
usernameOrUserId: "Uzantnomo aŭ identigilo de uzanto"
noSuchUser: "Neniuj uzantoj trovitaj."
remove: "Forviŝi"
lookup: "Informpeti"
announcements: "Novaĵoj"
imageUrl: "URL de bildo"
remove: "Forigi"
removed: "Forviŝis"
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
deleteAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
messaging: "Babilejoj"
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"'(o)n?"
deleteAreYouSure: "Ĉu vi certas ke vi volas forviŝi \"{x}\"'(o)n?"
saved: "Konservita"
messaging: "Retbabili"
upload: "Alŝuti"
fromDrive: "De la diskilo"
fromUrl: "De retadreso"
uploadFromUrl: "Aldoni de retadreso"
uploadFromUrlDescription: "Retadreso de la dosiero kiun vi volu alŝuti"
games: "Ludoj sur Miskejo"
fromDrive: "De la disko"
fromUrl: "De URL"
uploadFromUrl: "Alŝuti de URL"
uploadFromUrlDescription: "URL de la dosiero kiun vi volas alŝuti"
explore: "Esplori"
games: "Ludoj sur Misskey"
messageRead: "Legita"
startMessaging: "Komenci babiladon"
tos: "Kondiĉoj de Uzado"
nUsersRead: "Legita de {n} homoj"
tos: "Kondiĉoj de uzado"
start: "Komenciĝi"
home: "Ĉefpaĝo"
drive: "Diskilo"
home: "Hejmo"
remoteUserCaution: "Ĉi tiu Infomoj estas ne tute ekzakta pro distanca uzanto."
activity: "Aktiveco"
images: "Bildoj"
birthday: "Naskiĝdato"
registeredDate: "Registriĝdato"
location: "Loko"
theme: "Koloraro"
light: "Luma"
dark: "Malluma"
drive: "Disko"
fileName: "Dosiernomo"
selectFile: "Elekti dosieron"
selectFiles: "Elekti dosieron"
renameFile: "Renomigi dosieron"
selectFolder: "Elekti dosierujon"
selectFolders: "Elekti dosierujon"
renameFile: "Alinomi la dosieron"
folderName: "Nomo de la dosierujo"
createFolder: "Krei dosierujon"
renameFolder: "Alinomi la dosierujon"
deleteFolder: "Forviŝi dosierujon"
addFile: "Aldoni dosieron"
emptyDrive: "La diskilo enhavas neniun."
emptyDrive: "La disko malplenas"
emptyFolder: "La dosierujo malplenas"
unableToDelete: "Ne forigebla"
inputNewFileName: "Entajpu nova dosiernomon"
hasChildFilesOrFolders: "La dosierujo estas neforviŝebla pro tio, ke ĝi enhavas dosieron."
copyUrl: "Kopii retadreson"
inputNewFileName: "Entajpu nova nomon de la dosiero"
inputNewFolderName: "Entajpu nova nomon de la dosierujo"
hasChildFilesOrFolders: "La dosierujo ne estas forviŝebla, ĉar ĝi ne malplenas."
copyUrl: "Kopii URL"
rename: "Alinomi"
avatar: "Ikono"
banner: "Standardo"
nsfw: "Enhavo ne estas deca por laborejo (NSFW)"
reload: "Reŝargi"
watch: "Observi"
unwatch: "Malobservi"
accept: "Permesi"
normal: "Normala"
instanceName: "Nomo de la ekzemplo"
maintainerName: "Nomo de la administranto"
maintainerEmail: "Retpoŝto de la administranto"
tosUrl: "URL de kondiĉoj de uzado"
thisYear: "Ĉi-jare"
thisMonth: "Ĉi-monate"
today: "Hodiaŭ"
dayX: "{day}-a"
monthX: "{month}"
yearX: "La jaro {year}"
pages: "Paĝoj"
connectService: "Konekti"
disconnectService: "Farkonektiĝi"
driveCapacityPerLocalAccount: "Volumo po unu loka-uzanto"
driveCapacityPerRemoteAccount: "Volumo po unu transa uzanto"
enableGlobalTimeline: "Ebligi mallokan templinion"
registration: "Registri"
driveCapacityPerLocalAccount: "Volumo de disko po unu loka uzanto"
driveCapacityPerRemoteAccount: "Volumo de disko po unu transa uzanto"
iconUrl: "URL de la ikono (retpaĝsimbolo, ktp)"
bannerUrl: "URL de standardo"
backgroundImageUrl: "URL de fona bildo"
basicInfo: "Baza informo"
pinnedUsers: "Alpinglita uzanto"
pinnedPages: "Alpinglitaj paĝoj"
pinnedNotes: "Pinglita noto"
antennas: "Antenoj"
name: "Nomo"
withFileAntenna: "Nur kun aldonaĵo"
withReplies: "Inkluzive respondoj"
notesAndReplies: "Kun respondoj"
withFiles: "Kun aldonaĵo"
silenceConfirm: "Ĉu vi certas ke vi volas silentigi la uzanton?"
unsilenceConfirm: "Ĉu vi certas ke vi volas malsilentigi la uzanton?"
silence: "Mutigi"
silenceConfirm: "Ĉu vi certas ke vi volas mutigi la uzanton?"
unsilence: "Malmutigi"
unsilenceConfirm: "Ĉu vi certas ke vi volas malmutigi la uzanton?"
recentlyUpdatedUsers: "Uzantoj kiu lastatempe faris noton"
recentlyRegisteredUsers: "Nove aniĝintaj uzantoj"
popularTags: "Popularaj kradvortoj"
userList: "Listoj"
aboutMisskey: "Pri Miskejo"
about: "Informoj"
aboutMisskey: "Pri Misskey"
administrator: "Administranto"
moderator: "Moderigisto"
securityKey: "Sekureca ŝlosilo"
securityKeyName: "Nomo de la ŝlosilo"
lastUsed: "Plej malnove uzita"
passwordLessLogin: "Ensaluti sen pasvorto"
resetPassword: "Restarigi pasvorton"
newPasswordIs: "La nova pasvorto estas {password}."
share: "Diskonigi"
notFound: "Ne trovita"
cacheClear: "Malplenigi staplon"
help: "Manlibro de uzado"
inputMessageHere: "Entajpu masaĝo tie ĉi"
close: "Fermi"
group: "Grupo"
groups: "Grupoj"
createGroup: "Krei grupon"
groupName: "Grupa nomo"
members: "Membroj"
messagingWithUser: "Mesaĝado kun uzanto"
messagingWithGroup: "Mesaĝado kun grupo"
title: "Titolo"
text: "Teksto"
enable: "Ebligi"
next: "Sekve"
noteOf: "Noto de {user}"
noMessagesYet: "Neniu mesaĝo"
newMessageExists: "Vi ricevis novan mesaĝon."
onlyOneFileCanBeAttached: "Vi povas aldoni nur unu dosieron po unu mesaĝo."
uiLanguage: "Lingvo de la interfaco"
noFollowRequests: "Vi ne havas eksekvopetojn."
invitationCode: "Kodo de invito"
or: "Aŭ"
language: "Lingvo"
uiLanguage: "Lingvo de la fasado"
aboutX: "Pri {x}"
useOsNativeEmojis: "Oni uzas la emoĵioj de la denaska sistemo"
youHaveNoGroups: "Neniuj grupoj"
category: "Kategorio"
tags: "Etikedoj"
createAccount: "Krei konton"
existingAccount: "Ekzista konto"
fontSize: "Tipara grando"
noFollowRequests: "Vi ne havas peto de sekvado"
openImageInNewTab: "Fermi la bildon en nova tablo"
dashboard: "Stirpanelo"
local: "Loka"
remote: "Transa"
total: "Entute"
clientSettings: "Agordoj de kliento"
accountSettings: "Agordoj de Konto"
numberOfDays: "Nombro de tagoj"
hideThisNote: "Kaŝi tiun noton"
deleteAllFiles: "Forvisi ĉiujn dosierojn"
objectStorageBaseUrl: "Baza URL"
objectStorageRegion: "Regiono"
objectStorageUseSSL: "Oni uzas SSL"
serverLogs: "Servila protokolo"
deleteAll: "Forviŝi ĉiujn"
sounds: "Sonoj"
listen: "Aŭdi"
none: "Neniu"
showInPage: "Vidi en paĝo"
deleteAllFiles: "Forviŝi ĉiujn dosierojn"
deleteAllFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn viajn dosierojn?"
userSilenced: "Tiu uzanto estas mutigata."
menu: "Menuo"
deletedNote: "Forviŝita noto"
invisibleNote: "Malpublika noto"
poll: "Balotujo"
useCw: "Kaŝi enhavo"
themeEditor: "Redaktilo de koloraroj"
author: "Aŭtoro"
plugins: "Kromaĵoj"
deck: "Kartaro"
medium: "Meza"
small: "Malgranda"
edit: "Redakti"
emailServer: "Retpoŝta servilo"
email: "Retpoŝto"
emailAddress: "Retpoŝtadreso"
smtpUser: "Uzantonomo"
emailAddress: "Retpoŝta adreso"
smtpConfig: "Agordoj de la servilo SMTP"
smtpPort: "Pordo"
smtpUser: "Uzantnomo"
smtpPass: "Pasvorto"
wordMute: "Silentigo de vortoj"
userSaysSomething: "{name} parolis ion"
display: "Vidi"
copy: "Kopii"
database: "Datumbazo"
channel: "Kanalo"
fileIdOrUrl: "Dosirero ID aŭ retadreso"
create: "Krei"
notificationSetting: "Agordoj de sciigoj"
useGlobalSetting: "Oni uzas malloka agordo"
fileIdOrUrl: "Dosiera identigilo aŭ URL"
abuseReports: "Signaloj"
reportAbuse: "Signalo"
reportAbuseOf: "Signali kontraŭ {name}'(o)"
send: "Sendi"
i18nInfo: "Tradukojn de Misskey en diversaj lingvoj faras volontuloj. Vi povus kunlabori en tradukado sur {link}, se vi volus."
driveFilesCount: "Numero de dosieroj en la diskilo"
onlineUsersCount: "{n} uzanto(j) estas surkonektita"
openInNewTab: "Malfermi en nova langeto"
editTheseSettingsMayBreakAccount: "Redakti tiujn agordojn estas eble damaĝi konton."
public: "Publika"
i18nInfo: "Misskey estas tradukata en diversaj lingvoj far volontuloj. Oni povas kontribui por la tradukado ĉe {link}."
accountInfo: "Kontaj Informoj"
notesCount: "Numero de notoj"
repliesCount: "Numero de respondoj senditaj"
renotesCount: "Numero de renotoj kiun vi sendis"
repliedCount: "Numero de respondoj ricevitaj"
renotedCount: "Numero de renotoj kiun vi ricevis"
followingCount: "Numero de sekvatoj"
followersCount: "Numero de sekvantoj"
sentReactionsCount: "Numero de sentitaj reagoj"
receivedReactionsCount: "Numero de ricevitaj reagoj"
yes: "Jes"
no: "Ne"
driveFilesCount: "Numero de dosieroj sur la disko"
notSet: "Ne elektita"
noteFavoritesCount: "Numero de la preferataj notoj"
contact: "Kontakto"
makeExplorable: "Videbligi konton sur la paĝo \"Esplori\""
duplicate: "Duobligi"
left: "Maldekstra"
center: "Centra"
showTitlebar: "Montri titola stango"
clearCache: "Malplenigi staplon"
onlineUsersCount: "{n} uzanto(j) estas surlinea"
nUsers: "{n} uzanto(j)"
nNotes: "{n} notoj"
myTheme: "Miaj koloraroj"
backgroundColor: "Fona koloro"
textColor: "Teksto"
saveAs: "Konservi kiel…"
value: "Valoro"
createdAt: "Kreita je"
updatedAt: "Laste ĝisdatigita"
deleteConfirm: "Ĉu certas forviŝi?"
closeAccount: "Forigi konton"
currentVersion: "Nuna versio"
latestVersion: "Plej nova versio"
youAreRunningUpToDateClient: "Vi uzas la plej novan version de via kliento."
newVersionOfClientAvailable: "Nova versio de via kliento estas disponebla."
inUse: "Uzata"
editCode: "Redakti kodon"
emailNotification: "Sciigoj per retpoŝto"
publish: "Publikigi"
inChannelSearch: "Serĉi en kanalo"
useReactionPickerForContextMenu: "Oni malfermas reago-elektilon per dekstro-kliki"
typingUsers: "{users} estas entajpanta(j)..."
info: "Informoj"
unknown: "Nekonata"
online: "Surkonektita"
offline: "Forkonektita"
instanceBlocking: "Ekzempla blokado"
instanceBlocking: "Blokado de ekzemplo"
selectAccount: "Elekti konton"
user: "Uzanto"
accounts: "Kontoj"
high: "Alta"
middle: "Meza"
low: "Malalta"
customCss: "Uzantula CSS"
global: "Malloka"
sent: "Sendi"
received: "Ricevita"
searchResult: "Serĉorezultoj"
hashtags: "Kradvorto"
learnMore: "Lernu pli"
translate: "Traduki"
translatedFrom: "Tradukita el {x}"
_docs:
continueReading: "Legi plu"
features: "Funkcioj"
_gallery:
liked: "Ŝatitaj notoj"
like: "Ŝati"
_email:
_follow:
title: "Vi estas eksekvita."
title: "Vi estas eksekvita"
_receiveFollowRequest:
title: "Vi ricevis eksekvopeton."
title: "Vi ricevis peton de sekvado"
_registry:
key: "Ŝlosilo"
keys: "Ŝlosiloj"
domain: "Nomregno"
createKey: "Krei ŝlosilon"
_aboutMisskey:
about: "Misskey estas malferma koda programo evoluigata far syuilo ekde la 2014."
about: "Misskey estas malfermitkoda programo evoluigata de syuilo ekde la 2014."
contributors: "Precipaj kontribuantoj"
allContributors: "Ĉiuj kontribuintoj"
source: "Fontkodo"
translation: "Traduki Misskey'on"
patrons: "Mecenatoj"
_mfm:
mention: "Mencioj"
url: "Retadreso"
blockCode: "Kodo (Ujo)"
blockMath: "Formulo (Ujo)"
hashtag: "Kradvorto"
url: "URL"
link: "Ligilo"
bold: "Grasa"
small: "Malgrande"
center: "Centrigi"
inlineCode: "Kodo (en linio)"
blockCode: "Kodo (bloko)"
inlineMath: "Formulo (en linio)"
blockMath: "Formulo (bloko)"
quote: "Citi"
emoji: "Personecigitaj emoĵioj"
search: "Serĉi"
flip: "Inversa"
x2: "Granda"
x3: "Grandega"
x4: "Pli grandega"
_reversi:
total: "Entute"
_instanceTicker:
none: "Ne montri"
remote: "Montri al transaj uzantoj"
always: "Ĉiam montri"
_channel:
create: "Krei kanalon"
edit: "Redakti kanalon"
following: "Sekvaton"
following: "Sekvante"
usersCount: "{n} partoprenanto(j)"
_menuDisplay:
hide: "Kaŝi"
_wordMute:
muteWords: "Kaŝigitaj vortoj"
mutedNotes: "Silentigataj notoj"
_theme:
code: "Kodo de koloraro"
darken: "Malbrileco"
lighten: "Brileco"
keys:
bg: "Fono"
navBg: "Fono de flanka stango"
hashtag: "Kradvorto"
mention: "Mencioj"
renote: "Renotici"
renote: "Fari renoton"
buttonBg: "Fono de butono"
driveFolderBg: "Fono de dosierujo de la disko"
_sfx:
note: "Nova noto"
noteMy: "Mia noto"
notification: "Sciigoj"
chat: "Babilejoj"
channel: "Kanala sciigoj"
chat: "Retbabili"
chatBg: "Retbabili (BG)"
antenna: "Ricevo de anteno"
channel: "Sciigoj de kanalo"
_ago:
future: "Futuro"
justNow: "Ĵus"
secondsAgo: "Antaŭ {n} sekundoj"
minutesAgo: "Antaŭ {n} minutoj"
hoursAgo: "Antaŭ {n} horo(j)"
daysAgo: "Antaŭ {n} tagoj"
weeksAgo: "Antaŭ {n} semajnoj"
monthsAgo: "Antaŭ {n} monatoj"
yearsAgo: "Antaŭ {n} jaroj"
_time:
second: "sek"
minute: "min"
hour: "hor"
day: "Tago"
_tutorial:
title: "Uzado de Miskejo"
title: "Uzado de Misskey"
step1_1: "Bonvenon."
step7_2: "Se vi volas scii pli pri Misskey, rigardu la fakon {help}."
step7_3: "Do, bonvolu amuziĝi Misskey'on🚀"
_permissions:
"read:blocks": "Vidi la listo de la uzantoj kiun vi blokis."
"read:drive": "Vidi dosierojn en la diskilo"
"read:channels": "Legi kanalon"
"read:blocks": "Vidi la liston de uzantoj kiun vi blokas"
"write:blocks": "Redakti vian liston de blokataj uzantoj"
"read:drive": "Operacio por legi la informon de dosiero en via disko de Misskey"
"write:drive": "Ĉia operacio por skribi, forviŝi, aŭ alimaniere ŝanĝi la informon de dosiero en via disko de Misskey"
"read:favorites": "Vidi vian liston de preferatoj"
"read:following": "Vidi tiun kiun vi sekvas"
"write:following": "Sekvi aŭ malsekvi alian uzanton"
"read:messaging": "Vidi vian retbabiladon"
"read:mutes": "Vidi vian liston de silentigoj"
"write:mutes": "Redakti vian liston de silentigoj"
"write:notes": "Krei / Forviŝi noton"
"read:notifications": "Vidi sciigojn"
"read:reactions": "Vidi reagojn"
"write:reactions": "Redakti viajn reagojn"
"read:pages": "Vidi via paĝojn"
"read:page-likes": "Vidi ŝatojn de paĝo"
"read:channels": "Vidi kanalojn"
_antennaSources:
all: "Ĉiuj notoj"
homeTimeline: "Notoj far uzantoj, kiujn vi sekvas"
_weekday:
sunday: "dimanĉo"
monday: "lundo"
tuesday: "mardo"
wednesday: "merkredo"
thursday: "ĵaŭdo"
friday: "vendredo"
saturday: "sabato"
_widgets:
notifications: "Sciigoj"
timeline: "Tempolinio"
federation: "Fediverso"
timeline: "Templinio"
clock: "Horloĝo"
activity: "Aktiveco"
federation: "Kunfederaĵo"
slideshow: "Bildoprezento"
button: "Butono"
onlineUsers: "Surkonektita uzanto"
_cw:
show: "Vidu plu"
show: "Vidu pli"
files: "{count} dosiero(j)"
_poll:
choiceN: "Balotilo {n}"
noMore: "Oni ne povas aldoni pli."
infinite: "Neniam"
deadlineTime: "hor"
votesCount: "{n} balotiloj"
vote: "Baloti"
closed: "Oni jam balotis ĝin"
_visibility:
publicDescription: "Via noto aperiĝos sur konfederacia tempolinio"
home: "Ĉefpaĝo"
homeDescription: "Elsendi nur sur hejma tempolinio"
publicDescription: "Via noto aperiĝos sur la konfederacia templinio"
home: "Hejmo"
homeDescription: "Elsendi nur sur la hejmtemplinio"
followers: "Sekvantoj"
followersDescription: "Elsendi nur al sekvantoj de mi"
followersDescription: "Nur al sekvantoj al mi"
localOnly: "Nur loka"
localOnlyDescription: "Nelegabla al transaj uzantoj"
localOnlyDescription: "Ne montri al transaj uzantoj"
_postForm:
channelPlaceholder: "Elsendi sur la kanalo"
replyPlaceholder: "Respondi al tiu noto..."
quotePlaceholder: "Citado tiun noton..."
channelPlaceholder: "Sendi sur la kanalo"
_profile:
username: "Uzantonomo"
name: "Nomo"
username: "Uzantnomo"
metadataEdit: "Redakti kromaj informoj"
changeAvatar: "Ŝanĝi profilbildon"
changeBanner: "Ŝanĝi standardon"
_exportOrImport:
followingList: "Sekvi"
muteList: "Silentigi"
allNotes: "Ĉiuj notoj"
followingList: "Sekvataj"
muteList: "Silentigoj"
blockingList: "Blokado"
userLists: "Listoj"
_charts:
federationInstancesTotal: "Tuta numero de kunfederantaj ekzemploj"
filesTotal: "Tuta numero de dosieroj"
_timelines:
home: "Hejmo"
local: "Loka"
social: "Hejmo kaj loka"
social: "Sociala"
global: "Malloka"
_rooms:
translate: "Movi"
chooseImage: "Elekti bildon"
_furnitures:
server: "Servilo"
moon: "La luno"
_pages:
editPage: "Redakti paĝon"
deleted: "La paĝo estas forigita."
editThisPage: "Redakti la paĝon"
viewPage: "Vidi via paĝojn"
my: "Miaj paĝoj"
featured: "Ravaĵoj"
content: "Blokado de paĝo"
url: "Retadreso de la paĝo"
chooseBlock: "Aldoni blokado"
url: "URL de paĝo"
alignCenter: "Centrigi"
chooseBlock: "Aldoni blokon"
blocks:
image: "Bildo"
button: "Butono"
_post:
canvasId: "Kanvasa identigilo"
_numberInput:
text: "Titolo"
_canvas:
id: "Kanvasa identigilo"
_note:
id: "Identigilo de noto"
_counter:
text: "Titolo"
_button:
text: "Titolo"
_action:
_pushEvent:
event: "Nomo de la evento"
script:
categories:
list: "Listoj"
@ -315,23 +668,32 @@ _pages:
arg1: "Listoj"
_listLen:
arg1: "Listoj"
_splitStrByLine:
arg1: "Teksto"
types:
array: "Listoj"
stringArray: "List de teksto"
_notification:
fileUploaded: "La dosiero sukcese alŝutiĝis."
youWereFollowed: "Vi estas eksekvita."
youReceivedFollowRequest: "Vi ricevis eksekvopeton."
yourFollowRequestAccepted: "Via eksekvopeto estas akceptita."
youGotPoll: "{name} balotis"
youGotMessagingMessageFromUser: "{name} sentis mesaĝon al vi."
youGotMessagingMessageFromGroup: "Retbabilan mesaĝon oni sendis al la grupo {name}"
youWereFollowed: "sksekvis vin"
youReceivedFollowRequest: "Vi ricevis peton de sekvado"
yourFollowRequestAccepted: "Via peto por sekvado estis akceptita."
_types:
follow: "Sekvi"
follow: "Sekvatoj"
mention: "Mencioj"
renote: "Renotici"
renote: "Fari renoton"
quote: "Citi"
reaction: "Reagoj"
receiveFollowRequest: "Eksekvopeto ricevita"
receiveFollowRequest: "Ricevita peton de sekvado"
followRequestAccepted: "Akceptita peto por sekvado"
_deck:
profile: "Agordaro"
_columns:
notifications: "Sciigoj"
tl: "Tempolinio"
tl: "Templinio"
antenna: "Antenoj"
list: "Listoj"
mentions: "Mencioj"
mentions: "Al vi"

View File

@ -127,6 +127,7 @@ editWidgets: "Editar widgets"
editWidgetsExit: "Terminar edición"
customEmojis: "Emojis personalizados"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Nombre del emoji"
emojiUrl: "URL de la imágen del emoji"
addEmoji: "Agregar emoji"
@ -665,6 +666,10 @@ administration: "Administrar"
expiration: "Termina el"
middle: "Mediano"
global: "Global"
sent: "Enviar"
hashtags: "Hashtag"
_docs:
admin: "Administrar"
_ad:
back: "Deseleccionar"
_gallery:

View File

@ -91,11 +91,11 @@ followRequests: "Demandes dabonnement"
unfollow: "Se désabonner"
followRequestPending: "Demande d'abonnement en attente de confirmation"
enterEmoji: "Insérer un émoji"
renote: "Partager"
unrenote: "Annuler le partage"
renoted: "Republié !"
cantRenote: "Ce message ne peut pas être republié."
cantReRenote: "Impossible de repartager un partage."
renote: "Renoter"
unrenote: "Annuler la Renote"
renoted: "Renoté !"
cantRenote: "Ce message ne peut pas être renoté."
cantReRenote: "Impossible de renoter une Renote."
quote: "Citer"
pinnedNote: "Note épinglée"
pinned: "Épingler sur le profil"
@ -128,6 +128,7 @@ editWidgets: "Modifier les widgets"
editWidgetsExit: "Valider les modifications"
customEmojis: "Émojis personnalisés"
emoji: "Émoji"
emojis: "Émoji"
emojiName: "Nom de lémoji"
emojiUrl: "URL de lémoji"
addEmoji: "Ajouter un émoji"
@ -528,6 +529,7 @@ removeAllFollowing: "Retenir tous les abonnements"
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action uniquement si linstance nexiste plus."
userSuspended: "Cet·te utilisateur·rice a été suspendu·e."
userSilenced: "Cette utilisateur·trice a été mis·e en sourdine."
menu: "Menu"
divider: "Séparateur"
addItem: "Ajouter un élément"
rooms: "Chambre"
@ -636,9 +638,9 @@ manageAccessTokens: "Gérer les jetons d'accès"
accountInfo: " Informations du compte "
notesCount: "Nombre de notes"
repliesCount: "Nombre de réponses envoyées"
renotesCount: "Nombre de notes repartagées"
renotesCount: "Nombre de notes que vous avez renotées"
repliedCount: "Nombre de réponses reçues"
renotedCount: "Nombre de Renotes"
renotedCount: "Nombre de vos notes renotées"
followingCount: "Nombre de comptes suivis"
followersCount: "Nombre d'abonnés"
sentReactionsCount: "Nombre de réactions envoyées"
@ -760,7 +762,27 @@ middle: "Moyen"
low: "Basse"
emailNotConfiguredWarning: "Vous n'avez pas configuré d'adresse e-mail."
ratio: "Ratio"
customCss: "CSS personnalisé"
customCssWarn: "Utilisez cette fonctionnalité uniquement si vous savez exactement ce que vous faites. Une configuration inadaptée peut empêcher le client de s'exécuter normalement."
global: "Global"
squareAvatars: "Avatars carrés"
sent: "Envoyer"
searchResult: "Résultats de la recherche"
hashtags: "Hashtags"
troubleshooting: "Résolution de problèmes"
useBlurEffect: "Utiliser des effets de flou dans l'interface"
learnMore: "Plus d'informations"
misskeyUpdated: "Misskey a été mis à jour !"
whatIsNew: "Voir les derniers changements"
translate: "Traduire"
translatedFrom: "Traduit depuis {x}"
_docs:
continueReading: "Lire plus"
features: "Fonctionnalités"
generalTopics: "Sujets généraux"
advancedTopics: "Sujets avancés"
admin: "Gestion"
translateWarn: "Ceci est une traduction dont le contenu peut différer du texte original."
_ad:
back: "Retour"
reduceFrequencyOfThisAd: "Voir cette publicité moins souvent"
@ -859,6 +881,8 @@ _mfm:
blurDescription: "Le contenu peut être flouté ; il sera visible en le survolant avec le curseur."
font: "Police de caractères"
fontDescription: "Il est possible de choisir la police."
rainbow: "Arc-en-ciel"
rainbowDescription: "Permet d'afficher le contenu en couleurs arc-en-ciel."
_reversi:
reversi: "Reversi"
gameSettings: "Réglages de la partie"
@ -911,6 +935,9 @@ _channel:
usersCount: "{n} Participant·e·s"
notesCount: "{n} Notes"
_menuDisplay:
sideFull: "Latéral"
sideIcon: "Latéral (icônes)"
top: "Haut de page"
hide: "Masquer"
_wordMute:
muteWords: "Mots à filtrer"
@ -969,7 +996,7 @@ _theme:
hashtag: "Hashtags"
mention: "Mentionner"
mentionMe: "Mentions (Moi)"
renote: "Partager"
renote: "Renoter"
modalBg: "Modal d'arrière-plan"
divider: "Séparateur"
scrollbarHandle: "Poignée de la barre de navigation"
@ -1590,11 +1617,11 @@ _notification:
youWereInvitedToGroup: "Invité·e au groupe"
_types:
all: "Toutes"
follow: "Abonnements"
follow: "Nouvel·le abonné·e"
mention: "Mentions"
reply: "Réponses"
renote: "Partager"
quote: "Citer"
renote: "Renotes"
quote: "Citations"
reaction: "Réactions"
pollVote: "Votes dans des sondages"
receiveFollowRequest: "Demande d'abonnement reçue"

View File

@ -128,6 +128,7 @@ editWidgets: "Sunting gawit"
editWidgetsExit: "Selesai"
customEmojis: "Emoji kustom"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Nama emoji"
emojiUrl: "URL Emoji"
addEmoji: "Tambahkan emoji"
@ -528,6 +529,7 @@ removeAllFollowing: "Tahan semua mengikuti"
removeAllFollowingDescription: "Batal mengikuti semua akun dari {host}. Mohon jalankan ini ketika instansi sudah tidak ada lagi."
userSuspended: "Pengguna ini telah dibekukan."
userSilenced: "Pengguna ini telah dibungkam."
menu: "Menu"
divider: "Pembagi"
addItem: "Tambahkan item"
rooms: "Ruang"
@ -760,7 +762,26 @@ middle: "Sedang"
low: "Rendah"
emailNotConfiguredWarning: "Alamat surel tidak disetel."
ratio: "Rasio"
customCss: "Custom CSS"
customCssWarn: "Pengaturan ini seharusnya digunakan jika kamu tahu cara kerjanya. Memasukkan nilai yang tidak tepat dapat menyebabkan klien tidak berfungsi semestinya."
global: "Global"
squareAvatars: "Tampilkan avatar sebagai persegi"
sent: "Kirim"
received: "Diterima"
searchResult: "Hasil Penelusuran"
hashtags: "Tagar"
troubleshooting: "Penyelesaian Masalah"
useBlurEffect: "Gunakan efek blur pada antarmuka"
learnMore: "Pelajari lebih lanjut"
misskeyUpdated: "Misskey telah dimutakhirkan!"
whatIsNew: "Lihat perubahan pemutakhiran"
_docs:
continueReading: "Baca lebih lanjut"
features: "Fitur"
generalTopics: "Topik umum"
advancedTopics: "Topik tingkat lanjut"
admin: "Manajemen"
translateWarn: "Ini merupakan dokumen terjemahan. Konten di dalamnya kemungkinan dapat berbeda dari yang aslinya."
_ad:
back: "Kembali"
reduceFrequencyOfThisAd: "Tampilkan iklan ini lebih sedikit"
@ -859,6 +880,8 @@ _mfm:
blurDescription: "Konten dapat diburamkan dengan efek ini. Konten dapat ditampilkan dengan jelas dengan melayangkan kursor tetikus di atasnya."
font: "Font"
fontDescription: "Setel font yang ditampilkan untuk konten."
rainbow: "Pelangi"
rainbowDescription: "Membuat konten muncul dalam warna pelangi."
_reversi:
reversi: "Reversi"
gameSettings: "Pengaturan permainan"
@ -911,6 +934,9 @@ _channel:
usersCount: "{n} Partisipan"
notesCount: "terdapat {n} catatan"
_menuDisplay:
sideFull: "Horisontal"
sideIcon: "Horisontal (Ikon)"
top: "Atas"
hide: "Sembunyikan"
_wordMute:
muteWords: "Kata yang dibisukan"

View File

@ -127,6 +127,7 @@ editWidgets: "Modifica i widget"
editWidgetsExit: "Modifica fine"
customEmojis: "Emoji personalizzati"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Nome dell'emoji"
emojiUrl: "URL dell'emoji"
addEmoji: "Aggiungi un emoji"
@ -741,6 +742,13 @@ low: "Bassa"
emailNotConfiguredWarning: "Non hai impostato nessun indirizzo e-mail."
ratio: "Rapporto"
global: "Federata"
sent: "Inviare"
hashtags: "Hashtag"
troubleshooting: "Risoluzione problemi"
_docs:
continueReading: "Leggi di più"
features: "Funzionalità"
admin: "Gestione"
_ad:
back: "Indietro"
reduceFrequencyOfThisAd: "Visualizza questa pubblicità meno spesso"
@ -799,6 +807,7 @@ _mfm:
blur: "Sfocatura"
font: "Tipo di carattere"
fontDescription: "Puoi scegliere il tipo di carattere per il contenuto."
rainbow: "Arcobaleno"
_reversi:
reversi: "Reversi"
gameSettings: "Impostazioni di gioco"
@ -1386,12 +1395,12 @@ _notification:
youWereInvitedToGroup: "Invitat@ al gruppo"
_types:
all: "Tutto"
follow: "Follows"
follow: "Nuovə follower"
mention: "Menzioni"
reply: "Rispondi"
reply: "Risposte"
renote: "Rinota"
quote: "Cita"
reaction: "Reazione"
reaction: "Reazioni"
pollVote: "Voti ricevuti"
receiveFollowRequest: "Richiesta di follow ricevuta"
followRequestAccepted: "Richiesta di follow accettata"

View File

@ -128,6 +128,7 @@ editWidgets: "ウィジェットを編集"
editWidgetsExit: "編集を終了"
customEmojis: "カスタム絵文字"
emoji: "絵文字"
emojis: "絵文字"
emojiName: "絵文字名"
emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
@ -765,6 +766,34 @@ customCss: "カスタムCSS"
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
global: "グローバル"
squareAvatars: "アイコンを四角形で表示"
sent: "送信"
received: "受信"
searchResult: "検索結果"
hashtags: "ハッシュタグ"
troubleshooting: "トラブルシューティング"
useBlurEffect: "UIにぼかし効果を使用"
learnMore: "詳しく"
misskeyUpdated: "Misskeyが更新されました"
whatIsNew: "更新情報を見る"
translate: "翻訳"
translatedFrom: "{x}から翻訳"
accountDeletionInProgress: "アカウントの削除が進行中です"
_accountDelete:
accountDelete: "アカウントの削除"
mayTakeTime: "アカウントの削除は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。"
sendEmail: "アカウントの削除が完了する際は、登録してあったメールアドレス宛に通知を送信します。"
requestAccountDelete: "アカウント削除をリクエスト"
started: "削除処理が開始されました。"
inProgress: "削除が進行中"
_docs:
continueReading: "続きを読む"
features: "機能"
generalTopics: "一般的なトピック"
advancedTopics: "高度なトピック"
admin: "管理"
translateWarn: "このドキュメントは翻訳されたものです。オリジナルとは内容が異なる場合があります。"
_ad:
back: "戻る"
@ -872,6 +901,8 @@ _mfm:
blurDescription: "内容をぼかすことができます。ポインターを上に乗せるとはっきり見えるようになります。"
font: "フォント"
fontDescription: "内容のフォントを指定することができます。"
rainbow: "レインボー"
rainbowDescription: "内容をレインボーにします。"
_reversi:
reversi: "リバーシ"

View File

@ -7,6 +7,7 @@ search: "探す"
notifications: "通知"
username: "ユーザー名"
password: "パスワード"
forgotPassword: "パスワード忘れてん"
fetchingAsApObject: "今ちと連合に照会しとるで"
ok: "OKや"
gotIt: "ほい"
@ -127,6 +128,7 @@ editWidgets: "ウィジェットをいじる"
editWidgetsExit: "編集終ったで"
customEmojis: "カスタム絵文字"
emoji: "絵文字"
emojis: "絵文字"
emojiName: "絵文字名"
emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
@ -138,6 +140,7 @@ flagAsBotDescription: "もしこのアカウントがプログラムによって
flagAsCat: "Catやで"
flagAsCatDescription: "ワレ、猫ちゃんならこのフラグをつけてみ?"
autoAcceptFollowed: "フォローしとるユーザーからのフォローリクエストを勝手に許可しとく"
addAccount: "アカウントを追加"
loginFailed: "ログインに失敗してしもうた…"
showOnRemote: "リモートで見る"
general: "全般"
@ -277,6 +280,7 @@ emptyDrive: "ドライブにはなんも残っとらん"
emptyFolder: "ふぉろだーにはなんも残っとらん"
unableToDelete: "消そうおもってんけどな、あかんかったわ"
inputNewFileName: "今度のファイル名は何にするん?"
inputNewDescription: "新しいキャプションを入力しましょ"
inputNewFolderName: "今度のフォルダ名は何にするん?"
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーや。"
hasChildFilesOrFolders: "このフォルダ、まだなんか入っとるから消されへん"
@ -647,6 +651,10 @@ high: "高い"
middle: "中"
low: "低い"
global: "グローバル"
sent: "送信"
hashtags: "ハッシュタグ"
_docs:
admin: "管理"
_ad:
back: "戻る"
_gallery:

View File

@ -7,7 +7,9 @@ username: "Isem n umseqdac"
password: "Awal uffir"
ok: "IH"
settings: "Iɣewwaṛen"
otherSettings: "Iɣewwaren nniḍen"
profile: "Amaɣnu"
signup: "Jerred"
save: "Sekles"
delete: "Kkes"
addToList: "Rnu ɣer tebdart"
@ -27,15 +29,31 @@ followers: "Imeḍfaṛen"
followsYou: "Yeṭṭafaṛ-ik·em-id"
createList: "Snulfu-d tabdart"
enterListName: "Isem n tebdart"
privacy: "Tabaḍnit"
follow: "Ḍfeṛ"
you: "Kečči·mmi"
selectList: "Fren tabdart"
youHaveNoLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
security: "Taɣellist"
remove: "Kkes"
userList: "Tibdarin"
securityKey: "Tasarutt n tɣellist"
securityKeyName: "Isem n tsarutt"
signinRequired: "Ttxil jerred"
signinWith: "Tuqqna s {x}"
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
uiLanguage: "Tutlayt n wegrudem"
accountSettings: "Iɣewwaṛen n umiḍan"
plugins: "Izegrar"
email: "Imayl"
emailAddress: "Tansa imayl"
smtpUser: "Isem n umseqdac"
smtpPass: "Awal uffir"
other: "Wiyyaḍ"
accountInfo: "Talɣut n umiḍan"
emailNotification: "Ilɣa imayl"
selectAccount: "Fren amiḍan"
accounts: "Imiḍan"
_email:
_follow:
title: "Yeṭṭafaṛ-ik·em-id"
@ -48,6 +66,8 @@ _theme:
mention: "Bder"
_sfx:
notification: "Ilɣuyen"
_permissions:
"write:account": "Ẓreg talɣut n umiḍan-ik·im"
_widgets:
notifications: "Ilɣuyen"
_cw:

View File

@ -128,6 +128,7 @@ editWidgets: "위젯 편집"
editWidgetsExit: "편집 종료"
customEmojis: "커스텀 이모지"
emoji: "이모지"
emojis: "이모지"
emojiName: "이모지 이름"
emojiUrl: "이모지 URL"
addEmoji: "이모지 추가"
@ -528,6 +529,7 @@ removeAllFollowing: "모든 팔로잉 해제"
removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요."
userSuspended: "이 계정은 정지된 상태입니다."
userSilenced: "이 계정은 사일런스된 상태입니다."
menu: "메뉴"
divider: "구분선"
addItem: "항목 추가"
rooms: "방"
@ -760,7 +762,28 @@ middle: "보통"
low: "낮음"
emailNotConfiguredWarning: "메일 주소가 설정되어 있지 않습니다."
ratio: "비율"
customCss: "CSS 사용자화"
customCssWarn: "이 설정은 기능을 알고 있는 경우에만 사용해야 합니다. 잘못된 값을 입력하면 클라이언트가 정상적으로 작동하지 않을 수 있습니다."
global: "글로벌"
squareAvatars: "프로필 아이콘을 사각형으로 표시"
sent: "전송"
received: "수신"
searchResult: "검색 결과"
hashtags: "해시태그"
troubleshooting: "문제 해결"
useBlurEffect: "UI에 흐림 효과 사용"
learnMore: "자세히"
misskeyUpdated: "Misskey가 업데이트 되었습니다!"
whatIsNew: "패치 정보 보기"
translate: "번역"
translatedFrom: "{x}에서 번역"
_docs:
continueReading: "계속 읽기"
features: "기능"
generalTopics: "일반 주제"
advancedTopics: "심화 주제"
admin: "관리"
translateWarn: "이 문서는 번역되었기 때문에 원본과는 내용이 다를 수 있습니다."
_ad:
back: "뒤로"
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
@ -859,6 +882,8 @@ _mfm:
blurDescription: "내용이 흐리게 보입니다. 마우스를 위에 올려두면 내용이 보입니다."
font: "폰트"
fontDescription: "내용의 글꼴을 지정할 수 있습니다."
rainbow: "무지개"
rainbowDescription: "내용을 무지개로 표시합니다."
_reversi:
reversi: "리버시"
gameSettings: "대국 설정"
@ -911,6 +936,9 @@ _channel:
usersCount: "{n}명 참여 중"
notesCount: "{n}노트"
_menuDisplay:
sideFull: "가로"
sideIcon: "가로(아이콘)"
top: "상단"
hide: "숨기기"
_wordMute:
muteWords: "뮤트할 단어"

View File

@ -128,6 +128,7 @@ editWidgets: "Edytuj widżet"
editWidgetsExit: "Gotowe"
customEmojis: "Niestandardowe emoji"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Nazwa emoji"
emojiUrl: "Adres URL emoji"
addEmoji: "Dodaj emoji"
@ -735,6 +736,10 @@ low: "Niski"
emailNotConfiguredWarning: "Nie podano adresu e-mail"
ratio: "Stosunek"
global: "Globalna"
sent: "Wyślij"
hashtags: "Hashtag"
_docs:
admin: "Zarządzanie"
_ad:
back: "Wróć"
reduceFrequencyOfThisAd: "Pokazuj tę reklamę rzadziej"

View File

@ -128,6 +128,7 @@ editWidgets: "Редактировать виджеты"
editWidgetsExit: "Готово"
customEmojis: "Эмодзи пользователя"
emoji: "Эмодзи"
emojis: "Эмодзи"
emojiName: "Название эмодзи"
emojiUrl: "URL эмодзи"
addEmoji: "Добавить эмодзи"
@ -528,6 +529,7 @@ removeAllFollowing: "Удалить всех подписчиков"
removeAllFollowingDescription: "Отменить все подписки с домена {host}? Пожалуйста, применяйте это действие, если инстанс больше не существует."
userSuspended: "Эта учётная запись заморожена"
userSilenced: "Этот пользователь был заглушен"
menu: "Меню"
divider: "Линия-разделитель"
addItem: "Добавить элемент"
rooms: "Комната"
@ -760,7 +762,26 @@ middle: "Средне"
low: "Низкий"
emailNotConfiguredWarning: "Не указан адрес электронной почты"
ratio: "Соотношение"
customCss: "Индивидуальный CSS"
customCssWarn: "Используйте эту настройку только если знаете, что делаете. Ошибки здесь чреваты тем, что сайт перестанет нормально работать у вас."
global: "Всеобщая"
squareAvatars: "Квадратные аватарки"
sent: "Отправить"
received: "Получено"
searchResult: "Результаты поиска"
hashtags: "Хэштег"
troubleshooting: "Разрешение проблем"
useBlurEffect: "Размытие в интерфейсе"
learnMore: "Подробнее"
misskeyUpdated: "Misskey обновился!"
whatIsNew: "Что новенького?"
_docs:
continueReading: "Читать подробнее"
features: "Возможности"
generalTopics: "Основные темы"
advancedTopics: "Дополнительные темы"
admin: "Управление"
translateWarn: "Это перевод документа. Он может неточно отражать содержимое оригинала."
_ad:
back: "Выход"
reduceFrequencyOfThisAd: "Реже показывать эту рекламу"
@ -859,6 +880,8 @@ _mfm:
blurDescription: "Размывает текст до нечитаемости, будто его поместили за матовое стекло. Наведение указателя мыши на размытый текст возвращает чёткость."
font: "Шрифт"
fontDescription: "Так можно писать произвольным шрифтом."
rainbow: "Радуга"
rainbowDescription: "Заставлять содержимое отображаться в цветах радуги."
_reversi:
reversi: "Реверси"
gameSettings: "Настройки игры"
@ -911,6 +934,9 @@ _channel:
usersCount: "Участников: {n}"
notesCount: "Заметок: {n}"
_menuDisplay:
sideFull: "Сторона"
sideIcon: "Сторона (иконки)"
top: "Вверх"
hide: "Спрятать"
_wordMute:
muteWords: "Скрыть слово"

View File

@ -127,6 +127,7 @@ editWidgets: "Редагувати віджети"
editWidgetsExit: "Готово"
customEmojis: "Кастомні емоджі"
emoji: "Емоджі"
emojis: "Емоджі"
emojiName: "Назва емоджі"
emojiUrl: "URL емодзі"
addEmoji: "Додати емодзі"
@ -689,6 +690,10 @@ administration: "Управління"
expiration: "Опитування закінчується"
middle: "Середній"
global: "Глобальна"
sent: "Відправити"
hashtags: "Хештеґ"
_docs:
admin: "Управління"
_ad:
back: "Назад"
_gallery:

View File

@ -128,6 +128,7 @@ editWidgets: "编辑小工具"
editWidgetsExit: "完成编辑"
customEmojis: "自定义表情符号"
emoji: "表情符号"
emojis: "表情符号"
emojiName: "表情符号名称"
emojiUrl: "表情符号地址"
addEmoji: "添加表情符号"
@ -765,6 +766,24 @@ customCss: "自定义 CSS"
customCssWarn: "这些设置必须有相关的基础知识,不当的配置可能导致客户端无法正常使用!"
global: "全局"
squareAvatars: "显示方形头像图标"
sent: "发送"
received: "收取"
searchResult: "搜索结果"
hashtags: "话题标签"
troubleshooting: "故障排除"
useBlurEffect: "在UI上使用模糊效果"
learnMore: "更多信息"
misskeyUpdated: "Misskey更新完成"
whatIsNew: "显示更新信息"
translate: "翻译"
translatedFrom: "从 {x} 翻译"
_docs:
continueReading: "继续阅读"
features: "特性"
generalTopics: "通常提示"
advancedTopics: "进阶提示"
admin: "管理"
translateWarn: "本文档是翻译后的文档。内容可能与原文有所不同。"
_ad:
back: "返回"
reduceFrequencyOfThisAd: "减少此广告的频率"
@ -863,6 +882,8 @@ _mfm:
blurDescription: "产生模糊效果。将鼠标指针放在上面即可将内容显示出来。"
font: "字体"
fontDescription: "可以设置内容所使用的字体。"
rainbow: "彩虹"
rainbowDescription: "用彩虹色来显示内容。"
_reversi:
reversi: "黑白棋"
gameSettings: "对局设置"

View File

@ -128,6 +128,7 @@ editWidgets: "編輯小工具"
editWidgetsExit: "完成"
customEmojis: "自訂表情符號"
emoji: "表情符號"
emojis: "表情符號"
emojiName: "表情符號名稱"
emojiUrl: "表情符號URL"
addEmoji: "加入表情符號"
@ -751,6 +752,10 @@ low: "低"
emailNotConfiguredWarning: "沒有設定電子郵件地址"
ratio: "%"
global: "公開"
sent: "發送"
hashtags: "#tag"
_docs:
admin: "管理"
_ad:
back: "返回"
reduceFrequencyOfThisAd: "降低此廣告的頻率 "

View File

@ -0,0 +1,182 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class chartReindex1629004542760 implements MigrationInterface {
name = 'chartReindex1629004542760'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DELETE FROM "__chart__active_users" a USING "__chart__active_users" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__drive" a USING "__chart__drive" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__federation" a USING "__chart__federation" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__hashtag" a USING "__chart__hashtag" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__instance" a USING "__chart__instance" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__network" a USING "__chart__network" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__notes" a USING "__chart__notes" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_drive" a USING "__chart__per_user_drive" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_following" a USING "__chart__per_user_following" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_notes" a USING "__chart__per_user_notes" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__per_user_reaction" a USING "__chart__per_user_reaction" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__test_grouped" a USING "__chart__test_grouped" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__test_unique" a USING "__chart__test_unique" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DELETE FROM "__chart__users" a USING "__chart__users" b WHERE a.id < b.id AND ((a.group IS NULL AND b.group IS NULL) OR a.group = b.group) AND a.date = b.date;`);
await queryRunner.query(`DROP INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc"`);
await queryRunner.query(`DROP INDEX "IDX_00ed5f86db1f7efafb1978bf21"`);
await queryRunner.query(`DROP INDEX "IDX_9a3ed15a30ab7e3a37702e6e08"`);
await queryRunner.query(`DROP INDEX "IDX_13565815f618a1ff53886c5b28"`);
await queryRunner.query(`DROP INDEX "IDX_7a170f67425e62a8fabb76c872"`);
await queryRunner.query(`DROP INDEX "IDX_3313d7288855ec105b5bbf6c21"`);
await queryRunner.query(`DROP INDEX "IDX_36cb699c49580d4e6c2e6159f9"`);
await queryRunner.query(`DROP INDEX "IDX_76e87c7bfc5d925fcbba405d84"`);
await queryRunner.query(`DROP INDEX "IDX_dd907becf76104e4b656659e6b"`);
await queryRunner.query(`DROP INDEX "IDX_07747a1038c05f532a718fe1de"`);
await queryRunner.query(`DROP INDEX "IDX_99a7d2faaef84a6f728d714ad6"`);
await queryRunner.query(`DROP INDEX "IDX_25a97c02003338124b2b75fdbc"`);
await queryRunner.query(`DROP INDEX "IDX_6b8f34a1a64b06014b6fb66824"`);
await queryRunner.query(`DROP INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63"`);
await queryRunner.query(`DROP INDEX "IDX_39ee857ab2f23493037c6b6631"`);
await queryRunner.query(`DROP INDEX "IDX_a1efd3e0048a5f2793a47360dc"`);
await queryRunner.query(`DROP INDEX "IDX_7b5da130992ec9df96712d4290"`);
await queryRunner.query(`DROP INDEX "IDX_0a905b992fecd2b5c3fb98759e"`);
await queryRunner.query(`DROP INDEX "IDX_42eb716a37d381cdf566192b2b"`);
await queryRunner.query(`DROP INDEX "IDX_7036f2957151588b813185c794"`);
await queryRunner.query(`DROP INDEX "IDX_f09d543e3acb16c5976bdb31fa"`);
await queryRunner.query(`DROP INDEX "IDX_5f86db6492274e07c1a3cdf286"`);
await queryRunner.query(`DROP INDEX "IDX_e496ca8096d28f6b9b509264dc"`);
await queryRunner.query(`DROP INDEX "IDX_30bf67687f483ace115c5ca642"`);
await queryRunner.query(`DROP INDEX "IDX_7af07790712aa3438ff6773f3b"`);
await queryRunner.query(`DROP INDEX "IDX_4b3593098b6edc9c5afe36b18b"`);
await queryRunner.query(`DROP INDEX "IDX_b77d4dd9562c3a899d9a286fcd"`);
await queryRunner.query(`DROP INDEX "IDX_84234bd1abb873f07329681c83"`);
await queryRunner.query(`DROP INDEX "IDX_55bf20f366979f2436de99206b"`);
await queryRunner.query(`DROP INDEX "IDX_5048e9daccbbbc6d567bb142d3"`);
await queryRunner.query(`DROP INDEX "IDX_f7bf4c62059764c2c2bb40fdab"`);
await queryRunner.query(`DROP INDEX "IDX_8cf3156fd7a6b15c43459c6e3b"`);
await queryRunner.query(`DROP INDEX "IDX_229a41ad465f9205f1f5703291"`);
await queryRunner.query(`DROP INDEX "IDX_0c641990ecf47d2545df4edb75"`);
await queryRunner.query(`DROP INDEX "IDX_234dff3c0b56a6150b95431ab9"`);
await queryRunner.query(`DROP INDEX "IDX_b14489029e4b3aaf4bba5fb524"`);
await queryRunner.query(`DROP INDEX "IDX_437bab3c6061d90f6bb65fd2cc"`);
await queryRunner.query(`DROP INDEX "IDX_bbfa573a8181018851ed0b6357"`);
await queryRunner.query(`DROP INDEX "IDX_a0cd75442dd10d0643a17c4a49"`);
await queryRunner.query(`DROP INDEX "IDX_b070a906db04b44c67c6c2144d"`);
await queryRunner.query(`DROP INDEX "IDX_d41cce6aee1a50bfc062038f9b"`);
await queryRunner.query(`DROP INDEX "IDX_a319e5dbf47e8a17497623beae"`);
await queryRunner.query(`DROP INDEX "IDX_845254b3eaf708ae8a6cac3026"`);
await queryRunner.query(`DROP INDEX "IDX_ed9b95919c672a13008e9487ee"`);
await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_9a3ed15a30ab7e3a37702e6e08" ON "__chart__active_users" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_60c5c6e7e538c09aa274ecd1cf" ON "__chart__active_users" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_3313d7288855ec105b5bbf6c21" ON "__chart__drive" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ceab80a6729f8e2e6f5b8a1a3d" ON "__chart__drive" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dd907becf76104e4b656659e6b" ON "__chart__federation" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_eddfed8fb40305a04c6f941050" ON "__chart__federation" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_25a97c02003338124b2b75fdbc" ON "__chart__hashtag" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_53a3604b939e2b479eb2cfaac8" ON "__chart__hashtag" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_39ee857ab2f23493037c6b6631" ON "__chart__instance" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_8111b817b9818c04d7eb8475b1" ON "__chart__instance" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0a905b992fecd2b5c3fb98759e" ON "__chart__network" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_2082327b2699ce924fa654afc5" ON "__chart__network" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_f09d543e3acb16c5976bdb31fa" ON "__chart__notes" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_e60c358aaced5aab8900a4af31" ON "__chart__notes" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_30bf67687f483ace115c5ca642" ON "__chart__per_user_drive" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a9a806d466b314f253a1a611c4" ON "__chart__per_user_drive" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_b77d4dd9562c3a899d9a286fcd" ON "__chart__per_user_following" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dabbb38a51ab86ee3cab291326" ON "__chart__per_user_following" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5048e9daccbbbc6d567bb142d3" ON "__chart__per_user_notes" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_583a157ed0cf0ed1b5ec2a833f" ON "__chart__per_user_notes" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_229a41ad465f9205f1f5703291" ON "__chart__per_user_reaction" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_3b7697a96f522d0478972e6d6f" ON "__chart__per_user_reaction" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_b14489029e4b3aaf4bba5fb524" ON "__chart__test_grouped" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_da522b4008a9f5d7743b87ad55" ON "__chart__test_grouped" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a0cd75442dd10d0643a17c4a49" ON "__chart__test_unique" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_16effb2e888f6763673b579f80" ON "__chart__test_unique" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a319e5dbf47e8a17497623beae" ON "__chart__test" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_dab383a36f3c9db4a0c9b02cf3" ON "__chart__test" ("date") WHERE "group" IS NULL`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_337e9599f278bd7537fe30876f" ON "__chart__users" ("date", "group") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_66feba81e1795d176d06c0b1e6" ON "__chart__users" ("date") WHERE "group" IS NULL`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX "IDX_66feba81e1795d176d06c0b1e6"`);
await queryRunner.query(`DROP INDEX "IDX_337e9599f278bd7537fe30876f"`);
await queryRunner.query(`DROP INDEX "IDX_dab383a36f3c9db4a0c9b02cf3"`);
await queryRunner.query(`DROP INDEX "IDX_a319e5dbf47e8a17497623beae"`);
await queryRunner.query(`DROP INDEX "IDX_16effb2e888f6763673b579f80"`);
await queryRunner.query(`DROP INDEX "IDX_a0cd75442dd10d0643a17c4a49"`);
await queryRunner.query(`DROP INDEX "IDX_da522b4008a9f5d7743b87ad55"`);
await queryRunner.query(`DROP INDEX "IDX_b14489029e4b3aaf4bba5fb524"`);
await queryRunner.query(`DROP INDEX "IDX_3b7697a96f522d0478972e6d6f"`);
await queryRunner.query(`DROP INDEX "IDX_229a41ad465f9205f1f5703291"`);
await queryRunner.query(`DROP INDEX "IDX_583a157ed0cf0ed1b5ec2a833f"`);
await queryRunner.query(`DROP INDEX "IDX_5048e9daccbbbc6d567bb142d3"`);
await queryRunner.query(`DROP INDEX "IDX_dabbb38a51ab86ee3cab291326"`);
await queryRunner.query(`DROP INDEX "IDX_b77d4dd9562c3a899d9a286fcd"`);
await queryRunner.query(`DROP INDEX "IDX_a9a806d466b314f253a1a611c4"`);
await queryRunner.query(`DROP INDEX "IDX_30bf67687f483ace115c5ca642"`);
await queryRunner.query(`DROP INDEX "IDX_e60c358aaced5aab8900a4af31"`);
await queryRunner.query(`DROP INDEX "IDX_f09d543e3acb16c5976bdb31fa"`);
await queryRunner.query(`DROP INDEX "IDX_2082327b2699ce924fa654afc5"`);
await queryRunner.query(`DROP INDEX "IDX_0a905b992fecd2b5c3fb98759e"`);
await queryRunner.query(`DROP INDEX "IDX_8111b817b9818c04d7eb8475b1"`);
await queryRunner.query(`DROP INDEX "IDX_39ee857ab2f23493037c6b6631"`);
await queryRunner.query(`DROP INDEX "IDX_53a3604b939e2b479eb2cfaac8"`);
await queryRunner.query(`DROP INDEX "IDX_25a97c02003338124b2b75fdbc"`);
await queryRunner.query(`DROP INDEX "IDX_eddfed8fb40305a04c6f941050"`);
await queryRunner.query(`DROP INDEX "IDX_dd907becf76104e4b656659e6b"`);
await queryRunner.query(`DROP INDEX "IDX_ceab80a6729f8e2e6f5b8a1a3d"`);
await queryRunner.query(`DROP INDEX "IDX_3313d7288855ec105b5bbf6c21"`);
await queryRunner.query(`DROP INDEX "IDX_60c5c6e7e538c09aa274ecd1cf"`);
await queryRunner.query(`DROP INDEX "IDX_9a3ed15a30ab7e3a37702e6e08"`);
await queryRunner.query(`DROP INDEX "IDX_a9021cc2e1feb5f72d3db6e9f5"`);
await queryRunner.query(`DROP INDEX "IDX_f22169eb10657bded6d875ac8f"`);
await queryRunner.query(`DROP INDEX "IDX_c8cc87bd0f2f4487d17c651fbf"`);
await queryRunner.query(`DROP INDEX "IDX_754499f9b2642336433769518d"`);
await queryRunner.query(`DROP INDEX "IDX_315c779174fe8247ab324f036e"`);
await queryRunner.query(`DROP INDEX "IDX_c5d46cbfda48b1c33ed852e21b"`);
await queryRunner.query(`CREATE INDEX "IDX_337e9599f278bd7537fe30876f" ON "__chart__users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_ed9b95919c672a13008e9487ee" ON "__chart__users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_845254b3eaf708ae8a6cac3026" ON "__chart__users" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_a319e5dbf47e8a17497623beae" ON "__chart__test" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_d41cce6aee1a50bfc062038f9b" ON "__chart__test" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_b070a906db04b44c67c6c2144d" ON "__chart__test" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_a0cd75442dd10d0643a17c4a49" ON "__chart__test_unique" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_bbfa573a8181018851ed0b6357" ON "__chart__test_unique" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_437bab3c6061d90f6bb65fd2cc" ON "__chart__test_unique" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_b14489029e4b3aaf4bba5fb524" ON "__chart__test_grouped" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_234dff3c0b56a6150b95431ab9" ON "__chart__test_grouped" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_0c641990ecf47d2545df4edb75" ON "__chart__test_grouped" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_229a41ad465f9205f1f5703291" ON "__chart__per_user_reaction" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_8cf3156fd7a6b15c43459c6e3b" ON "__chart__per_user_reaction" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_f7bf4c62059764c2c2bb40fdab" ON "__chart__per_user_reaction" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_5048e9daccbbbc6d567bb142d3" ON "__chart__per_user_notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_55bf20f366979f2436de99206b" ON "__chart__per_user_notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_84234bd1abb873f07329681c83" ON "__chart__per_user_notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_b77d4dd9562c3a899d9a286fcd" ON "__chart__per_user_following" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_4b3593098b6edc9c5afe36b18b" ON "__chart__per_user_following" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_7af07790712aa3438ff6773f3b" ON "__chart__per_user_following" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_30bf67687f483ace115c5ca642" ON "__chart__per_user_drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_e496ca8096d28f6b9b509264dc" ON "__chart__per_user_drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_5f86db6492274e07c1a3cdf286" ON "__chart__per_user_drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_f09d543e3acb16c5976bdb31fa" ON "__chart__notes" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7036f2957151588b813185c794" ON "__chart__notes" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_42eb716a37d381cdf566192b2b" ON "__chart__notes" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_0a905b992fecd2b5c3fb98759e" ON "__chart__network" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7b5da130992ec9df96712d4290" ON "__chart__network" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_a1efd3e0048a5f2793a47360dc" ON "__chart__network" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_39ee857ab2f23493037c6b6631" ON "__chart__instance" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_da8a46ba84ca1d8bb5a29bfb63" ON "__chart__instance" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_6b8f34a1a64b06014b6fb66824" ON "__chart__instance" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_25a97c02003338124b2b75fdbc" ON "__chart__hashtag" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_99a7d2faaef84a6f728d714ad6" ON "__chart__hashtag" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_07747a1038c05f532a718fe1de" ON "__chart__hashtag" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_dd907becf76104e4b656659e6b" ON "__chart__federation" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_76e87c7bfc5d925fcbba405d84" ON "__chart__federation" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_36cb699c49580d4e6c2e6159f9" ON "__chart__federation" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_3313d7288855ec105b5bbf6c21" ON "__chart__drive" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_7a170f67425e62a8fabb76c872" ON "__chart__drive" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_13565815f618a1ff53886c5b28" ON "__chart__drive" ("date") `);
await queryRunner.query(`CREATE INDEX "IDX_9a3ed15a30ab7e3a37702e6e08" ON "__chart__active_users" ("date", "group") `);
await queryRunner.query(`CREATE INDEX "IDX_00ed5f86db1f7efafb1978bf21" ON "__chart__active_users" ("group") `);
await queryRunner.query(`CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `);
}
}

View File

@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class deeplIntegration1629024377804 implements MigrationInterface {
name = 'deeplIntegration1629024377804'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" ADD "deeplAuthKey" character varying(128)`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`);
}
}

View File

@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class fixChannelUserId1629288472000 implements MigrationInterface {
name = 'fixChannelUserId1629288472000'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "userId" DROP NOT NULL;`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`);
}
}

View File

@ -0,0 +1,15 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class isUserDeleted1629512953000 implements MigrationInterface {
name = 'isUserDeleted1629512953000'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "user" ADD "isDeleted" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`COMMENT ON COLUMN "user"."isDeleted" IS 'Whether the User is deleted.'`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isDeleted"`);
}
}

View File

@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.84.3",
"version": "12.89.0",
"codename": "indigo",
"repository": {
"type": "git",
@ -10,7 +10,8 @@
"main": "./index.js",
"private": true,
"scripts": {
"start": "node ./index.js",
"start": "node --experimental-json-modules ./index.js",
"start:test": "cross-env NODE_ENV=test node --experimental-json-modules ./index.js",
"init": "npm run migrate",
"ormconfig": "node ./built/ormconfig.js",
"migrate": "ts-node ./node_modules/typeorm/cli.js migration:run",
@ -26,6 +27,9 @@
"clean": "gulp clean",
"cleanall": "gulp cleanall",
"lint": "tslint 'src/**/*.ts'",
"cy:open": "cypress open",
"cy:run": "cypress run",
"e2e": "start-server-and-test start:test http://localhost cy:run",
"test": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
"format": "gulp format"
},
@ -34,7 +38,6 @@
"lodash": "^4.17.21"
},
"dependencies": {
"@babel/plugin-transform-runtime": "7.14.5",
"@elastic/elasticsearch": "7.11.0",
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
@ -44,7 +47,7 @@
"@sinonjs/fake-timers": "7.1.2",
"@syuilo/aiscript": "0.11.1",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.15.2",
"@types/bull": "3.15.3",
"@types/cbor": "6.0.0",
"@types/dateformat": "3.0.1",
"@types/escape-regexp": "0.0.0",
@ -57,8 +60,8 @@
"@types/jsonld": "1.5.6",
"@types/katex": "0.11.1",
"@types/koa": "2.13.4",
"@types/koa-bodyparser": "4.3.2",
"@types/koa-cors": "0.0.1",
"@types/koa-bodyparser": "4.3.3",
"@types/koa-cors": "0.0.2",
"@types/koa-favicon": "2.0.21",
"@types/koa-logger": "3.1.1",
"@types/koa-mount": "4.0.0",
@ -68,10 +71,10 @@
"@types/koa__multer": "2.0.3",
"@types/koa__router": "8.0.7",
"@types/markdown-it": "12.0.3",
"@types/matter-js": "0.17.3",
"@types/matter-js": "0.17.5",
"@types/mocha": "8.2.3",
"@types/node": "16.3.3",
"@types/node-fetch": "2.5.11",
"@types/node": "16.6.2",
"@types/node-fetch": "2.5.12",
"@types/nodemailer": "6.4.4",
"@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1",
@ -86,9 +89,9 @@
"@types/redis": "2.8.31",
"@types/rename": "1.0.4",
"@types/request-stats": "3.0.0",
"@types/rimraf": "3.0.1",
"@types/rimraf": "3.0.2",
"@types/seedrandom": "2.4.28",
"@types/sharp": "0.28.4",
"@types/sharp": "0.28.5",
"@types/sinonjs__fake-timers": "6.0.3",
"@types/speakeasy": "2.0.6",
"@types/throttle-debounce": "2.1.0",
@ -98,40 +101,40 @@
"@types/web-push": "3.3.2",
"@types/webpack": "5.28.0",
"@types/webpack-stream": "3.2.12",
"@types/websocket": "1.0.3",
"@types/ws": "7.4.6",
"@typescript-eslint/parser": "4.28.3",
"@vue/compiler-sfc": "3.1.5",
"@types/websocket": "1.0.4",
"@types/ws": "7.4.7",
"@typescript-eslint/parser": "4.29.2",
"@vue/compiler-sfc": "3.2.4",
"abort-controller": "3.0.0",
"apexcharts": "3.27.2",
"apexcharts": "3.27.3",
"autobind-decorator": "2.4.0",
"autosize": "4.0.4",
"autwh": "0.1.0",
"aws-sdk": "2.948.0",
"aws-sdk": "2.966.0",
"bcryptjs": "2.4.3",
"blurhash": "1.1.3",
"broadcast-channel": "3.7.0",
"bull": "3.26.0",
"blurhash": "1.1.4",
"broadcast-channel": "4.2.0",
"bull": "3.28.1",
"cacheable-lookup": "6.0.0",
"cafy": "15.2.1",
"cbor": "7.0.6",
"chalk": "4.1.1",
"cbor": "8.0.0",
"chalk": "4.1.2",
"chart.js": "2.9.4",
"cli-highlight": "2.1.11",
"commander": "7.2.0",
"concurrently": "6.2.0",
"commander": "8.1.0",
"compare-versions": "3.6.0",
"concurrently": "6.2.1",
"content-disposition": "0.5.3",
"core-js": "3.15.2",
"crc-32": "1.2.0",
"css-loader": "6.0.0",
"cssnano": "5.0.6",
"css-loader": "6.2.0",
"cssnano": "5.0.8",
"dateformat": "4.5.1",
"diskusage": "1.1.3",
"escape-regexp": "0.0.1",
"eslint": "7.30.0",
"eslint-plugin-vue": "7.13.0",
"eslint": "7.32.0",
"eslint-plugin-vue": "7.16.0",
"eventemitter3": "4.0.7",
"feed": "4.2.2",
"file-type": "16.5.1",
"file-type": "16.5.3",
"fluent-ffmpeg": "2.1.2",
"glob": "7.1.7",
"got": "11.8.2",
@ -141,22 +144,18 @@
"gulp-replace": "1.1.3",
"gulp-terser": "2.0.1",
"gulp-tslint": "8.1.4",
"hard-source-webpack-plugin": "0.13.1",
"html-minifier": "4.0.0",
"http-proxy-agent": "4.0.1",
"hpagent": "0.1.2",
"http-signature": "1.3.5",
"https-proxy-agent": "5.0.0",
"idb-keyval": "5.0.6",
"idb-keyval": "5.1.3",
"insert-text-at-cursor": "0.3.0",
"is-root": "2.1.0",
"is-svg": "4.3.1",
"js-yaml": "4.1.0",
"jsdom": "16.6.0",
"jsdom": "16.7.0",
"json5": "2.2.0",
"json5-loader": "4.0.1",
"jsonld": "5.2.0",
"jsrsasign": "8.0.20",
"katex": "0.13.11",
"katex": "0.13.13",
"koa": "2.13.1",
"koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0",
@ -167,30 +166,26 @@
"koa-slow": "2.1.0",
"koa-views": "7.0.1",
"langmap": "0.0.16",
"lookup-dns-cache": "2.1.0",
"markdown-it": "12.1.0",
"markdown-it": "12.2.0",
"markdown-it-anchor": "7.1.0",
"matter-js": "0.17.1",
"mfm-js": "0.19.0",
"misskey-js": "0.0.6",
"mocha": "8.4.0",
"moji": "0.5.1",
"ms": "2.1.3",
"multer": "1.4.2",
"multer": "1.4.3",
"nested-property": "4.0.0",
"node-fetch": "2.6.1",
"nodemailer": "6.6.3",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
"parse5": "6.0.1",
"pg": "8.6.0",
"pg": "8.7.1",
"portscanner": "2.2.0",
"postcss": "8.3.5",
"postcss": "8.3.6",
"postcss-loader": "6.1.1",
"prismjs": "1.24.1",
"probe-image-size": "7.2.1",
"promise-limit": "2.7.0",
"promise-sequential": "1.1.1",
"pug": "3.0.2",
"punycode": "2.1.1",
"pureimage": "0.3.2",
@ -198,67 +193,62 @@
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
"re2": "1.16.0",
"reconnecting-websocket": "4.4.0",
"redis": "3.1.2",
"redis-lock": "0.1.4",
"reflect-metadata": "0.1.13",
"regenerator-runtime": "0.13.7",
"rename": "1.0.4",
"request-stats": "3.0.0",
"require-all": "3.0.0",
"rimraf": "3.0.2",
"rndstr": "1.0.0",
"s-age": "1.1.2",
"sass": "1.35.2",
"sass": "1.38.0",
"sass-loader": "12.1.0",
"seedrandom": "3.0.5",
"sharp": "0.28.3",
"sharp": "0.29.0",
"speakeasy": "2.0.0",
"stringz": "2.1.0",
"style-loader": "3.1.0",
"summaly": "2.4.0",
"style-loader": "3.2.1",
"summaly": "2.4.1",
"syslog-pro": "1.0.0",
"systeminformation": "5.7.7",
"systeminformation": "5.8.0",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.117.1",
"throttle-debounce": "3.0.1",
"tinycolor2": "1.4.2",
"tmp": "0.2.1",
"ts-loader": "9.2.3",
"ts-node": "10.1.0",
"tsc-alias": "1.3.7",
"ts-loader": "9.2.5",
"ts-node": "10.2.1",
"tsc-alias": "1.3.9",
"tsconfig-paths": "3.10.1",
"tslint": "6.1.3",
"tslint-sonarts": "1.9.0",
"twemoji-parser": "13.1.0",
"typeorm": "0.2.32",
"typeorm": "0.2.37",
"typescript": "4.3.5",
"ulid": "2.3.0",
"uuid": "8.3.2",
"v-debounce": "0.1.2",
"vanilla-tilt": "1.7.0",
"vue": "3.1.5",
"vue-color": "2.8.1",
"vue-json-pretty": "1.8.1",
"vue-loader": "16.3.1",
"vue": "3.2.4",
"vue-loader": "16.5.0",
"vue-prism-editor": "2.0.0-alpha.2",
"vue-router": "4.0.5",
"vue-style-loader": "4.1.3",
"vue-svg-loader": "0.17.0-beta.2",
"vuedraggable": "4.0.1",
"web-push": "3.4.5",
"webpack": "5.45.1",
"webpack-cli": "4.7.2",
"webpack": "5.51.0",
"webpack-cli": "4.8.0",
"websocket": "1.0.34",
"ws": "7.5.3",
"ws": "8.2.0",
"xev": "2.0.1"
},
"devDependencies": {
"@redocly/openapi-core": "1.0.0-beta.44",
"@types/chai": "4.2.16",
"@redocly/openapi-core": "1.0.0-beta.54",
"@types/fluent-ffmpeg": "2.1.17",
"chai": "4.3.4",
"cross-env": "7.0.3"
"cross-env": "7.0.3",
"cypress": "8.3.0",
"start-server-and-test": "1.13.1"
}
}

View File

@ -1,7 +0,0 @@
declare module 'is-root' {
function isRoot(): boolean;
namespace isRoot {} // Hack
export = isRoot;
}

View File

@ -1,9 +0,0 @@
declare module 'lookup-dns-cache' {
import { LookupOneOptions, LookupAllOptions, LookupOptions, LookupAddress } from 'dns';
function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
function lookup(hostname: string, options: LookupAllOptions, callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void): void;
function lookup(hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family: number) => void): void;
function lookup(hostname: string, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
}

View File

@ -1,24 +1,23 @@
import { Command } from 'commander';
import config from '@/config';
import config from '@/config/index';
const program = new Command();
program
.version(config.version)
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
.option('--disable-clustering', 'Disable clustering')
.option('--only-server', 'Run server only (without job queue processing)')
.option('--only-queue', 'Pocessing job queue only (without server)')
.option('--quiet', 'Suppress all logs')
.option('--verbose', 'Enable all logs')
.option('--with-log-time', 'Include timestamp for each logs')
.option('--slow', 'Delay all requests (for debbuging)')
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
.parse(process.argv);
program.version(config.version);
program.option('--no-daemons', 'Disable daemon processes (for debbuging)');
program.option('--disable-clustering', 'Disable clustering');
program.option('--only-server', 'Run server only (without job queue processing)');
program.option('--only-queue', 'Pocessing job queue only (without server)');
program.option('--quiet', 'Suppress all logs');
program.option('--verbose', 'Enable all logs');
program.option('--with-log-time', 'Include timestamp for each logs');
program.option('--slow', 'Delay all requests (for debbuging)');
program.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.');
program.parse(process.argv);
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
if (process.env.NODE_ENV === 'test') program.disableClustering = true;
if (process.env.NODE_ENV === 'test') program.quiet = true;
//if (process.env.NODE_ENV === 'test') program.quiet = true;
if (process.env.NODE_ENV === 'test') program.noDaemons = true;
export { program };

View File

@ -2,7 +2,7 @@ import * as cluster from 'cluster';
import * as chalk from 'chalk';
import Xev from 'xev';
import Logger from '../services/logger';
import Logger from '@/services/logger';
import { program } from '../argv';
// for typeorm

View File

@ -1,18 +1,25 @@
import * as fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import * as os from 'os';
import * as cluster from 'cluster';
import * as chalk from 'chalk';
import * as portscanner from 'portscanner';
import * as isRoot from 'is-root';
import { getConnection } from 'typeorm';
import Logger from '../services/logger';
import Logger from '@/services/logger';
import loadConfig from '@/config/load';
import { Config } from '@/config/types';
import { lessThan } from '../prelude/array';
import { lessThan } from '@/prelude/array';
import { program } from '../argv';
import { showMachineInfo } from '@/misc/show-machine-info';
import { initDb } from '../db/postgre';
const meta = require('../meta.json');
//const _filename = fileURLToPath(import.meta.url);
const _filename = __filename;
const _dirname = dirname(_filename);
const meta = JSON.parse(fs.readFileSync(`${_dirname}/../meta.json`, 'utf-8'));
const logger = new Logger('core', 'cyan');
const bootLogger = logger.createSubLogger('boot', 'magenta', false);
@ -39,6 +46,11 @@ function greet() {
bootLogger.info(`Misskey v${meta.version}`, null, true);
}
function isRoot() {
// maybe process.getuid will be undefined under not POSIX environment (e.g. Windows)
return process.getuid != null && process.getuid() === 0;
}
/**
* Init master process
*/

View File

@ -1,7 +1,8 @@
import { get, set } from '@client/scripts/idb-proxy';
import { reactive } from 'vue';
import { apiUrl } from '@client/config';
import { waiting } from '@client/os';
import { unisonReload } from '@client/scripts/unison-reload';
import { unisonReload, reloadChannel } from '@client/scripts/unison-reload';
// TODO: 他のタブと永続化されたstateを同期
@ -10,6 +11,7 @@ type Account = {
token: string;
isModerator: boolean;
isAdmin: boolean;
isDeleted: boolean;
};
const data = localStorage.getItem('account');
@ -17,22 +19,45 @@ const data = localStorage.getItem('account');
// TODO: 外部からはreadonlyに
export const $i = data ? reactive(JSON.parse(data) as Account) : null;
export function signout() {
export async function signout() {
waiting();
localStorage.removeItem('account');
//#region Remove account
const accounts = await getAccounts();
accounts.splice(accounts.findIndex(x => x.id === $i.id), 1);
set('accounts', accounts);
//#endregion
//#region Remove push notification registration
try {
const registration = await navigator.serviceWorker.ready;
const push = await registration.pushManager.getSubscription();
if (!push) return;
await fetch(`${apiUrl}/sw/unregister`, {
method: 'POST',
body: JSON.stringify({
i: $i.token,
endpoint: push.endpoint,
}),
});
} catch (e) {}
//#endregion
document.cookie = `igi=; path=/`;
location.href = '/';
if (accounts.length > 0) login(accounts[0].token);
else unisonReload();
}
export function getAccounts() {
const accountsData = localStorage.getItem('accounts');
const accounts: { id: Account['id'], token: Account['token'] }[] = accountsData ? JSON.parse(accountsData) : [];
return accounts;
export async function getAccounts(): Promise<{ id: Account['id'], token: Account['token'] }[]> {
return (await get('accounts')) || [];
}
export function addAccount(id: Account['id'], token: Account['token']) {
const accounts = getAccounts();
export async function addAccount(id: Account['id'], token: Account['token']) {
const accounts = await getAccounts();
if (!accounts.some(x => x.id === id)) {
localStorage.setItem('accounts', JSON.stringify(accounts.concat([{ id, token }])));
await set('accounts', accounts.concat([{ id, token }]));
}
}
@ -47,7 +72,7 @@ function fetchAccount(token): Promise<Account> {
})
.then(res => {
// When failed to authenticate user
if (res.status >= 400 && res.status < 500) {
if (res.status !== 200 && res.status < 500) {
return signout();
}
@ -69,15 +94,22 @@ export function updateAccount(data) {
}
export function refreshAccount() {
fetchAccount($i.token).then(updateAccount);
return fetchAccount($i.token).then(updateAccount);
}
export async function login(token: Account['token']) {
export async function login(token: Account['token'], redirect?: string) {
waiting();
if (_DEV_) console.log('logging as token ', token);
const me = await fetchAccount(token);
localStorage.setItem('account', JSON.stringify(me));
addAccount(me.id, token);
await addAccount(me.id, token);
if (redirect) {
reloadChannel.postMessage('reload');
location.href = redirect;
return;
}
unisonReload();
}

View File

@ -10,9 +10,9 @@
</template>
<div class="dpvffvvy _monolithic_">
<div class="_section">
<MkTextarea v-model:value="comment">
<span>{{ $ts.details }}</span>
<template #desc>{{ $ts.fillAbuseReportDescription }}</template>
<MkTextarea v-model="comment">
<template #label>{{ $ts.details }}</template>
<template #caption>{{ $ts.fillAbuseReportDescription }}</template>
</MkTextarea>
</div>
<div class="_section">

View File

@ -35,6 +35,7 @@ import { twemojiSvgBase } from '@/misc/twemoji-base';
import { getStaticImageUrl } from '@client/scripts/get-static-image-url';
import { acct } from '@client/filters/user';
import * as os from '@client/os';
import { instance } from '@client/instance';
type EmojiDef = {
emoji: string;
@ -75,6 +76,36 @@ for (const x of lib) {
emjdb.sort((a, b) => a.name.length - b.name.length);
//#region Construct Emoji DB
const customEmojis = instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
const emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
export default defineComponent({
props: {
type: {
@ -124,7 +155,6 @@ export default defineComponent({
emojis: [],
items: [],
select: -1,
emojiDb: [] as EmojiDef[]
}
},
@ -144,36 +174,6 @@ export default defineComponent({
mounted() {
this.setPosition();
//#region Construct Emoji DB
const customEmojis = this.$instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
this.emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
this.textarea.addEventListener('keydown', this.onKeydown);
for (const el of Array.from(document.querySelectorAll('body *'))) {
@ -203,6 +203,13 @@ export default defineComponent({
complete(type, value) {
this.$emit('done', { type, value });
this.$emit('closed');
if (type === 'emoji') {
let recents = this.$store.state.recentlyUsedEmojis;
recents = recents.filter((e: any) => e !== value);
recents.unshift(value);
this.$store.set('recentlyUsedEmojis', recents.splice(0, 32));
}
},
setPosition() {
@ -281,29 +288,26 @@ export default defineComponent({
}
} else if (this.type == 'emoji') {
if (this.q == null || this.q == '') {
this.emojis = this.emojiDb.filter(x => x.isCustomEmoji && !x.aliasOf).sort((a, b) => {
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});
// 最近使った絵文字をサジェスト
this.emojis = this.$store.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji == emoji)).filter(x => x != null);
return;
}
const matched = [];
const max = 30;
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.startsWith(this.q) && !x.aliasOf && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
if (matched.length < max) {
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.startsWith(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});
}
if (matched.length < max) {
this.emojiDb.some(x => {
emojiDb.some(x => {
if (x.name.includes(this.q) && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == max;
});

View File

@ -48,15 +48,7 @@ export default defineComponent({
render() {
if (this.items.length === 0) return;
return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? {
class: 'sqadhkmv' + (this.noGap ? ' noGap _block' : ''),
name: 'list',
tag: 'div',
'data-direction': this.direction,
'data-reversed': this.reversed ? 'true' : 'false',
} : {
class: 'sqadhkmv' + (this.noGap ? ' noGap _block' : ''),
}, this.items.map((item, i) => {
const renderChildren = () => this.items.map((item, i) => {
const el = this.$slots.default({
item: item
})[0];
@ -98,7 +90,19 @@ export default defineComponent({
return el;
}
}
}));
});
return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? {
class: 'sqadhkmv' + (this.noGap ? ' noGap' : ''),
name: 'list',
tag: 'div',
'data-direction': this.direction,
'data-reversed': this.reversed ? 'true' : 'false',
} : {
class: 'sqadhkmv' + (this.noGap ? ' noGap' : ''),
}, {
default: renderChildren
});
},
});
</script>

View File

@ -14,8 +14,8 @@
</div>
<header v-if="title"><Mfm :text="title"/></header>
<div class="body" v-if="text"><Mfm :text="text"/></div>
<MkInput v-if="input" v-model:value="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></MkInput>
<MkSelect v-if="select" v-model:value="selectedValue" autofocus>
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></MkInput>
<MkSelect v-if="select" v-model="selectedValue" autofocus>
<template v-if="select.items">
<option v-for="item in select.items" :value="item.value">{{ item.text }}</option>
</template>

View File

@ -114,7 +114,7 @@ export default defineComponent({
if (this.selectMode) {
this.$emit('chosen', this.file);
} else {
os.modalMenu(this.getMenu(), ev.currentTarget || ev.target);
os.popupMenu(this.getMenu(), ev.currentTarget || ev.target);
}
},

View File

@ -10,6 +10,7 @@
<span class="separator" v-if="folder != null"><i class="fas fa-angle-right"></i></span>
<span class="folder current" v-if="folder != null">{{ folder.name }}</span>
</div>
<button @click="showMenu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
</nav>
<div class="main" :class="{ uploading: uploadings.length > 0, fetching }"
ref="main"
@ -627,8 +628,12 @@ export default defineComponent({
}];
},
onContextmenu(e) {
os.contextMenu(this.getMenu(), e);
showMenu(ev) {
os.popupMenu(this.getMenu(), ev.currentTarget || ev.target);
},
onContextmenu(ev) {
os.contextMenu(this.getMenu(), ev);
},
}
});
@ -641,7 +646,7 @@ export default defineComponent({
height: 100%;
> nav {
display: block;
display: flex;
z-index: 2;
width: 100%;
padding: 0 8px;
@ -696,6 +701,10 @@ export default defineComponent({
}
}
}
> .menu {
margin-left: auto;
}
}
> .main {

View File

@ -1,17 +1,17 @@
<template>
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
</MkModal>
<MkPopup ref="popup" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.popup.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')" #default="{point}">
<MkEmojiPicker class="ryghynhb _popup _shadow" :class="{ pointer: point === 'top' }" :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
</MkPopup>
</template>
<script lang="ts">
import { defineComponent, markRaw } from 'vue';
import MkModal from '@client/components/ui/modal.vue';
import MkPopup from '@client/components/ui/popup.vue';
import MkEmojiPicker from '@client/components/emoji-picker.vue';
export default defineComponent({
components: {
MkModal,
MkPopup,
MkEmojiPicker,
},
@ -33,7 +33,7 @@ export default defineComponent({
},
},
emits: ['done', 'closed'],
emits: ['done', 'close', 'closed'],
data() {
return {
@ -44,7 +44,7 @@ export default defineComponent({
methods: {
chosen(emoji: any) {
this.$emit('done', emoji);
this.$refs.modal.close();
this.$refs.popup.close();
},
opening() {
@ -56,145 +56,20 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
.omfetrab {
$pad: 8px;
--eachSize: 40px;
display: flex;
flex-direction: column;
contain: content;
&.big {
--eachSize: 44px;
}
&.w1 {
width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
}
&.w2 {
width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.w3 {
width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
}
&.h1 {
--height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
}
&.h2 {
--height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.h3 {
--height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
}
> .search {
width: 100%;
padding: 12px;
box-sizing: border-box;
font-size: 1em;
outline: none;
border: none;
background: transparent;
color: var(--fg);
&:not(.filled) {
order: 1;
z-index: 2;
box-shadow: 0px -1px 0 0px var(--divider);
}
}
> .emojis {
height: var(--height);
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
> .index {
min-height: var(--height);
position: relative;
border-bottom: solid 0.5px var(--divider);
> .arrow {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 16px 0;
text-align: center;
opacity: 0.5;
pointer-events: none;
}
}
section {
> header {
position: sticky;
top: 0;
left: 0;
z-index: 1;
padding: 8px;
font-size: 12px;
}
> div {
padding: $pad;
> button {
position: relative;
padding: 0;
width: var(--eachSize);
height: var(--eachSize);
border-radius: 4px;
&:focus {
outline: solid 2px var(--focus);
z-index: 1;
}
&:hover {
background: rgba(0, 0, 0, 0.05);
}
&:active {
background: var(--accent);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
}
> * {
font-size: 24px;
height: 1.25em;
vertical-align: -.25em;
pointer-events: none;
}
}
}
&.result {
border-bottom: solid 0.5px var(--divider);
&:empty {
display: none;
}
}
&.unicode {
min-height: 384px;
}
&.custom {
min-height: 64px;
}
.ryghynhb {
&.pointer {
&:before {
--size: 8px;
content: '';
display: block;
position: absolute;
top: calc(0px - (var(--size) * 2));
left: 0;
right: 0;
width: 0;
margin: auto;
border: solid var(--size) transparent;
border-bottom-color: var(--popup);
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<div class="omfetrab _popup" :class="['w' + width, 'h' + height, { big }]">
<div class="omfetrab" :class="['w' + width, 'h' + height, { big }]">
<input ref="search" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
<div class="emojis" ref="emojis">
<section class="result">
@ -346,7 +346,6 @@ export default defineComponent({
display: flex;
flex-direction: column;
contain: content;
&.big {
--eachSize: 44px;

View File

@ -9,14 +9,14 @@
<form class="_monolithic_" @submit.prevent="onSubmit" v-if="$instance.enableEmail">
<div class="_section">
<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required>
<span>{{ $ts.username }}</span>
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required>
<template #label>{{ $ts.username }}</template>
<template #prefix>@</template>
</MkInput>
<MkInput v-model:value="email" type="email" spellcheck="false" required>
<span>{{ $ts.emailAddress }}</span>
<template #desc>{{ $ts._forgotPassword.enterEmail }}</template>
<MkInput v-model="email" type="email" spellcheck="false" required>
<template #label>{{ $ts.emailAddress }}</template>
<template #caption>{{ $ts._forgotPassword.enterEmail }}</template>
</MkInput>
<MkButton type="submit" :disabled="processing" primary style="margin: 0 auto;">{{ $ts.send }}</MkButton>

View File

@ -32,8 +32,8 @@
margin: -8px calc(var(--formXPadding) * -1) 0 calc(var(--formXPadding) * -1);
padding: 8px calc(var(--formContentHMargin) + var(--formXPadding)) 8px calc(var(--formContentHMargin) + var(--formXPadding));
background: var(--X17);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: var(--blur, blur(10px));
backdrop-filter: var(--blur, blur(10px));
}
._themeChanging_ ._formLabel {

View File

@ -1,5 +1,5 @@
<template>
<div class="yxspomdl" :class="{ inline, colored }">
<div class="yxspomdl" :class="{ inline, colored, mini }">
<div class="ring"></div>
</div>
</template>
@ -18,7 +18,12 @@ export default defineComponent({
type: Boolean,
required: false,
default: true
}
},
mini: {
type: Boolean,
required: false,
default: false
},
}
});
</script>
@ -38,6 +43,8 @@ export default defineComponent({
text-align: center;
cursor: wait;
--size: 48px;
&.colored {
color: var(--accent);
}
@ -45,19 +52,12 @@ export default defineComponent({
&.inline {
display: inline;
padding: 0;
--size: 32px;
}
> .ring:after {
width: 32px;
height: 32px;
}
> .ring {
&:before,
&:after {
width: 32px;
height: 32px;
}
}
&.mini {
padding: 16px;
--size: 32px;
}
> .ring {
@ -70,8 +70,8 @@ export default defineComponent({
content: " ";
display: block;
box-sizing: border-box;
width: 48px;
height: 48px;
width: var(--size);
height: var(--size);
border-radius: 50%;
border: solid 4px;
}

View File

@ -117,6 +117,11 @@ export default defineComponent({
75% { transform: scale3d(1.05, 0.95, 1); }
to { transform: scale3d(1, 1, 1); }
}
@keyframes mfm-rainbow {
0% { filter: hue-rotate(0deg) contrast(150%) saturate(150%); }
100% { filter: hue-rotate(360deg) contrast(150%) saturate(150%); }
}
</style>
<style lang="scss" scoped>

View File

@ -1,7 +1,7 @@
<template>
<div class="zbcjwnqg" style="margin-top: -8px;">
<div class="selects" style="display: flex;">
<MkSelect v-model:value="chartSrc" style="margin: 0; flex: 1;">
<MkSelect v-model="chartSrc" style="margin: 0; flex: 1;">
<optgroup :label="$ts.federation">
<option value="federation-instances">{{ $ts._charts.federationInstancesIncDec }}</option>
<option value="federation-instances-total">{{ $ts._charts.federationInstancesTotal }}</option>
@ -24,7 +24,7 @@
<option value="drive-total">{{ $ts._charts.storageUsageTotal }}</option>
</optgroup>
</MkSelect>
<MkSelect v-model:value="chartSpan" style="margin: 0;">
<MkSelect v-model="chartSpan" style="margin: 0;">
<option value="hour">{{ $ts.perHour }}</option>
<option value="day">{{ $ts.perDay }}</option>
</MkSelect>

View File

@ -165,6 +165,10 @@ export default defineComponent({
class: '_mfm_blur_',
}, genEl(token.children));
}
case 'rainbow': {
style = this.$store.state.animatedMfm ? 'animation: mfm-rainbow 1s linear infinite;' : '';
break;
}
}
if (style == null) {
return h('span', {}, ['[', token.props.name, ...genEl(token.children), ']']);

View File

@ -1,13 +1,10 @@
<template>
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')">
<div class="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
<div class="hrmcaedk _window _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header" @contextmenu="onContextmenu">
<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button>
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
<span class="title">
<XHeader :info="pageInfo" :with-back="false"/>
<XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="$refs.modal.close()"/>
</span>
<button class="_button" @click="$refs.modal.close()"><i class="fas fa-times"></i></button>
</div>
<div class="body _flat_">
<keep-alive>
@ -177,35 +174,19 @@ export default defineComponent({
flex-shrink: 0;
box-shadow: 0px 1px var(--divider);
> button {
height: $height;
width: $height;
@media (max-width: 500px) {
height: $height-narrow;
width: $height-narrow;
}
}
> .title {
flex: 1;
line-height: $height;
padding-left: 32px;
height: $height;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
pointer-events: none;
@media (max-width: 500px) {
line-height: $height-narrow;
height: $height-narrow;
padding-left: 16px;
}
}
> button + .title {
padding-left: 0;
}
}
> .body {

View File

@ -1,6 +1,6 @@
<template>
<div
class="note _block"
class="lxwezrsl _block"
v-if="!muted"
v-show="!isDeleted"
:tabindex="!isDeleted ? '-1' : null"
@ -67,6 +67,13 @@
<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
<div class="translation" v-if="translating || translation">
<MkLoading v-if="translating" mini/>
<div class="translated" v-else>
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b>
{{ translation.text }}
</div>
</div>
</div>
<div class="files" v-if="appearNote.files.length > 0">
<XMediaList :media-list="appearNote.files"/>
@ -79,8 +86,8 @@
</div>
<footer class="footer">
<div class="info">
<span class="mobile" v-if="note.viaMobile"><i class="fas fa-mobile-alt"></i></span>
<MkTime class="created-at" :time="note.createdAt" mode="detail"/>
<span class="mobile" v-if="appearNote.viaMobile"><i class="fas fa-mobile-alt"></i></span>
<MkTime class="created-at" :time="appearNote.createdAt" mode="detail"/>
</div>
<XReactionsViewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()" class="button _button">
@ -178,6 +185,8 @@ export default defineComponent({
showContent: false,
isDeleted: false,
muted: false,
translation: null,
translating: false,
};
},
@ -454,7 +463,7 @@ export default defineComponent({
renote(viaKeyboard = false) {
pleaseLogin();
this.blur();
os.modalMenu([{
os.popupMenu([{
text: this.$ts.renote,
icon: 'fas fa-retweet',
action: () => {
@ -619,6 +628,11 @@ export default defineComponent({
text: this.$ts.share,
action: this.share
},
this.$instance.translatorAvailable ? {
icon: 'fas fa-language',
text: this.$ts.translate,
action: this.translate
} : undefined,
null,
statePromise.then(state => state.isFavorited ? {
icon: 'fas fa-star',
@ -743,14 +757,14 @@ export default defineComponent({
},
menu(viaKeyboard = false) {
os.modalMenu(this.getMenu(), this.$refs.menuButton, {
os.popupMenu(this.getMenu(), this.$refs.menuButton, {
viaKeyboard
}).then(this.focus);
},
showRenoteMenu(viaKeyboard = false) {
if (!this.isMyRenote) return;
os.modalMenu([{
os.popupMenu([{
text: this.$ts.unrenote,
icon: 'fas fa-trash-alt',
danger: true,
@ -794,7 +808,7 @@ export default defineComponent({
async clip() {
const clips = await os.api('clips/list');
os.modalMenu([{
os.popupMenu([{
icon: 'fas fa-plus',
text: this.$ts.createNew,
action: async () => {
@ -852,6 +866,17 @@ export default defineComponent({
});
},
async translate() {
if (this.translation != null) return;
this.translating = true;
const res = await os.api('notes/translate', {
noteId: this.appearNote.id,
targetLang: localStorage.getItem('lang') || navigator.language,
});
this.translating = false;
this.translation = res;
},
focus() {
this.$el.focus();
},
@ -874,7 +899,7 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
.note {
.lxwezrsl {
position: relative;
transition: box-shadow 0.1s ease;
overflow: hidden;
@ -1050,6 +1075,13 @@ export default defineComponent({
font-style: oblique;
color: var(--renote);
}
> .translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
}
> .url-preview {

View File

@ -24,8 +24,8 @@
<script lang="ts">
import { defineComponent } from 'vue';
import notePage from '../filters/note';
import { userPage } from '../filters/user';
import notePage from '@client/filters/note';
import { userPage } from '@client/filters/user';
import * as os from '@client/os';
export default defineComponent({

View File

@ -51,6 +51,13 @@
<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote != null">RN:</a>
<div class="translation" v-if="translating || translation">
<MkLoading v-if="translating" mini/>
<div class="translated" v-else>
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}:</b>
{{ translation.text }}
</div>
</div>
</div>
<div class="files" v-if="appearNote.files.length > 0">
<XMediaList :media-list="appearNote.files"/>
@ -164,6 +171,8 @@ export default defineComponent({
collapsed: false,
isDeleted: false,
muted: false,
translation: null,
translating: false,
};
},
@ -429,7 +438,7 @@ export default defineComponent({
renote(viaKeyboard = false) {
pleaseLogin();
this.blur();
os.modalMenu([{
os.popupMenu([{
text: this.$ts.renote,
icon: 'fas fa-retweet',
action: () => {
@ -594,6 +603,11 @@ export default defineComponent({
text: this.$ts.share,
action: this.share
},
this.$instance.translatorAvailable ? {
icon: 'fas fa-language',
text: this.$ts.translate,
action: this.translate
} : undefined,
null,
statePromise.then(state => state.isFavorited ? {
icon: 'fas fa-star',
@ -718,14 +732,14 @@ export default defineComponent({
},
menu(viaKeyboard = false) {
os.modalMenu(this.getMenu(), this.$refs.menuButton, {
os.popupMenu(this.getMenu(), this.$refs.menuButton, {
viaKeyboard
}).then(this.focus);
},
showRenoteMenu(viaKeyboard = false) {
if (!this.isMyRenote) return;
os.modalMenu([{
os.popupMenu([{
text: this.$ts.unrenote,
icon: 'fas fa-trash-alt',
danger: true,
@ -769,7 +783,7 @@ export default defineComponent({
async clip() {
const clips = await os.api('clips/list');
os.modalMenu([{
os.popupMenu([{
icon: 'fas fa-plus',
text: this.$ts.createNew,
action: async () => {
@ -827,6 +841,17 @@ export default defineComponent({
});
},
async translate() {
if (this.translation != null) return;
this.translating = true;
const res = await os.api('notes/translate', {
noteId: this.appearNote.id,
targetLang: localStorage.getItem('lang') || navigator.language,
});
this.translating = false;
this.translation = res;
},
focus() {
this.$el.focus();
},
@ -1053,6 +1078,13 @@ export default defineComponent({
font-style: oblique;
color: var(--renote);
}
> .translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
}
> .url-preview {

View File

@ -9,7 +9,7 @@
<div>{{ $ts.noNotes }}</div>
</div>
<div v-else>
<div v-else class="giivymft" :class="{ noGap }">
<div v-show="more && reversed" style="margin-bottom: var(--margin);">
<MkButton style="margin: 0 auto;" @click="fetchMoreFeature" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
@ -17,8 +17,8 @@
</MkButton>
</div>
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap" :ad="true">
<XNote :note="note" class="_block" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/>
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap" :ad="true" class="notes">
<XNote class="qtqtichx" :note="note" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/>
</XList>
<div v-show="more && !reversed" style="margin-top: var(--margin);">
@ -108,4 +108,23 @@ export default defineComponent({
.fade-leave-to {
opacity: 0;
}
.giivymft {
&.noGap {
> .notes {
background: var(--panel);
}
}
&:not(.noGap) {
> .notes {
background: var(--bg);
.qtqtichx {
background: var(--panel);
border-radius: var(--radius);
}
}
}
}
</style>

View File

@ -11,16 +11,16 @@
<template #header>{{ $ts.notificationSetting }}</template>
<div class="_monolithic_">
<div v-if="showGlobalToggle" class="_section">
<MkSwitch v-model:value="useGlobalSetting">
<MkSwitch v-model="useGlobalSetting">
{{ $ts.useGlobalSetting }}
<template #desc>{{ $ts.useGlobalSettingDesc }}</template>
<template #caption>{{ $ts.useGlobalSettingDesc }}</template>
</MkSwitch>
</div>
<div v-if="!useGlobalSetting" class="_section">
<MkInfo>{{ $ts.notificationSettingDesc }}</MkInfo>
<MkButton inline @click="disableAll">{{ $ts.disableAll }}</MkButton>
<MkButton inline @click="enableAll">{{ $ts.enableAll }}</MkButton>
<MkSwitch v-for="type in notificationTypes" :key="type" v-model:value="typesMap[type]">{{ $t(`_notification._types.${type}`) }}</MkSwitch>
<MkSwitch v-for="type in notificationTypes" :key="type" v-model="typesMap[type]">{{ $t(`_notification._types.${type}`) }}</MkSwitch>
</div>
</div>
</XModalWindow>

View File

@ -62,8 +62,8 @@ import { defineComponent, markRaw } from 'vue';
import { getNoteSummary } from '@/misc/get-note-summary';
import XReactionIcon from './reaction-icon.vue';
import MkFollowButton from './follow-button.vue';
import notePage from '../filters/note';
import { userPage } from '../filters/user';
import notePage from '@client/filters/note';
import { userPage } from '@client/filters/user';
import { i18n } from '@client/i18n';
import * as os from '@client/os';

View File

@ -7,7 +7,7 @@
<p class="mfcuwfyp" v-else-if="empty">{{ $ts.noNotifications }}</p>
<div v-else>
<XList class="notifications" :items="items" v-slot="{ item: notification }" :no-gap="true">
<XList class="elsfgstc" :items="items" v-slot="{ item: notification }" :no-gap="true">
<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :note="notification.note" @update:note="noteUpdated(notification.note, $event)" :key="notification.id"/>
<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
</XList>
@ -141,4 +141,8 @@ export default defineComponent({
text-align: center;
color: var(--fg);
}
.elsfgstc {
background: var(--panel);
}
</style>

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { userName } from '../filters/user';
import { userName } from '@client/filters/user';
import * as os from '@client/os';
export default defineComponent({

View File

@ -3,16 +3,12 @@
:initial-width="500"
:initial-height="500"
:can-resize="true"
:close-right="true"
:close-button="false"
:contextmenu="contextmenu"
@closed="$emit('closed')"
>
<template #header>
<XHeader :info="pageInfo" :with-back="false"/>
</template>
<template #buttons>
<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button>
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
<XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="close()"/>
</template>
<div class="yrolvcoq _flat_">
<component :is="component" v-bind="props" :ref="changePage"/>
@ -139,6 +135,10 @@ export default defineComponent({
this.navigate(this.history.pop(), false);
},
close() {
this.$refs.window.close();
},
expand() {
this.$router.push(this.path);
this.$refs.window.close();
@ -155,6 +155,5 @@ export default defineComponent({
<style lang="scss" scoped>
.yrolvcoq {
min-height: 100%;
background: var(--bg);
}
</style>

View File

@ -1,6 +1,8 @@
<template>
<div>
<MkInput class="kudkigyw" :value="value" @update:value="updateValue($event)" type="number">{{ hpml.interpolate(block.text) }}</MkInput>
<MkInput class="kudkigyw" :model-value="value" @update:modelValue="updateValue($event)" type="number">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkInput>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div class="ngbfujlo">
<MkTextarea :value="text" readonly style="margin: 0;"></MkTextarea>
<MkTextarea :model-value="text" readonly style="margin: 0;"></MkTextarea>
<MkButton class="button" primary @click="post()" :disabled="posting || posted">
<i v-if="posted" class="fas fa-check"></i>
<i v-else class="fas fa-paper-plane"></i>

View File

@ -1,6 +1,6 @@
<template>
<div class="hkcxmtwj">
<MkSwitch :value="value" @update:value="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkSwitch>
<MkSwitch :model-value="value" @update:modelValue="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkSwitch>
</div>
</template>

View File

@ -1,6 +1,8 @@
<template>
<div>
<MkInput class="kudkigyw" :value="value" @update:value="updateValue($event)" type="text">{{ hpml.interpolate(block.text) }}</MkInput>
<MkInput class="kudkigyw" :model-value="value" @update:modelValue="updateValue($event)" type="text">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkInput>
</div>
</template>

View File

@ -1,6 +1,8 @@
<template>
<div>
<MkTextarea :value="value" @update:value="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkTextarea>
<MkTextarea :model-value="value" @update:modelValue="updateValue($event)">
<template #label>{{ hpml.interpolate(block.text) }}</template>
</MkTextarea>
</div>
</template>

View File

@ -1,5 +1,5 @@
<template>
<MkTextarea :value="text" readonly></MkTextarea>
<MkTextarea :model-value="text" readonly></MkTextarea>
</template>
<script lang="ts">

View File

@ -5,8 +5,7 @@
</p>
<ul ref="choices">
<li v-for="(choice, i) in choices" :key="i">
<MkInput class="input" :value="choice" @update:value="onInput(i, $event)">
<span>{{ $t('_poll.choiceN', { n: i + 1 }) }}</span>
<MkInput class="input" :model-value="choice" @update:modelValue="onInput(i, $event)" :placeholder="$t('_poll.choiceN', { n: i + 1 })">
</MkInput>
<button @click="remove(i)" class="_button">
<i class="fas fa-times"></i>
@ -16,27 +15,27 @@
<MkButton class="add" v-if="choices.length < 10" @click="add">{{ $ts.add }}</MkButton>
<MkButton class="add" v-else disabled>{{ $ts._poll.noMore }}</MkButton>
<section>
<MkSwitch v-model:value="multiple">{{ $ts._poll.canMultipleVote }}</MkSwitch>
<MkSwitch v-model="multiple">{{ $ts._poll.canMultipleVote }}</MkSwitch>
<div>
<MkSelect v-model:value="expiration">
<MkSelect v-model="expiration">
<template #label>{{ $ts._poll.expiration }}</template>
<option value="infinite">{{ $ts._poll.infinite }}</option>
<option value="at">{{ $ts._poll.at }}</option>
<option value="after">{{ $ts._poll.after }}</option>
</MkSelect>
<section v-if="expiration === 'at'">
<MkInput v-model:value="atDate" type="date" class="input">
<span>{{ $ts._poll.deadlineDate }}</span>
<MkInput v-model="atDate" type="date" class="input">
<template #label>{{ $ts._poll.deadlineDate }}</template>
</MkInput>
<MkInput v-model:value="atTime" type="time" class="input">
<span>{{ $ts._poll.deadlineTime }}</span>
<MkInput v-model="atTime" type="time" class="input">
<template #label>{{ $ts._poll.deadlineTime }}</template>
</MkInput>
</section>
<section v-if="expiration === 'after'">
<MkInput v-model:value="after" type="number" class="input">
<span>{{ $ts._poll.duration }}</span>
<MkInput v-model="after" type="number" class="input">
<template #label>{{ $ts._poll.duration }}</template>
</MkInput>
<MkSelect v-model:value="unit">
<MkSelect v-model="unit">
<option value="second">{{ $ts._time.second }}</option>
<option value="minute">{{ $ts._time.minute }}</option>
<option value="hour">{{ $ts._time.hour }}</option>

View File

@ -112,7 +112,7 @@ export default defineComponent({
showFileMenu(file, ev: MouseEvent) {
if (this.menu) return;
this.menu = os.modalMenu([{
this.menu = os.popupMenu([{
text: this.$ts.renameFile,
icon: 'fas fa-i-cursor',
action: () => { this.rename(file) }

View File

@ -17,7 +17,7 @@
<span v-if="visibility === 'followers'"><i class="fas fa-unlock"></i></span>
<span v-if="visibility === 'specified'"><i class="fas fa-envelope"></i></span>
</button>
<button class="submit _buttonPrimary" :disabled="!canPost" @click="post">{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button>
<button class="submit _buttonPrimary" :disabled="!canPost" @click="post" data-cy-open-post-form-submit>{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button>
</div>
</header>
<div class="form" :class="{ fixed }">
@ -36,7 +36,8 @@
</div>
<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo>
<input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown">
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" />
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" data-cy-post-form-text/>
<input v-show="withHashtags" ref="hashtags" class="hashtags" v-model="hashtags" :placeholder="$ts.hashtags" list="hashtags">
<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/>
<footer>
@ -44,9 +45,13 @@
<button class="_button" @click="togglePoll" :class="{ active: poll }" v-tooltip="$ts.poll"><i class="fas fa-poll-h"></i></button>
<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$ts.useCw"><i class="fas fa-eye-slash"></i></button>
<button class="_button" @click="insertMention" v-tooltip="$ts.mention"><i class="fas fa-at"></i></button>
<button class="_button" @click="withHashtags = !withHashtags" :class="{ active: withHashtags }" v-tooltip="$ts.hashtags"><i class="fas fa-hashtag"></i></button>
<button class="_button" @click="insertEmoji" v-tooltip="$ts.emoji"><i class="fas fa-laugh-squint"></i></button>
<button class="_button" @click="showActions" v-tooltip="$ts.plugin" v-if="postFormActions.length > 0"><i class="fas fa-plug"></i></button>
</footer>
<datalist id="hashtags">
<option v-for="hashtag in recentHashtags" :value="hashtag" :key="hashtag"/>
</datalist>
</div>
</div>
</template>
@ -67,10 +72,11 @@ import { Autocomplete } from '@client/scripts/autocomplete';
import { noteVisibilities } from '../../types';
import * as os from '@client/os';
import { selectFile } from '@client/scripts/select-file';
import { notePostInterruptors, postFormActions } from '@client/store';
import { defaultStore, notePostInterruptors, postFormActions } from '@client/store';
import { isMobile } from '@client/scripts/is-mobile';
import { throttle } from 'throttle-debounce';
import MkInfo from '@client/components/ui/info.vue';
import { defaultStore } from '@client/store';
export default defineComponent({
components: {
@ -212,7 +218,10 @@ export default defineComponent({
max(): number {
return this.$instance ? this.$instance.maxNoteTextLength : 1000;
}
},
withHashtags: defaultStore.makeGetterSetter('postFormWithHashtags'),
hashtags: defaultStore.makeGetterSetter('postFormHashtags'),
},
watch: {
@ -303,6 +312,7 @@ export default defineComponent({
// TODO: detach when unmount
new Autocomplete(this.$refs.text, this, { model: 'text' });
new Autocomplete(this.$refs.cw, this, { model: 'cw' });
new Autocomplete(this.$refs.hashtags, this, { model: 'hashtags' });
this.$nextTick(() => {
// 書きかけの投稿を復元
@ -329,7 +339,12 @@ export default defineComponent({
this.cw = init.cw;
this.useCw = init.cw != null;
if (init.poll) {
this.poll = init.poll;
this.poll = {
choices: init.poll.choices.map(x => x.text),
multiple: init.poll.multiple,
expiresAt: init.poll.expiresAt,
expiredAfter: init.poll.expiredAfter,
};
}
this.visibility = init.visibility;
this.localOnly = init.localOnly;
@ -605,6 +620,11 @@ export default defineComponent({
viaMobile: isMobile
};
if (this.withHashtags && this.hashtags && this.hashtags.trim() !== '') {
const hashtags = this.hashtags.trim().split(' ').map(x => x.startsWith('#') ? x : '#' + x).join(' ');
data.text = data.text ? `${data.text} ${hashtags}` : hashtags;
}
// plugin
if (notePostInterruptors.length > 0) {
for (const interruptor of notePostInterruptors) {
@ -618,8 +638,8 @@ export default defineComponent({
this.$nextTick(() => {
this.deleteDraft();
this.$emit('posted');
if (this.text && this.text != '') {
const hashtags = mfm.parse(this.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag);
if (data.text && data.text != '') {
const hashtags = mfm.parse(data.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag);
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
}
@ -649,7 +669,7 @@ export default defineComponent({
},
showActions(ev) {
os.modalMenu(postFormActions.map(action => ({
os.popupMenu(postFormActions.map(action => ({
text: action.title,
action: () => {
action.handler({
@ -785,6 +805,7 @@ export default defineComponent({
}
> .cw,
> .hashtags,
> .text {
display: block;
box-sizing: border-box;
@ -813,6 +834,13 @@ export default defineComponent({
border-bottom: solid 0.5px var(--divider);
}
> .hashtags {
z-index: 1;
padding-top: 8px;
padding-bottom: 8px;
border-top: solid 0.5px var(--divider);
}
> .text {
max-width: 100%;
min-width: 100%;
@ -872,6 +900,7 @@ export default defineComponent({
}
> .cw,
> .hashtags,
> .text {
padding: 0 16px;
}

View File

@ -170,7 +170,7 @@ export default defineComponent({
}
> span {
color: #fff;
color: var(--fgOnAccent);
}
}

View File

@ -1,10 +1,10 @@
<template>
<div class="_card">
<div class="_content">
<MkInput v-model:value="text">
<span>Text</span>
<MkInput v-model="text">
<template #label>Text</template>
</MkInput>
<MkSwitch v-model:value="flag">
<MkSwitch v-model="flag">
<span>Switch is now {{ flag ? 'on' : 'off' }}</span>
</MkSwitch>
<div style="margin: 32px 0;">
@ -93,7 +93,7 @@ export default defineComponent({
},
async openMenu(ev) {
os.modalMenu([{
os.popupMenu([{
type: 'label',
text: 'Fruits'
}, {

View File

@ -3,15 +3,13 @@
<div class="auth _section">
<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div>
<div class="normal-signin" v-if="!totpLogin">
<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:value="onUsernameChange">
<span>{{ $ts.username }}</span>
<MkInput v-model="username" :placeholder="$ts.username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @update:modelValue="onUsernameChange" data-cy-signin-username>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</MkInput>
<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required>
<span>{{ $ts.password }}</span>
<MkInput v-model="password" :placeholder="$ts.password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required data-cy-signin-password>
<template #prefix><i class="fas fa-lock"></i></template>
<template #desc><button class="_textButton" @click="resetPassword">{{ $ts.forgotPassword }}</button></template>
<template #caption><button class="_textButton" @click="resetPassword" type="button">{{ $ts.forgotPassword }}</button></template>
</MkInput>
<MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton>
</div>
@ -27,12 +25,12 @@
</div>
<div class="twofa-group totp-group">
<p style="margin-bottom:0;">{{ $ts.twoStepAuthentication }}</p>
<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="user && user.usePasswordLessLogin" required>
<span>{{ $ts.password }}</span>
<MkInput v-model="password" type="password" :with-password-toggle="true" v-if="user && user.usePasswordLessLogin" required>
<template #label>{{ $ts.password }}</template>
<template #prefix><i class="fas fa-lock"></i></template>
</MkInput>
<MkInput v-model:value="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<span>{{ $ts.token }}</span>
<MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<template #label>{{ $ts.token }}</template>
<template #prefix><i class="fas fa-gavel"></i></template>
</MkInput>
<MkButton type="submit" :disabled="signing" primary style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton>

View File

@ -1,39 +1,39 @@
<template>
<form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()">
<template v-if="meta">
<MkInput v-if="meta.disableRegistration" v-model:value="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<span>{{ $ts.invitationCode }}</span>
<MkInput v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<template #label>{{ $ts.invitationCode }}</template>
<template #prefix><i class="fas fa-key"></i></template>
</MkInput>
<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:value="onChangeUsername">
<span>{{ $ts.username }}</span>
<MkInput v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeUsername" data-cy-signup-username>
<template #label>{{ $ts.username }}</template>
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
<template #desc>
<template #caption>
<span v-if="usernameState == 'wait'" style="color:#999"><i class="fas fa-spinner fa-pulse fa-fw"></i> {{ $ts.checking }}</span>
<span v-if="usernameState == 'ok'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.available }}</span>
<span v-if="usernameState == 'unavailable'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.unavailable }}</span>
<span v-if="usernameState == 'error'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.error }}</span>
<span v-if="usernameState == 'invalid-format'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.usernameInvalidFormat }}</span>
<span v-if="usernameState == 'min-range'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooShort }}</span>
<span v-if="usernameState == 'max-range'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span>
<span v-if="usernameState == 'ok'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.available }}</span>
<span v-if="usernameState == 'unavailable'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.unavailable }}</span>
<span v-if="usernameState == 'error'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.error }}</span>
<span v-if="usernameState == 'invalid-format'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.usernameInvalidFormat }}</span>
<span v-if="usernameState == 'min-range'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooShort }}</span>
<span v-if="usernameState == 'max-range'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span>
</template>
</MkInput>
<MkInput v-model:value="password" type="password" :autocomplete="Math.random()" required @update:value="onChangePassword">
<span>{{ $ts.password }}</span>
<MkInput v-model="password" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePassword" data-cy-signup-password>
<template #label>{{ $ts.password }}</template>
<template #prefix><i class="fas fa-lock"></i></template>
<template #desc>
<p v-if="passwordStrength == 'low'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.weakPassword }}</p>
<p v-if="passwordStrength == 'medium'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.normalPassword }}</p>
<p v-if="passwordStrength == 'high'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</p>
<template #caption>
<span v-if="passwordStrength == 'low'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.weakPassword }}</span>
<span v-if="passwordStrength == 'medium'" style="color: var(--warn)"><i class="fas fa-check fa-fw"></i> {{ $ts.normalPassword }}</span>
<span v-if="passwordStrength == 'high'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</span>
</template>
</MkInput>
<MkInput v-model:value="retypedPassword" type="password" :autocomplete="Math.random()" required @update:value="onChangePasswordRetype">
<span>{{ $ts.password }} ({{ $ts.retype }})</span>
<MkInput v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @update:modelValue="onChangePasswordRetype" data-cy-signup-password-retype>
<template #label>{{ $ts.password }} ({{ $ts.retype }})</template>
<template #prefix><i class="fas fa-lock"></i></template>
<template #desc>
<p v-if="passwordRetypeState == 'match'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.passwordMatched }}</p>
<p v-if="passwordRetypeState == 'not-match'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.passwordNotMatched }}</p>
<template #caption>
<span v-if="passwordRetypeState == 'match'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.passwordMatched }}</span>
<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.passwordNotMatched }}</span>
</template>
</MkInput>
<label v-if="meta.tosUrl" class="tou">
@ -46,7 +46,7 @@
</label>
<captcha v-if="meta.enableHcaptcha" class="captcha" provider="hcaptcha" ref="hcaptcha" v-model:value="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/>
<captcha v-if="meta.enableRecaptcha" class="captcha" provider="recaptcha" ref="recaptcha" v-model:value="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/>
<MkButton type="submit" :disabled="shouldDisableSubmitting" primary>{{ $ts.start }}</MkButton>
<MkButton type="submit" :disabled="shouldDisableSubmitting" primary data-cy-signup-submit>{{ $ts.start }}</MkButton>
</template>
</form>
</template>

View File

@ -14,13 +14,15 @@
<MkInfo warn>{{ information }}</MkInfo>
</div>
<div class="_section">
<MkInput v-model:value="name">{{ $ts.name }}</MkInput>
<MkInput v-model="name">
<template #label>{{ $ts.name }}</template>
</MkInput>
</div>
<div class="_section">
<div style="margin-bottom: 16px;"><b>{{ $ts.permission }}</b></div>
<MkButton inline @click="disableAll">{{ $ts.disableAll }}</MkButton>
<MkButton inline @click="enableAll">{{ $ts.enableAll }}</MkButton>
<MkSwitch v-for="kind in (initialPermissions || kinds)" :key="kind" v-model:value="permissions[kind]">{{ $t(`_permissions.${kind}`) }}</MkSwitch>
<MkSwitch v-for="kind in (initialPermissions || kinds)" :key="kind" v-model="permissions[kind]">{{ $t(`_permissions.${kind}`) }}</MkSwitch>
</div>
</XModalWindow>
</template>

View File

@ -1,6 +1,6 @@
<template>
<component class="bghgjjyj _button"
:is="link ? 'a' : 'button'"
:is="link ? 'MkA' : 'button'"
:class="{ inline, primary, danger, full }"
:type="type"
@click="$emit('click', $event)"
@ -115,6 +115,7 @@ export default defineComponent({
z-index: 1; // 他コンポーネントのbox-shadowに隠されないようにするため
display: block;
min-width: 100px;
width: max-content;
padding: 8px 14px;
text-align: center;
font-weight: normal;
@ -125,6 +126,8 @@ export default defineComponent({
background: var(--buttonBg);
border-radius: 999px;
overflow: hidden;
box-sizing: border-box;
transition: background 0.1s ease;
&:not(:disabled):hover {
background: var(--buttonHoverBg);
@ -140,7 +143,7 @@ export default defineComponent({
&.primary {
font-weight: bold;
color: #fff !important;
color: var(--fgOnAccent) !important;
background: var(--accent);
&:not(:disabled):hover {
@ -174,17 +177,8 @@ export default defineComponent({
}
&:focus {
&:after {
content: "";
pointer-events: none;
position: absolute;
top: -5px;
right: -5px;
bottom: -5px;
left: -5px;
border: 2px solid var(--accentAlpha03);
border-radius: 10px;
}
outline: solid 2px var(--focus);
outline-offset: 2px;
}
&.inline + .bghgjjyj {

View File

@ -99,9 +99,12 @@ export default defineComponent({
z-index: 10;
position: sticky;
top: var(--stickyTop, 0px);
background: var(--panel);
/* TODO panelの半透明バージョンをプログラマティックに作りたい
background: var(--X17);
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(20px));
*/
> .title {
margin: 0;

View File

@ -1,32 +1,9 @@
<template>
<div class="juejbjww" :class="{ focused, filled, inline, disabled }">
<div class="icon" ref="icon"><slot name="icon"></slot></div>
<div class="input">
<span class="label" ref="labelEl"><slot></slot></span>
<span class="title" ref="title">
<slot name="title"></slot>
<span class="warning" v-if="invalid"><i class="fas fa-exclamation-circle"></i>{{ $refs.input.validationMessage }}</span>
</span>
<div class="matxzzsk">
<div class="label" @click="focus"><slot name="label"></slot></div>
<div class="input" :class="{ inline, disabled, focused }">
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
<input v-if="debounce" ref="inputEl"
v-debounce="500"
:type="type"
v-model.lazy="v"
:disabled="disabled"
:required="required"
:readonly="readonly"
:placeholder="placeholder"
:pattern="pattern"
:autocomplete="autocomplete"
:spellcheck="spellcheck"
:step="step"
@focus="focused = true"
@blur="focused = false"
@keydown="onKeydown($event)"
@input="onInput"
:list="id"
>
<input v-else ref="inputEl"
<input ref="inputEl"
:type="type"
v-model="v"
:disabled="disabled"
@ -48,23 +25,25 @@
</datalist>
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
</div>
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $ts.save }}</button>
<div class="desc _caption"><slot name="desc"></slot></div>
<div class="caption"><slot name="caption"></slot></div>
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import debounce from 'v-debounce';
import * as os from '@client/os';
import MkButton from './button.vue';
import { debounce } from 'throttle-debounce';
export default defineComponent({
directives: {
debounce
components: {
MkButton,
},
props: {
value: {
required: false
modelValue: {
required: true
},
type: {
type: String,
@ -104,9 +83,6 @@ export default defineComponent({
step: {
required: false
},
debounce: {
required: false
},
datalist: {
type: Array,
required: false,
@ -116,15 +92,23 @@ export default defineComponent({
required: false,
default: false
},
save: {
type: Function,
debounce: {
type: Boolean,
required: false,
default: false
},
manualSave: {
type: Boolean,
required: false,
default: false
},
},
emits: ['change', 'keydown', 'enter'],
emits: ['change', 'keydown', 'enter', 'update:modelValue'],
setup(props, context) {
const { value, type, autofocus } = toRefs(props);
const v = ref(value.value);
const { modelValue, type, autofocus } = toRefs(props);
const v = ref(modelValue.value);
const id = Math.random().toString(); // TODO: uuid?
const focused = ref(false);
const changed = ref(false);
@ -133,7 +117,6 @@ export default defineComponent({
const inputEl = ref(null);
const prefixEl = ref(null);
const suffixEl = ref(null);
const labelEl = ref(null);
const focus = () => inputEl.value.focus();
const onInput = (ev) => {
@ -148,15 +131,28 @@ export default defineComponent({
}
};
watch(value, newValue => {
const updated = () => {
changed.value = false;
if (type?.value === 'number') {
context.emit('update:modelValue', parseFloat(v.value));
} else {
context.emit('update:modelValue', v.value);
}
};
const debouncedUpdated = debounce(1000, updated);
watch(modelValue, newValue => {
v.value = newValue;
});
watch(v, newValue => {
if (type?.value === 'number') {
context.emit('update:value', parseFloat(newValue));
} else {
context.emit('update:value', newValue);
if (!props.manualSave) {
if (props.debounce) {
debouncedUpdated();
} else {
updated();
}
}
invalid.value = inputEl.value.validity.badInput;
@ -172,7 +168,6 @@ export default defineComponent({
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
const clock = setInterval(() => {
if (prefixEl.value) {
labelEl.value.style.left = (prefixEl.value.offsetLeft + prefixEl.value.offsetWidth) + 'px';
if (prefixEl.value.offsetWidth) {
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
}
@ -200,148 +195,78 @@ export default defineComponent({
inputEl,
prefixEl,
suffixEl,
labelEl,
focus,
onInput,
onKeydown,
updated,
};
},
});
</script>
<style lang="scss" scoped>
.juejbjww {
position: relative;
margin: 32px 0;
.matxzzsk {
margin: 1.5em 0;
&:not(.inline):first-child {
margin-top: 8px;
> .label {
font-size: 0.85em;
padding: 0 0 8px 12px;
user-select: none;
&:empty {
display: none;
}
}
&:not(.inline):last-child {
margin-bottom: 8px;
}
> .caption {
font-size: 0.8em;
padding: 8px 0 0 12px;
color: var(--fgTransparentWeak);
> .icon {
position: absolute;
top: 0;
left: 0;
width: 24px;
text-align: center;
line-height: 32px;
&:not(:empty) + .input {
margin-left: 28px;
&:empty {
display: none;
}
}
> .input {
$height: 42px;
position: relative;
&:before {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: var(--inputBorder);
}
&:after {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
background: var(--accent);
opacity: 0;
transform: scaleX(0.12);
transition: border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
will-change: border opacity transform;
}
> .label {
position: absolute;
z-index: 1;
top: 0;
left: 0;
pointer-events: none;
transition: 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-duration: 0.3s;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
pointer-events: none;
//will-change transform
transform-origin: top left;
transform: scale(1);
}
> .title {
position: absolute;
z-index: 1;
top: -17px;
left: 0 !important;
pointer-events: none;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
pointer-events: none;
//will-change transform
transform-origin: top left;
transform: scale(.75);
white-space: nowrap;
width: 133%;
overflow: hidden;
text-overflow: ellipsis;
> .warning {
margin-left: 0.5em;
color: var(--infoWarnFg);
> svg {
margin-right: 0.1em;
}
}
}
> input {
$height: 32px;
appearance: none;
-webkit-appearance: none;
display: block;
height: $height;
width: 100%;
margin: 0;
padding: 0;
padding: 0 12px;
font: inherit;
font-weight: normal;
font-size: 1em;
line-height: $height;
color: var(--inputText);
background: transparent;
border: none;
border-radius: 0;
color: var(--fg);
background: var(--panel);
border: solid 1px var(--inputBorder);
border-radius: 6px;
outline: none;
box-shadow: none;
box-sizing: border-box;
transition: border-color 0.1s ease-out;
&[type='file'] {
display: none;
&:hover {
border-color: var(--inputBorderHover);
}
}
> .prefix,
> .suffix {
display: block;
display: flex;
align-items: center;
position: absolute;
z-index: 1;
top: 0;
padding: 0 12px;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
height: $height;
pointer-events: none;
&:empty {
@ -360,67 +285,33 @@ export default defineComponent({
> .prefix {
left: 0;
padding-right: 4px;
padding-right: 6px;
}
> .suffix {
right: 0;
padding-left: 4px;
}
}
> .save {
margin: 6px 0 0 0;
font-size: 0.8em;
}
> .desc {
margin: 6px 0 0 0;
&:empty {
display: none;
padding-left: 6px;
}
* {
&.inline {
display: inline-block;
margin: 0;
}
}
&.focused {
> .input {
&:after {
opacity: 1;
transform: scaleX(1);
}
> .label {
color: var(--accent);
&.focused {
> input {
border-color: var(--accent);
//box-shadow: 0 0 0 4px var(--focus);
}
}
}
&.focused,
&.filled {
> .input {
> .label {
top: -17px;
left: 0 !important;
transform: scale(0.75);
&.disabled {
opacity: 0.7;
&, * {
cursor: not-allowed !important;
}
}
}
&.inline {
display: inline-block;
margin: 0;
}
&.disabled {
opacity: 0.7;
&, * {
cursor: not-allowed !important;
}
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="rrevdjwt" :class="{ left: align === 'left' }"
<div class="rrevdjwt" :class="{ left: align === 'left', pointer: point === 'top' }"
ref="items"
@contextmenu.self="e => e.preventDefault()"
v-hotkey="keymap"
@ -58,7 +58,11 @@ export default defineComponent({
align: {
type: String,
requried: false
}
},
point: {
type: String,
requried: false
},
},
emits: ['close'],
data() {
@ -137,6 +141,22 @@ export default defineComponent({
.rrevdjwt {
padding: 8px 0;
&.pointer {
&:before {
--size: 8px;
content: '';
display: block;
position: absolute;
top: calc(0px - (var(--size) * 2));
left: 0;
right: 0;
width: 0;
margin: auto;
border: solid var(--size) transparent;
border-bottom-color: var(--popup);
}
}
&.left {
> .item {
text-align: left;
@ -171,13 +191,13 @@ export default defineComponent({
}
&:hover {
color: #fff;
color: var(--fgOnAccent);
background: var(--accent);
text-decoration: none;
}
&:active {
color: #fff;
color: var(--fgOnAccent);
background: var(--accentDarken);
}

View File

@ -1,6 +1,6 @@
<template>
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')">
<div class="ebkgoccj _popup _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: scroll ? (height ? `${height}px` : null) : (height ? `min(${height}px, 100%)` : '100%') }">
<div class="ebkgoccj _window _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: scroll ? (height ? `${height}px` : null) : (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header">
<button class="_button" v-if="withOkButton" @click="$emit('close')"><i class="fas fa-times"></i></button>
<span class="title">

View File

@ -1,19 +1,20 @@
<template>
<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
<MkMenu :items="items" :align="align" @close="$refs.modal.close()" class="_popup"/>
</MkModal>
<MkPopup ref="popup" :src="src" @closed="$emit('closed')" #default="{point}">
<MkMenu :items="items" :align="align" :point="point" @close="$refs.popup.close()" class="_popup _shadow"/>
</MkPopup>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MkModal from './modal.vue';
import MkPopup from './popup.vue';
import MkMenu from './menu.vue';
export default defineComponent({
components: {
MkModal,
MkPopup,
MkMenu,
},
props: {
items: {
type: Array,
@ -31,17 +32,7 @@ export default defineComponent({
required: false
},
},
emits: ['closed'],
computed: {
keymap(): any {
return {
'esc': () => this.$refs.modal.close(),
};
},
},
emits: ['close', 'closed'],
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,216 @@
<template>
<transition :name="$store.state.animation ? 'popup-menu' : ''" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
<div v-show="manualShowing != null ? manualShowing : showing" class="ccczpooj" :class="{ front, fixed, top: position === 'top' }" ref="content" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<slot :point="point"></slot>
</div>
</transition>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue';
function getFixedContainer(el: Element | null): Element | null {
if (el == null || el.tagName === 'BODY') return null;
const position = window.getComputedStyle(el).getPropertyValue('position');
if (position === 'fixed') {
return el;
} else {
return getFixedContainer(el.parentElement);
}
}
export default defineComponent({
props: {
manualShowing: {
type: Boolean,
required: false,
default: null,
},
srcCenter: {
type: Boolean,
required: false
},
src: {
type: Object as PropType<HTMLElement>,
required: false,
},
position: {
required: false
},
front: {
type: Boolean,
required: false,
default: false,
}
},
emits: ['opening', 'click', 'esc', 'close', 'closed'],
data() {
return {
showing: true,
fixed: false,
transformOrigin: 'center',
contentClicking: false,
point: null,
};
},
mounted() {
this.$watch('src', () => {
if (this.src) {
this.src.style.pointerEvents = 'none';
}
this.fixed = getFixedContainer(this.src) != null;
this.$nextTick(() => {
this.align();
});
}, { immediate: true });
this.$nextTick(() => {
const popover = this.$refs.content as any;
new ResizeObserver((entries, observer) => {
this.align();
}).observe(popover);
});
document.addEventListener('mousedown', this.onDocumentClick, { passive: true });
},
beforeUnmount() {
document.removeEventListener('mousedown', this.onDocumentClick);
},
methods: {
align() {
if (this.src == null) return;
const popover = this.$refs.content as any;
if (popover == null) return;
const rect = this.src.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
let left;
let top;
if (this.srcCenter) {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + (this.src.offsetHeight / 2);
left = (x - (width / 2));
top = (y - (height / 2));
} else {
const x = rect.left + (this.fixed ? 0 : window.pageXOffset) + (this.src.offsetWidth / 2);
const y = rect.top + (this.fixed ? 0 : window.pageYOffset) + this.src.offsetHeight;
left = (x - (width / 2));
top = y;
}
if (this.fixed) {
if (left + width > window.innerWidth) {
left = window.innerWidth - width;
}
if (top + height > window.innerHeight) {
top = window.innerHeight - height;
}
} else {
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset - 1;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset - 1;
}
}
if (top < 0) {
top = 0;
}
if (left < 0) {
left = 0;
}
if (top > rect.top + (this.fixed ? 0 : window.pageYOffset)) {
this.point = 'top';
this.transformOrigin = 'center top';
} else {
this.point = null;
this.transformOrigin = 'center';
}
popover.style.left = left + 'px';
popover.style.top = top + 'px';
},
childRendered() {
// モーダルコンテンツにマウスボタンが押され、コンテンツ外でマウスボタンが離されたときにモーダルバックグラウンドクリックと判定させないためにマウスイベントを監視しフラグ管理する
const content = this.$refs.content.children[0];
content.addEventListener('mousedown', e => {
this.contentClicking = true;
window.addEventListener('mouseup', e => {
// click イベントより先に mouseup イベントが発生するかもしれないのでちょっと待つ
setTimeout(() => {
this.contentClicking = false;
}, 100);
}, { passive: true, once: true });
}, { passive: true });
},
close() {
if (this.src) this.src.style.pointerEvents = 'auto';
this.showing = false;
this.$emit('close');
},
onClosed() {
this.$emit('closed');
},
onDocumentClick(ev) {
const flyoutElement = this.$refs.content;
let targetElement = ev.target;
do {
if (targetElement === flyoutElement) {
return;
}
targetElement = targetElement.parentNode;
} while (targetElement);
this.close();
}
}
});
</script>
<style lang="scss" scoped>
.popup-menu-enter-active {
transform-origin: var(--transformOrigin);
transition: opacity 0.2s cubic-bezier(0, 0, 0.2, 1), transform 0.2s cubic-bezier(0, 0, 0.2, 1) !important;
}
.popup-menu-leave-active {
transform-origin: var(--transformOrigin);
transition: opacity 0.2s cubic-bezier(0.4, 0, 1, 1), transform 0.2s cubic-bezier(0.4, 0, 1, 1) !important;
}
.popup-menu-enter-from, .popup-menu-leave-to {
pointer-events: none;
opacity: 0;
transform: scale(0.9);
}
.ccczpooj {
position: absolute;
z-index: 10000;
&.fixed {
position: fixed;
}
&.front {
z-index: 20000;
}
}
</style>

View File

@ -1,185 +1,218 @@
<template>
<div class="eiipwacr" :class="{ focused, disabled, filled, inline }">
<div class="icon" ref="icon"><slot name="icon"></slot></div>
<div class="input" @click="focus">
<span class="label" ref="label"><slot name="label"></slot></span>
<div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
<select ref="input"
<div class="vblkjoeq">
<div class="label" @click="focus"><slot name="label"></slot></div>
<div class="input" :class="{ inline, disabled, focused }">
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
<select ref="inputEl"
v-model="v"
:required="required"
:disabled="disabled"
:required="required"
:readonly="readonly"
:placeholder="placeholder"
@focus="focused = true"
@blur="focused = false"
@input="onInput"
>
<slot></slot>
</select>
<div class="suffix">
<slot name="suffix">
<i class="fas fa-chevron-down"></i>
</slot>
</div>
<div class="suffix" ref="suffixEl"><i class="fas fa-chevron-down"></i></div>
</div>
<div class="text"><slot name="text"></slot></div>
<div class="caption"><slot name="caption"></slot></div>
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import MkButton from './button.vue';
export default defineComponent({
components: {
MkButton,
},
props: {
value: {
required: false
modelValue: {
required: true
},
required: {
type: Boolean,
required: false
},
readonly: {
type: Boolean,
required: false
},
disabled: {
type: Boolean,
required: false
},
placeholder: {
type: String,
required: false
},
autofocus: {
type: Boolean,
required: false,
default: false
},
inline: {
type: Boolean,
required: false,
default: false
},
manualSave: {
type: Boolean,
required: false,
default: false
},
},
data() {
emits: ['change', 'update:modelValue'],
setup(props, context) {
const { modelValue, autofocus } = toRefs(props);
const v = ref(modelValue.value);
const focused = ref(false);
const changed = ref(false);
const invalid = ref(false);
const filled = computed(() => v.value !== '' && v.value != null);
const inputEl = ref(null);
const prefixEl = ref(null);
const suffixEl = ref(null);
const focus = () => inputEl.value.focus();
const onInput = (ev) => {
changed.value = true;
context.emit('change', ev);
};
const updated = () => {
changed.value = false;
context.emit('update:modelValue', v.value);
};
watch(modelValue, newValue => {
v.value = newValue;
});
watch(v, newValue => {
if (!props.manualSave) {
updated();
}
invalid.value = inputEl.value.validity.badInput;
});
onMounted(() => {
nextTick(() => {
if (autofocus.value) {
focus();
}
// このコンポーネントが作成された時、非表示状態である場合がある
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
const clock = setInterval(() => {
if (prefixEl.value) {
if (prefixEl.value.offsetWidth) {
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
}
}
if (suffixEl.value) {
if (suffixEl.value.offsetWidth) {
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px';
}
}
}, 100);
onUnmounted(() => {
clearInterval(clock);
});
});
});
return {
focused: false,
v,
focused,
invalid,
changed,
filled,
inputEl,
prefixEl,
suffixEl,
focus,
onInput,
updated,
};
},
computed: {
v: {
get() {
return this.value;
},
set(v) {
this.$emit('update:value', v);
}
},
filled(): boolean {
return true;
}
},
mounted() {
if (this.$refs.prefix) {
this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
}
},
methods: {
focus() {
this.$refs.input.focus();
}
}
});
</script>
<style lang="scss" scoped>
.eiipwacr {
position: relative;
margin: 32px 0;
.vblkjoeq {
margin: 1.5em 0;
&:not(.inline):first-child {
margin-top: 8px;
> .label {
font-size: 0.85em;
padding: 0 0 8px 12px;
user-select: none;
&:empty {
display: none;
}
}
&:not(.inline):last-child {
margin-bottom: 8px;
}
> .caption {
font-size: 0.8em;
padding: 8px 0 0 12px;
color: var(--fgTransparentWeak);
> .icon {
position: absolute;
top: 0;
left: 0;
width: 24px;
text-align: center;
line-height: 32px;
&:not(:empty) + .input {
margin-left: 28px;
&:empty {
display: none;
}
}
> .input {
display: flex;
$height: 42px;
position: relative;
&:before {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: var(--inputBorder);
}
&:after {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2px;
background: var(--accent);
opacity: 0;
transform: scaleX(0.12);
transition: border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
will-change: border opacity transform;
}
> .label {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
transition: 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-duration: 0.3s;
font-size: 1em;
line-height: 32px;
pointer-events: none;
//will-change transform
transform-origin: top left;
transform: scale(1);
}
> select {
appearance: none;
-webkit-appearance: none;
display: block;
flex: 1;
height: $height;
width: 100%;
padding: 0;
margin: 0;
padding: 0 12px;
font: inherit;
font-weight: normal;
font-size: 1em;
height: 32px;
background: none;
border: none;
border-radius: 0;
color: var(--fg);
background: var(--panel);
border: solid 1px var(--inputBorder);
border-radius: 6px;
outline: none;
box-shadow: none;
appearance: none;
-webkit-appearance: none;
color: var(--fg);
box-sizing: border-box;
cursor: pointer;
transition: border-color 0.1s ease-out;
option,
optgroup {
color: var(--fg);
background: var(--bg);
&:hover {
border-color: var(--inputBorderHover);
}
}
> .prefix,
> .suffix {
display: block;
align-self: center;
justify-self: center;
display: flex;
align-items: center;
position: absolute;
z-index: 1;
top: 0;
padding: 0 12px;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
height: $height;
pointer-events: none;
&:empty {
@ -187,53 +220,41 @@ export default defineComponent({
}
> * {
display: block;
display: inline-block;
min-width: 16px;
max-width: 150px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
> .prefix {
padding-right: 4px;
left: 0;
padding-right: 6px;
}
> .suffix {
padding-left: 4px;
}
}
> .text {
margin: 6px 0;
font-size: 0.8em;
&:empty {
display: none;
right: 0;
padding-left: 6px;
}
* {
&.inline {
display: inline-block;
margin: 0;
}
}
&.focused {
> .input {
&:after {
opacity: 1;
transform: scaleX(1);
}
> .label {
color: var(--accent);
&.focused {
> select {
border-color: var(--accent);
}
}
}
&.focused,
&.filled {
> .input {
> .label {
top: -17px;
left: 0 !important;
transform: scale(0.75);
&.disabled {
opacity: 0.7;
&, * {
cursor: not-allowed !important;
}
}
}

View File

@ -18,7 +18,7 @@
</span>
<span class="label">
<span><slot></slot></span>
<p><slot name="desc"></slot></p>
<p><slot name="caption"></slot></p>
</span>
</div>
</template>
@ -28,7 +28,7 @@ import { defineComponent } from 'vue';
export default defineComponent({
props: {
value: {
modelValue: {
type: Boolean,
default: false
},
@ -39,13 +39,13 @@ export default defineComponent({
},
computed: {
checked(): boolean {
return this.value;
return this.modelValue;
}
},
methods: {
toggle() {
if (this.disabled) return;
this.$emit('update:value', !this.checked);
this.$emit('update:modelValue', !this.checked);
}
}
});
@ -136,7 +136,7 @@ export default defineComponent({
> p {
margin: 0;
opacity: 0.7;
color: var(--fgTransparentWeak);
font-size: 90%;
}
}

View File

@ -1,30 +1,45 @@
<template>
<div class="adhpbeos" :class="{ focused, filled, tall, pre }">
<div class="input">
<span class="label" ref="label"><slot></slot></span>
<textarea ref="input" :class="{ code, _monospace: code }"
:value="value"
<div class="adhpbeos">
<div class="label" @click="focus"><slot name="label"></slot></div>
<div class="input" :class="{ disabled, focused, tall, pre }">
<textarea ref="inputEl"
:class="{ code, _monospace: code }"
v-model="v"
:disabled="disabled"
:required="required"
:readonly="readonly"
:placeholder="placeholder"
:pattern="pattern"
:autocomplete="autocomplete"
:spellcheck="!code"
@input="onInput"
:spellcheck="spellcheck"
@focus="focused = true"
@blur="focused = false"
@keydown="onKeydown($event)"
@input="onInput"
></textarea>
</div>
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $ts.save }}</button>
<div class="desc _caption"><slot name="desc"></slot></div>
<div class="caption"><slot name="caption"></slot></div>
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import MkButton from './button.vue';
import { debounce } from 'throttle-debounce';
export default defineComponent({
components: {
MkButton,
},
props: {
value: {
modelValue: {
required: true
},
type: {
type: String,
required: false
},
required: {
@ -35,14 +50,29 @@ export default defineComponent({
type: Boolean,
required: false
},
disabled: {
type: Boolean,
required: false
},
pattern: {
type: String,
required: false
},
autocomplete: {
placeholder: {
type: String,
required: false
},
autofocus: {
type: Boolean,
required: false,
default: false
},
autocomplete: {
required: false
},
spellcheck: {
required: false
},
code: {
type: Boolean,
required: false
@ -57,169 +87,164 @@ export default defineComponent({
required: false,
default: false
},
save: {
type: Function,
debounce: {
type: Boolean,
required: false,
default: false
},
manualSave: {
type: Boolean,
required: false,
default: false
},
},
data() {
emits: ['change', 'keydown', 'enter', 'update:modelValue'],
setup(props, context) {
const { modelValue, autofocus } = toRefs(props);
const v = ref(modelValue.value);
const focused = ref(false);
const changed = ref(false);
const invalid = ref(false);
const filled = computed(() => v.value !== '' && v.value != null);
const inputEl = ref(null);
const focus = () => inputEl.value.focus();
const onInput = (ev) => {
changed.value = true;
context.emit('change', ev);
};
const onKeydown = (ev: KeyboardEvent) => {
context.emit('keydown', ev);
if (ev.code === 'Enter') {
context.emit('enter');
}
};
const updated = () => {
changed.value = false;
context.emit('update:modelValue', v.value);
};
const debouncedUpdated = debounce(1000, updated);
watch(modelValue, newValue => {
v.value = newValue;
});
watch(v, newValue => {
if (!props.manualSave) {
if (props.debounce) {
debouncedUpdated();
} else {
updated();
}
}
invalid.value = inputEl.value.validity.badInput;
});
onMounted(() => {
nextTick(() => {
if (autofocus.value) {
focus();
}
});
});
return {
focused: false,
changed: false,
}
v,
focused,
invalid,
changed,
filled,
inputEl,
focus,
onInput,
onKeydown,
updated,
};
},
computed: {
filled(): boolean {
return this.value != '' && this.value != null;
}
},
methods: {
focus() {
this.$refs.input.focus();
},
onInput(ev) {
this.changed = true;
this.$emit('update:value', ev.target.value);
}
}
});
</script>
<style lang="scss" scoped>
.adhpbeos {
margin: 42px 0 32px 0;
position: relative;
margin: 1.5em 0;
&:first-child {
margin-top: 16px;
> .label {
font-size: 0.85em;
padding: 0 0 8px 12px;
user-select: none;
&:empty {
display: none;
}
}
&:last-child {
margin-bottom: 0;
> .caption {
font-size: 0.8em;
padding: 8px 0 0 12px;
color: var(--fgTransparentWeak);
&:empty {
display: none;
}
}
> .input {
position: relative;
&:before {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: none;
border: solid 1px var(--inputBorder);
border-radius: 3px;
pointer-events: none;
}
&:after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: none;
border: solid 2px var(--accent);
border-radius: 3px;
opacity: 0;
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
> .label {
position: absolute;
top: 6px;
left: 12px;
pointer-events: none;
transition: 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-duration: 0.3s;
font-size: 1em;
line-height: 32px;
pointer-events: none;
//will-change transform
transform-origin: top left;
transform: scale(1);
}
> textarea {
appearance: none;
-webkit-appearance: none;
display: block;
width: 100%;
min-width: 100%;
max-width: 100%;
min-height: 130px;
margin: 0;
padding: 12px;
box-sizing: border-box;
font: inherit;
font-weight: normal;
font-size: 1em;
background: transparent;
border: none;
border-radius: 0;
color: var(--fg);
background: var(--panel);
border: solid 1px var(--inputBorder);
border-radius: 6px;
outline: none;
box-shadow: none;
color: var(--fg);
box-sizing: border-box;
transition: border-color 0.1s ease-out;
&.code {
tab-size: 2;
&:hover {
border-color: var(--inputBorderHover);
}
}
}
> .save {
margin: 6px 0 0 0;
font-size: 0.8em;
}
> .desc {
margin: 6px 0 0 0;
&:empty {
display: none;
}
* {
margin: 0;
}
}
&.focused {
> .input {
&:after {
opacity: 1;
}
> .label {
color: var(--accent);
&.focused {
> textarea {
border-color: var(--accent);
}
}
}
&.focused,
&.filled {
> .input {
> .label {
top: -24px;
left: 0 !important;
transform: scale(0.75);
&.disabled {
opacity: 0.7;
&, * {
cursor: not-allowed !important;
}
}
}
&.tall {
> .input {
&.tall {
> textarea {
min-height: 200px;
}
}
}
&.pre {
> .input {
&.pre {
> textarea {
white-space: pre;
}

View File

@ -1,17 +1,13 @@
<template>
<transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')">
<div class="ebkgocck" :class="{ front }" v-if="showing">
<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
<div class="body _window _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu">
<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
<button v-else class="_button" @click="close()"><i class="fas fa-times"></i></button>
<button v-if="closeButton" class="_button" @click="close()"><i class="fas fa-times"></i></button>
<span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
<slot name="header"></slot>
</span>
<button v-if="closeRight" class="_button" @click="close()"><i class="fas fa-times"></i></button>
<slot v-else name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
</div>
<div class="body" v-if="padding">
<div class="_section">
@ -86,10 +82,10 @@ export default defineComponent({
required: false,
default: false,
},
closeRight: {
closeButton: {
type: Boolean,
required: false,
default: false,
default: true,
},
mini: {
type: Boolean,
@ -420,6 +416,7 @@ export default defineComponent({
flex-shrink: 0;
user-select: none;
height: var(--height);
border-bottom: solid 1px var(--divider);
> ::v-deep(button) {
height: var(--height);

View File

@ -0,0 +1,58 @@
<template>
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
<div class="ewlycnyt">
<div class="title">{{ $ts.misskeyUpdated }}</div>
<div class="version">{{ version }}🚀</div>
<MkButton full @click="whatIsNew">{{ $ts.whatIsNew }}</MkButton>
<MkButton primary full @click="$refs.modal.close()">{{ $ts.gotIt }}</MkButton>
</div>
</MkModal>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MkModal from '@client/components/ui/modal.vue';
import MkButton from '@client/components/ui/button.vue';
import { version } from '@client/config';
export default defineComponent({
components: {
MkModal,
MkButton,
},
data() {
return {
version: version,
};
},
methods: {
whatIsNew() {
this.$refs.modal.close();
this.$router.push('/docs/general/changelog');
}
}
});
</script>
<style lang="scss" scoped>
.ewlycnyt {
position: relative;
padding: 32px;
min-width: 320px;
max-width: 480px;
box-sizing: border-box;
text-align: center;
background: var(--panel);
border-radius: var(--radius);
> .title {
font-weight: bold;
}
> .version {
margin: 1em 0;
}
}
</style>

View File

@ -31,7 +31,7 @@
import { defineComponent } from 'vue';
import { parseAcct } from '@/misc/acct';
import MkFollowButton from './follow-button.vue';
import { userPage } from '../filters/user';
import { userPage } from '@client/filters/user';
export default defineComponent({
components: {

View File

@ -18,7 +18,7 @@
import { defineComponent } from 'vue';
import paging from '@client/scripts/paging';
import MkUserInfo from './user-info.vue';
import { userPage } from '../filters/user';
import { userPage } from '@client/filters/user';
export default defineComponent({
components: {

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