Merge branch 'develop'

This commit is contained in:
syuilo 2021-10-25 02:34:58 +09:00
commit 6d557269c1
79 changed files with 1260 additions and 1450 deletions

View file

@ -7,6 +7,20 @@
--> -->
## 12.94.0 (2021/10/25)
### Improvements
- クライアント: 画像ビューアを強化
- クライアント: メンションにユーザーのアバターを表示するように
- クライアント: デザインの調整
- クライアント: twemojiをセルフホスティングするように
### Bugfixes
- クライアント: CWで画像が隠されたとき、画像の高さがおかしいことになる問題を修正
### NOTE
- このバージョンから、iOS 15未満のサポートがされなくなります。対象のバージョンをお使いの方は、iOSのバージョンアップを行ってください。
## 12.93.2 (2021/10/23) ## 12.93.2 (2021/10/23)
### Bugfixes ### Bugfixes

BIN
assets/user-unknown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -77,7 +77,9 @@ error: "خطأ"
somethingHappened: "حدث خطأ" somethingHappened: "حدث خطأ"
retry: "حاول مجددًا" retry: "حاول مجددًا"
pageLoadError: "فشل تحميل الصفحة" pageLoadError: "فشل تحميل الصفحة"
pageLoadErrorDescription: "عادة ما يكون السبب خطأ في الشبكة أو التخزين المؤقت للمتصفح. امسح التخزين المؤقت ثم أعد المحاولة لاحقًا."
serverIsDead: "الخادم لا يستجيب، حاول بعد قليل" serverIsDead: "الخادم لا يستجيب، حاول بعد قليل"
youShouldUpgradeClient: "حدّث الصفحة لعرضها."
enterListName: "اسم القائمة" enterListName: "اسم القائمة"
privacy: "الخصوصية" privacy: "الخصوصية"
makeFollowManuallyApprove: "القبول يدويا طلبات الإشتراك" makeFollowManuallyApprove: "القبول يدويا طلبات الإشتراك"
@ -110,6 +112,7 @@ unsuspend: "ألغ التعليق"
blockConfirm: "أمتأكد من حجب هذا الحساب؟" blockConfirm: "أمتأكد من حجب هذا الحساب؟"
unblockConfirm: "أمتأكد من إلغاء حجب هذا الحساب؟" unblockConfirm: "أمتأكد من إلغاء حجب هذا الحساب؟"
selectList: "اختر قائمة" selectList: "اختر قائمة"
selectAntenna: "اختر هوائيًا"
editWidgetsExit: "تم" editWidgetsExit: "تم"
customEmojis: "إيموجي مخصص" customEmojis: "إيموجي مخصص"
emoji: "الوجوه التعبيرية" emoji: "الوجوه التعبيرية"
@ -120,6 +123,7 @@ addEmoji: "إضافة إيموجي"
settingGuide: "الإعدادات المستحسنة" settingGuide: "الإعدادات المستحسنة"
cacheRemoteFiles: "خزن مؤقتا الملفات البعيدة" cacheRemoteFiles: "خزن مؤقتا الملفات البعيدة"
autoAcceptFollowed: "اقبل طلبات المتابعة تلقائيا من الحسابات المتابَعة" autoAcceptFollowed: "اقبل طلبات المتابعة تلقائيا من الحسابات المتابَعة"
addAccount: "أضف حساباً"
loginFailed: "فشل الولوج" loginFailed: "فشل الولوج"
showOnRemote: "رؤيته على مثيل الخادم البُعدي" showOnRemote: "رؤيته على مثيل الخادم البُعدي"
general: "الرئيسية" general: "الرئيسية"
@ -136,8 +140,10 @@ recipient: "المرسَل إليه·ها"
annotation: "التعليقات" annotation: "التعليقات"
federation: "الفديرالية" federation: "الفديرالية"
instances: "مثيل الخادم" instances: "مثيل الخادم"
registeredAt: "مسجل في"
latestRequestSentAt: "آخر طلب أرسِل في" latestRequestSentAt: "آخر طلب أرسِل في"
latestRequestReceivedAt: "آخر طلب تُلقي في" latestRequestReceivedAt: "آخر طلب تُلقي في"
latestStatus: "الحالات الأخيرة"
storageUsage: "مساحة التخزين المستخدمة" storageUsage: "مساحة التخزين المستخدمة"
charts: "المنحنيات البيانية" charts: "المنحنيات البيانية"
perHour: "في الساعة" perHour: "في الساعة"
@ -157,6 +163,8 @@ disk: "قرص التخزين"
instanceInfo: "معلومات مثيل الخادم" instanceInfo: "معلومات مثيل الخادم"
statistics: "الإحصائيات" statistics: "الإحصائيات"
clearQueue: "تفريغ قائمة الإنتظار" clearQueue: "تفريغ قائمة الإنتظار"
clearQueueConfirmTitle: "أتريد مسح الطابور؟"
clearCachedFiles: "امسح التخزين المؤقت"
muteAndBlock: "تم كتمها / تم حجبها" muteAndBlock: "تم كتمها / تم حجبها"
mutedUsers: "الحسابات التي تم كتمها" mutedUsers: "الحسابات التي تم كتمها"
blockedUsers: "الحسابات التي تم حظرها" blockedUsers: "الحسابات التي تم حظرها"
@ -495,6 +503,7 @@ pollVotesCount: "عدد الاستطلاعات المرسلة"
pollVotedCount: "عدد الاستطلاعات المستلمة" pollVotedCount: "عدد الاستطلاعات المستلمة"
yes: "نعم" yes: "نعم"
no: "لا" no: "لا"
clearCache: "امسح التخزين المؤقت"
currentVersion: "الإصدار الحالي" currentVersion: "الإصدار الحالي"
latestVersion: "آخر نسخة مستقرة" latestVersion: "آخر نسخة مستقرة"
usageAmount: "الإستخدام" usageAmount: "الإستخدام"

View file

@ -795,10 +795,10 @@ itsOff: "Ausgeschaltet"
emailRequiredForSignup: "Angaben einer Email-Adresse als benötigt markieren" emailRequiredForSignup: "Angaben einer Email-Adresse als benötigt markieren"
unread: "Ungelesen" unread: "Ungelesen"
filter: "Filter" filter: "Filter"
controllPanel: "Systemsteuerung"
manageAccounts: "Benutzerkonten verwalten" manageAccounts: "Benutzerkonten verwalten"
makeReactionsPublic: "Reaktionsverlauf veröffentlichen" makeReactionsPublic: "Reaktionsverlauf veröffentlichen"
makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktionen einsehen können." makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktionen einsehen können."
classic: "Classic"
_signup: _signup:
almostThere: "Fast geschafft" almostThere: "Fast geschafft"
emailAddressInfo: "Bitte gib deine Email-Adresse ein." emailAddressInfo: "Bitte gib deine Email-Adresse ein."

View file

@ -795,10 +795,11 @@ itsOff: "Disabled"
emailRequiredForSignup: "Require email address for sign-up" emailRequiredForSignup: "Require email address for sign-up"
unread: "Unread" unread: "Unread"
filter: "Filter" filter: "Filter"
controllPanel: "Control Panel" controlPanel: "Control Panel"
manageAccounts: "Manage Accounts" manageAccounts: "Manage Accounts"
makeReactionsPublic: "Set reaction history to public" makeReactionsPublic: "Set reaction history to public"
makeReactionsPublicDescription: "This will make the list of all your past reactions publicly visible." makeReactionsPublicDescription: "This will make the list of all your past reactions publicly visible."
classic: "Classic"
_signup: _signup:
almostThere: "Almost there" almostThere: "Almost there"
emailAddressInfo: "Please enter your email address." emailAddressInfo: "Please enter your email address."

View file

@ -542,7 +542,7 @@ troubleshooting: "Problemsolvi"
learnMore: "Lernu pli" learnMore: "Lernu pli"
translate: "Traduki" translate: "Traduki"
translatedFrom: "Tradukita el {x}" translatedFrom: "Tradukita el {x}"
controllPanel: "Ŝaltpodio" controlPanel: "Ŝaltpodio"
_docs: _docs:
continueReading: "Legi plu" continueReading: "Legi plu"
features: "Funkcioj" features: "Funkcioj"

View file

@ -795,7 +795,7 @@ itsOff: "Désactivé"
emailRequiredForSignup: "Une adresse e-mail est nécessaire pour créer un compte" emailRequiredForSignup: "Une adresse e-mail est nécessaire pour créer un compte"
unread: "Non lu" unread: "Non lu"
filter: "Filtre" filter: "Filtre"
controllPanel: "Panneau de contrôle" controlPanel: "Panneau de contrôle"
manageAccounts: "Gérer les comptes" manageAccounts: "Gérer les comptes"
_signup: _signup:
almostThere: "Bientôt fini" almostThere: "Bientôt fini"

View file

@ -780,7 +780,7 @@ translatedFrom: "Terjemahkan dari {x}"
accountDeletionInProgress: "Penghapusan akun sedang dalam proses" accountDeletionInProgress: "Penghapusan akun sedang dalam proses"
usernameInfo: "Nama yang mengidentifikasikan akun kamu dari yang lain pada server ini. Kamu dapat menggunakan alfabet (a~z, A~Z), digit (0~9) atau garis bawah (_). Username tidak dapat diubah setelahnya." usernameInfo: "Nama yang mengidentifikasikan akun kamu dari yang lain pada server ini. Kamu dapat menggunakan alfabet (a~z, A~Z), digit (0~9) atau garis bawah (_). Username tidak dapat diubah setelahnya."
keepCw: "Biarkan Peringatan Konten" keepCw: "Biarkan Peringatan Konten"
controllPanel: "Panel kontrol" controlPanel: "Panel kontrol"
_accountDelete: _accountDelete:
accountDelete: "Hapus akun" accountDelete: "Hapus akun"
mayTakeTime: "Karena penghapusan akun merupakan proses yang berat dan intensif, kemungkinan dapat membutuhkan waktu untuk menyelesaikan tergantung daripada berapa banyak konten yang kamu buat dan berapa banyak berkas yang telah kamu unggah." mayTakeTime: "Karena penghapusan akun merupakan proses yang berat dan intensif, kemungkinan dapat membutuhkan waktu untuk menyelesaikan tergantung daripada berapa banyak konten yang kamu buat dan berapa banyak berkas yang telah kamu unggah."

View file

@ -795,10 +795,11 @@ itsOff: "オフになっています"
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする" emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする"
unread: "未読" unread: "未読"
filter: "フィルタ" filter: "フィルタ"
controllPanel: "コントロールパネル" controlPanel: "コントロールパネル"
manageAccounts: "アカウントを管理" manageAccounts: "アカウントを管理"
makeReactionsPublic: "リアクション一覧を公開する" makeReactionsPublic: "リアクション一覧を公開する"
makeReactionsPublicDescription: "あなたがしたリアクション一覧を誰でも見れるようにします。" makeReactionsPublicDescription: "あなたがしたリアクション一覧を誰でも見れるようにします。"
classic: "クラシック"
_signup: _signup:
almostThere: "ほとんど完了です" almostThere: "ほとんど完了です"

View file

@ -787,7 +787,7 @@ pubSub: "Pub/Sub 계정"
lastCommunication: "마지막 통신" lastCommunication: "마지막 통신"
resolved: "해결됨" resolved: "해결됨"
unresolved: "해결되지 않음" unresolved: "해결되지 않음"
controllPanel: "제어판" controlPanel: "제어판"
_accountDelete: _accountDelete:
accountDelete: "계정 삭제" accountDelete: "계정 삭제"
mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다." mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다."

View file

@ -784,7 +784,7 @@ accountDeletionInProgress: "В настоящее время выполняет
usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже." usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже."
aiChanMode: "ИИ режим" aiChanMode: "ИИ режим"
keepCw: "Сохраняйте Предупреждения о содержимом" keepCw: "Сохраняйте Предупреждения о содержимом"
controllPanel: "Панель управления" controlPanel: "Панель управления"
manageAccounts: "Управление аккаунтом" manageAccounts: "Управление аккаунтом"
_docs: _docs:
continueReading: "Читать подробнее" continueReading: "Читать подробнее"

View file

@ -795,8 +795,9 @@ itsOff: "已关闭"
emailRequiredForSignup: "注册账户需要电子邮件地址" emailRequiredForSignup: "注册账户需要电子邮件地址"
unread: "未读" unread: "未读"
filter: "筛选" filter: "筛选"
controllPanel: "控制面板" controlPanel: "控制面板"
manageAccounts: "管理账户" manageAccounts: "管理账户"
classic: "经典"
_signup: _signup:
almostThere: "即将完成" almostThere: "即将完成"
emailAddressInfo: "请输入您所使用的电子邮件地址" emailAddressInfo: "请输入您所使用的电子邮件地址"

View file

@ -1,7 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>", "version": "12.94.0",
"version": "12.93.2",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",
@ -38,6 +37,7 @@
"lodash": "^4.17.21" "lodash": "^4.17.21"
}, },
"dependencies": { "dependencies": {
"@discordapp/twemoji": "13.1.0",
"@elastic/elasticsearch": "7.11.0", "@elastic/elasticsearch": "7.11.0",
"@koa/cors": "3.1.0", "@koa/cors": "3.1.0",
"@koa/multer": "3.0.0", "@koa/multer": "3.0.0",
@ -51,18 +51,15 @@
"@types/cbor": "6.0.0", "@types/cbor": "6.0.0",
"@types/dateformat": "3.0.1", "@types/dateformat": "3.0.1",
"@types/escape-regexp": "0.0.0", "@types/escape-regexp": "0.0.0",
"@types/glob": "7.1.4", "@types/glob": "7.2.0",
"@types/gulp": "4.0.9", "@types/gulp": "4.0.9",
"@types/gulp-rename": "2.0.1", "@types/gulp-rename": "2.0.1",
"@types/is-url": "1.2.30", "@types/is-url": "1.2.30",
"@types/js-yaml": "4.0.3", "@types/js-yaml": "4.0.4",
"@types/jsdom": "16.2.13", "@types/jsdom": "16.2.13",
"@types/jsonld": "1.5.6", "@types/jsonld": "1.5.6",
"@types/katex": "0.11.1", "@types/katex": "0.11.1",
"@types/koa": "2.13.4", "@types/koa": "2.13.4",
"@types/koa__cors": "3.0.3",
"@types/koa__multer": "2.0.3",
"@types/koa__router": "8.0.8",
"@types/koa-bodyparser": "4.3.3", "@types/koa-bodyparser": "4.3.3",
"@types/koa-cors": "0.0.2", "@types/koa-cors": "0.0.2",
"@types/koa-favicon": "2.0.21", "@types/koa-favicon": "2.0.21",
@ -70,15 +67,18 @@
"@types/koa-mount": "4.0.1", "@types/koa-mount": "4.0.1",
"@types/koa-send": "4.1.3", "@types/koa-send": "4.1.3",
"@types/koa-views": "7.0.0", "@types/koa-views": "7.0.0",
"@types/koa__cors": "3.0.3",
"@types/koa__multer": "2.0.4",
"@types/koa__router": "8.0.8",
"@types/markdown-it": "12.2.3", "@types/markdown-it": "12.2.3",
"@types/matter-js": "0.17.5", "@types/matter-js": "0.17.6",
"@types/mocha": "8.2.3", "@types/mocha": "8.2.3",
"@types/node": "16.10.3", "@types/node": "16.11.4",
"@types/node-fetch": "2.5.12", "@types/node-fetch": "2.5.12",
"@types/nodemailer": "6.4.4", "@types/nodemailer": "6.4.4",
"@types/nprogress": "0.2.0", "@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1", "@types/oauth": "0.9.1",
"@types/parse5": "6.0.1", "@types/parse5": "6.0.2",
"@types/parsimmon": "1.10.6", "@types/parsimmon": "1.10.6",
"@types/portscanner": "2.1.1", "@types/portscanner": "2.1.1",
"@types/pug": "2.0.5", "@types/pug": "2.0.5",
@ -96,21 +96,20 @@
"@types/speakeasy": "2.0.6", "@types/speakeasy": "2.0.6",
"@types/throttle-debounce": "2.1.0", "@types/throttle-debounce": "2.1.0",
"@types/tinycolor2": "1.4.3", "@types/tinycolor2": "1.4.3",
"@types/tmp": "0.2.1", "@types/tmp": "0.2.2",
"@types/uuid": "8.3.1", "@types/uuid": "8.3.1",
"@types/web-push": "3.3.2", "@types/web-push": "3.3.2",
"@types/webpack": "5.28.0", "@types/webpack": "5.28.0",
"@types/webpack-stream": "3.2.12", "@types/webpack-stream": "3.2.12",
"@types/websocket": "1.0.4", "@types/websocket": "1.0.4",
"@types/ws": "8.2.0", "@types/ws": "8.2.0",
"@typescript-eslint/parser": "5.0.0", "@typescript-eslint/parser": "5.1.0",
"@vue/compiler-sfc": "3.2.20", "@vue/compiler-sfc": "3.2.20",
"abort-controller": "3.0.0", "abort-controller": "3.0.0",
"apexcharts": "3.28.3",
"autobind-decorator": "2.4.0", "autobind-decorator": "2.4.0",
"autosize": "4.0.4", "autosize": "4.0.4",
"autwh": "0.1.0", "autwh": "0.1.0",
"aws-sdk": "2.1003.0", "aws-sdk": "2.1013.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "1.1.4", "blurhash": "1.1.4",
"broadcast-channel": "4.2.0", "broadcast-channel": "4.2.0",
@ -119,7 +118,7 @@
"cafy": "15.2.1", "cafy": "15.2.1",
"cbor": "8.0.2", "cbor": "8.0.2",
"chalk": "4.1.2", "chalk": "4.1.2",
"chart.js": "3.5.1", "chart.js": "3.6.0",
"chartjs-adapter-date-fns": "2.0.0", "chartjs-adapter-date-fns": "2.0.0",
"chartjs-plugin-zoom": "1.1.1", "chartjs-plugin-zoom": "1.1.1",
"cli-highlight": "2.1.11", "cli-highlight": "2.1.11",
@ -132,8 +131,8 @@
"date-fns": "2.25.0", "date-fns": "2.25.0",
"dateformat": "4.5.1", "dateformat": "4.5.1",
"escape-regexp": "0.0.1", "escape-regexp": "0.0.1",
"eslint": "8.0.1", "eslint": "8.1.0",
"eslint-plugin-vue": "7.19.1", "eslint-plugin-vue": "7.20.0",
"eventemitter3": "4.0.7", "eventemitter3": "4.0.7",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "16.5.3", "file-type": "16.5.3",
@ -159,7 +158,7 @@
"jsonld": "5.2.0", "jsonld": "5.2.0",
"jsrsasign": "8.0.20", "jsrsasign": "8.0.20",
"katex": "0.13.18", "katex": "0.13.18",
"koa": "2.13.3", "koa": "2.13.4",
"koa-bodyparser": "4.3.0", "koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0", "koa-favicon": "2.1.0",
"koa-json-body": "5.3.0", "koa-json-body": "5.3.0",
@ -173,7 +172,7 @@
"markdown-it-anchor": "7.1.0", "markdown-it-anchor": "7.1.0",
"matter-js": "0.17.1", "matter-js": "0.17.1",
"mfm-js": "0.20.0", "mfm-js": "0.20.0",
"misskey-js": "0.0.6", "misskey-js": "0.0.8",
"mocha": "8.4.0", "mocha": "8.4.0",
"ms": "2.1.3", "ms": "2.1.3",
"multer": "1.4.3", "multer": "1.4.3",
@ -183,8 +182,9 @@
"os-utils": "0.0.14", "os-utils": "0.0.14",
"parse5": "6.0.1", "parse5": "6.0.1",
"pg": "8.7.1", "pg": "8.7.1",
"photoswipe": "git://github.com/dimsemenov/photoswipe#v5-beta",
"portscanner": "2.2.0", "portscanner": "2.2.0",
"postcss": "8.3.9", "postcss": "8.3.11",
"postcss-loader": "6.2.0", "postcss-loader": "6.2.0",
"prismjs": "1.25.0", "prismjs": "1.25.0",
"private-ip": "2.3.0", "private-ip": "2.3.0",
@ -206,17 +206,17 @@
"rimraf": "3.0.2", "rimraf": "3.0.2",
"rndstr": "1.0.0", "rndstr": "1.0.0",
"s-age": "1.1.2", "s-age": "1.1.2",
"sass": "1.43.2", "sass": "1.43.3",
"sass-loader": "12.2.0", "sass-loader": "12.2.0",
"seedrandom": "3.0.5", "seedrandom": "3.0.5",
"sharp": "0.29.1", "sharp": "0.29.2",
"speakeasy": "2.0.0", "speakeasy": "2.0.0",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"style-loader": "3.3.0", "style-loader": "3.3.1",
"summaly": "2.4.1", "summaly": "2.4.1",
"syslog-pro": "1.0.0", "syslog-pro": "1.0.0",
"systeminformation": "5.9.7", "systeminformation": "5.9.8",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"three": "0.117.1", "three": "0.117.1",
@ -224,7 +224,7 @@
"tinycolor2": "1.4.2", "tinycolor2": "1.4.2",
"tmp": "0.2.1", "tmp": "0.2.1",
"ts-loader": "9.2.6", "ts-loader": "9.2.6",
"ts-node": "10.3.0", "ts-node": "10.4.0",
"tsc-alias": "1.3.10", "tsc-alias": "1.3.10",
"tsconfig-paths": "3.11.0", "tsconfig-paths": "3.11.0",
"tslint": "6.1.3", "tslint": "6.1.3",
@ -244,8 +244,8 @@
"vue-svg-loader": "0.17.0-beta.2", "vue-svg-loader": "0.17.0-beta.2",
"vuedraggable": "4.0.1", "vuedraggable": "4.0.1",
"web-push": "3.4.5", "web-push": "3.4.5",
"webpack": "5.58.2", "webpack": "5.59.1",
"webpack-cli": "4.9.0", "webpack-cli": "4.9.1",
"websocket": "1.0.34", "websocket": "1.0.34",
"ws": "8.2.3", "ws": "8.2.3",
"xev": "2.0.1" "xev": "2.0.1"

View file

@ -89,6 +89,16 @@ export default defineComponent({
required: false, required: false,
default: false default: false
}, },
stacked: {
type: Boolean,
required: false,
default: false
},
aspectRatio: {
type: Number,
required: false,
default: null
},
}, },
setup(props) { setup(props) {
@ -157,7 +167,7 @@ export default defineComponent({
})), })),
}, },
options: { options: {
aspectRatio: 2.5, aspectRatio: props.aspectRatio || 2.5,
layout: { layout: {
padding: { padding: {
left: 16, left: 16,
@ -174,7 +184,6 @@ export default defineComponent({
unit: props.span === 'day' ? 'month' : 'day', unit: props.span === 'day' ? 'month' : 'day',
}, },
grid: { grid: {
display: props.detailed,
color: gridColor, color: gridColor,
borderColor: 'rgb(0, 0, 0, 0)', borderColor: 'rgb(0, 0, 0, 0)',
}, },
@ -190,6 +199,7 @@ export default defineComponent({
}, },
y: { y: {
position: 'left', position: 'left',
stacked: props.stacked,
grid: { grid: {
color: gridColor, color: gridColor,
borderColor: 'rgb(0, 0, 0, 0)', borderColor: 'rgb(0, 0, 0, 0)',
@ -204,6 +214,7 @@ export default defineComponent({
}, },
plugins: { plugins: {
legend: { legend: {
display: props.detailed,
position: 'bottom', position: 'bottom',
labels: { labels: {
boxWidth: 16, boxWidth: 16,
@ -583,6 +594,30 @@ export default defineComponent({
}; };
}; };
const fetchPerUserNotesChart = async (): Promise<typeof data> => {
const raw = await os.api('charts/user/notes', { userId: props.args.user.id, limit: props.limit, span: props.span });
return {
series: [...(props.args.withoutAll ? [] : [{
name: 'All',
type: 'line',
borderDash: [5, 5],
data: format(sum(raw.inc, negate(raw.dec))),
}]), {
name: 'Renotes',
type: 'area',
data: format(raw.diffs.renote),
}, {
name: 'Replies',
type: 'area',
data: format(raw.diffs.reply),
}, {
name: 'Normal',
type: 'area',
data: format(raw.diffs.normal),
}],
};
};
const fetchAndRender = async () => { const fetchAndRender = async () => {
const fetchData = () => { const fetchData = () => {
switch (props.src) { switch (props.src) {
@ -611,6 +646,8 @@ export default defineComponent({
case 'instance-drive-usage-total': return fetchInstanceDriveUsageChart(true); case 'instance-drive-usage-total': return fetchInstanceDriveUsageChart(true);
case 'instance-drive-files': return fetchInstanceDriveFilesChart(false); case 'instance-drive-files': return fetchInstanceDriveFilesChart(false);
case 'instance-drive-files-total': return fetchInstanceDriveFilesChart(true); case 'instance-drive-files-total': return fetchInstanceDriveFilesChart(true);
case 'per-user-notes': return fetchPerUserNotesChart();
} }
}; };
fetching.value = true; fetching.value = true;

View file

@ -2,8 +2,8 @@
<div class="fdidabkb" :class="{ slim: narrow, thin: thin_ }" :style="{ background: bg }" @click="onClick" ref="el"> <div class="fdidabkb" :class="{ slim: narrow, thin: thin_ }" :style="{ background: bg }" @click="onClick" ref="el">
<template v-if="info"> <template v-if="info">
<div class="titleContainer" @click="showTabsPopup" v-if="!hideTitle"> <div class="titleContainer" @click="showTabsPopup" v-if="!hideTitle">
<i v-if="info.icon" class="icon" :class="info.icon"></i> <MkAvatar v-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/>
<MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <i v-else-if="info.icon" class="icon" :class="info.icon"></i>
<div class="title"> <div class="title">
<MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/> <MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/>
@ -162,11 +162,6 @@ export default defineComponent({
onUnmounted(() => { onUnmounted(() => {
ro.disconnect(); ro.disconnect();
}); });
setTimeout(() => {
const currentStickyTop = getComputedStyle(el.value.parentElement).getPropertyValue('--stickyTop') || '0px';
el.value.style.setProperty('--stickyTop', currentStickyTop);
el.value.parentElement.style.setProperty('--stickyTop', `calc(${currentStickyTop} + ${el.value.offsetHeight}px)`);
}, 100); // stickyTop
} }
}); });

View file

@ -0,0 +1,74 @@
<template>
<div ref="rootEl">
<slot name="header"></slot>
<div ref="bodyEl">
<slot></slot>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, ref } from 'vue';
export default defineComponent({
props: {
autoSticky: {
type: Boolean,
required: false,
default: false,
},
},
setup(props, context) {
const rootEl = ref<HTMLElement>(null);
const bodyEl = ref<HTMLElement>(null);
const calc = () => {
const currentStickyTop = getComputedStyle(rootEl.value).getPropertyValue('--stickyTop') || '0px';
const header = rootEl.value.children[0];
if (header === bodyEl.value) {
bodyEl.value.style.setProperty('--stickyTop', currentStickyTop);
} else {
bodyEl.value.style.setProperty('--stickyTop', `calc(${currentStickyTop} + ${header.offsetHeight}px)`);
if (props.autoSticky) {
header.style.setProperty('--stickyTop', currentStickyTop);
header.style.position = 'sticky';
header.style.top = 'var(--stickyTop)';
header.style.zIndex = '1';
}
}
};
onMounted(() => {
calc();
const observer = new MutationObserver(() => {
setTimeout(() => {
calc();
}, 100);
});
observer.observe(rootEl.value, {
attributes: false,
childList: true,
subtree: false,
});
onUnmounted(() => {
observer.disconnect();
});
});
return {
rootEl,
bodyEl,
};
},
});
</script>
<style lang="scss" module>
</style>

View file

@ -15,6 +15,7 @@ import error from './global/error.vue';
import ad from './global/ad.vue'; import ad from './global/ad.vue';
import header from './global/header.vue'; import header from './global/header.vue';
import spacer from './global/spacer.vue'; import spacer from './global/spacer.vue';
import stickyContainer from './global/sticky-container.vue';
export default function(app: App) { export default function(app: App) {
app.component('I18n', i18n); app.component('I18n', i18n);
@ -32,4 +33,5 @@ export default function(app: App) {
app.component('MkAd', ad); app.component('MkAd', ad);
app.component('MkHeader', header); app.component('MkHeader', header);
app.component('MkSpacer', spacer); app.component('MkSpacer', spacer);
app.component('MkStickyContainer', stickyContainer);
} }

View file

@ -12,7 +12,6 @@
<a <a
:href="image.url" :href="image.url"
:title="image.name" :title="image.name"
@click.prevent="onClick"
> >
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/> <ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
<div class="gif" v-if="image.type === 'image/gif'">GIF</div> <div class="gif" v-if="image.type === 'image/gif'">GIF</div>
@ -73,17 +72,6 @@ export default defineComponent({
immediate: true, immediate: true,
}); });
}, },
methods: {
onClick() {
if (this.$store.state.imageNewTab) {
window.open(this.image.url, '_blank');
} else {
os.popup(ImageViewer, {
image: this.image
}, {}, 'closed');
}
}
}
}); });
</script> </script>

View file

@ -1,11 +1,11 @@
<template> <template>
<div class="mk-media-list"> <div class="hoawjimk">
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/> <XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/>
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container" ref="gridOuter"> <div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
<div :data-count="mediaList.filter(media => previewable(media)).length" :style="gridInnerStyle"> <div :data-count="mediaList.filter(media => previewable(media)).length" ref="gallery">
<template v-for="media in mediaList"> <template v-for="media in mediaList">
<XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/> <XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/>
<XImage :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/> <XImage class="image" :data-id="media.id" :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/>
</template> </template>
</div> </div>
</div> </div>
@ -13,11 +13,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, onMounted, PropType, ref } from 'vue';
import * as misskey from 'misskey-js';
import PhotoSwipeLightbox from 'photoswipe/dist/photoswipe-lightbox.esm.js';
import PhotoSwipe from 'photoswipe/dist/photoswipe.esm.js';
import 'photoswipe/dist/photoswipe.css';
import XBanner from './media-banner.vue'; import XBanner from './media-banner.vue';
import XImage from './media-image.vue'; import XImage from './media-image.vue';
import XVideo from './media-video.vue'; import XVideo from './media-video.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import { defaultStore } from '@client/store';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -27,63 +32,63 @@ export default defineComponent({
}, },
props: { props: {
mediaList: { mediaList: {
required: true type: Array as PropType<misskey.entities.DriveFile[]>,
required: true,
}, },
raw: { raw: {
default: false default: false
}, },
}, },
data() { setup(props) {
return { const gallery = ref(null);
gridInnerStyle: {},
sizeWaiting: false
}
},
mounted() {
this.size();
window.addEventListener('resize', this.size);
},
beforeUnmount() {
window.removeEventListener('resize', this.size);
},
activated() {
this.size();
},
methods: {
previewable(file) {
return file.type.startsWith('video') || file.type.startsWith('image');
},
size() {
// for Safari bug
if (this.sizeWaiting) return;
this.sizeWaiting = true; onMounted(() => {
const lightbox = new PhotoSwipeLightbox({
window.requestAnimationFrame(() => { dataSource: props.mediaList.filter(media => media.type.startsWith('image')).map(media => ({
this.sizeWaiting = false; src: media.url,
w: media.properties.width,
if (this.$refs.gridOuter) { h: media.properties.height,
let height = 287; alt: media.name,
const parent = this.$parent.$el; })),
gallery: gallery.value,
if (this.$refs.gridOuter.clientHeight) { children: '.image',
height = this.$refs.gridOuter.clientHeight; thumbSelector: '.image',
} else if (parent) { pswpModule: PhotoSwipe
height = parent.getBoundingClientRect().width * 9 / 16;
}
this.gridInnerStyle = { height: `${height}px` };
} else {
this.gridInnerStyle = {};
}
}); });
}
lightbox.on('itemData', (e) => {
const { itemData } = e;
// element is children
const { element } = itemData;
const id = element.dataset.id;
const file = props.mediaList.find(media => media.id === id);
itemData.src = file.url;
itemData.w = Number(file.properties.width);
itemData.h = Number(file.properties.height);
itemData.msrc = file.thumbnailUrl;
itemData.thumbCropped = true;
});
lightbox.init();
});
const previewable = (file: misskey.entities.DriveFile): boolean => {
return file.type.startsWith('video') || file.type.startsWith('image');
};
return {
previewable,
gallery,
};
}, },
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.mk-media-list { .hoawjimk {
> .gird-container { > .gird-container {
position: relative; position: relative;
width: 100%; width: 100%;

View file

@ -1,6 +1,7 @@
<template> <template>
<MkA class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')"> <MkA class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
<span class="me" v-if="isMe">{{ $ts.you }}</span> <span class="me" v-if="isMe">{{ $ts.you }}</span>
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
<span class="main"> <span class="main">
<span class="username">@{{ username }}</span> <span class="username">@{{ username }}</span>
<span class="host" v-if="(host != localHost) || $store.state.showFullAcct">@{{ toUnicode(host) }}</span> <span class="host" v-if="(host != localHost) || $store.state.showFullAcct">@{{ toUnicode(host) }}</span>
@ -76,6 +77,13 @@ export default defineComponent({
vertical-align: top; vertical-align: top;
} }
> .icon {
width: 1.5em;
margin: 0 0.2em;
vertical-align: bottom;
border-radius: 100%;
}
> .main { > .main {
> .host { > .host {
opacity: 0.5; opacity: 0.5;

View file

@ -10,10 +10,13 @@
</span> </span>
<button class="_button" @click="$refs.modal.close()"><i class="fas fa-times"></i></button> <button class="_button" @click="$refs.modal.close()"><i class="fas fa-times"></i></button>
</div> </div>
<div class="body _fitSide_"> <div class="body">
<keep-alive> <MkStickyContainer>
<component :is="component" v-bind="props" :ref="changePage"/> <template #header><MkHeader v-if="pageInfo && !pageInfo.hideHeader" :info="pageInfo"/></template>
</keep-alive> <keep-alive>
<component :is="component" v-bind="props" :ref="changePage"/>
</keep-alive>
</MkStickyContainer>
</div> </div>
</div> </div>
</MkModal> </MkModal>

View file

@ -16,8 +16,11 @@
<template #headerLeft> <template #headerLeft>
<button v-if="history.length > 0" class="_button" @click="back()" v-tooltip="$ts.goBack"><i class="fas fa-arrow-left"></i></button> <button v-if="history.length > 0" class="_button" @click="back()" v-tooltip="$ts.goBack"><i class="fas fa-arrow-left"></i></button>
</template> </template>
<div class="yrolvcoq _fitSide_"> <div class="yrolvcoq">
<component :is="component" v-bind="props" :ref="changePage"/> <MkStickyContainer>
<template #header><MkHeader v-if="pageInfo && !pageInfo.hideHeader" :info="pageInfo"/></template>
<component :is="component" v-bind="props" :ref="changePage"/>
</MkStickyContainer>
</div> </div>
</XWindow> </XWindow>
</template> </template>

View file

@ -79,6 +79,7 @@ export default defineComponent({
pointRadius: 0, pointRadius: 0,
tension: 0, tension: 0,
borderWidth: 2, borderWidth: 2,
borderJoinStyle: 'round',
borderColor: '#00E396', borderColor: '#00E396',
backgroundColor: alpha('#00E396', 0.1), backgroundColor: alpha('#00E396', 0.1),
data: [] data: []
@ -87,6 +88,7 @@ export default defineComponent({
pointRadius: 0, pointRadius: 0,
tension: 0, tension: 0,
borderWidth: 2, borderWidth: 2,
borderJoinStyle: 'round',
borderColor: '#00BCD4', borderColor: '#00BCD4',
backgroundColor: alpha('#00BCD4', 0.1), backgroundColor: alpha('#00BCD4', 0.1),
data: [] data: []
@ -95,17 +97,21 @@ export default defineComponent({
pointRadius: 0, pointRadius: 0,
tension: 0, tension: 0,
borderWidth: 2, borderWidth: 2,
borderJoinStyle: 'round',
borderColor: '#FFB300', borderColor: '#FFB300',
backgroundColor: alpha('#FFB300', 0.1), backgroundColor: alpha('#FFB300', 0.1),
yAxisID: 'y2',
data: [] data: []
}, { }, {
label: 'Delayed', label: 'Delayed',
pointRadius: 0, pointRadius: 0,
tension: 0, tension: 0,
borderWidth: 2, borderWidth: 2,
borderJoinStyle: 'round',
borderColor: '#E53935', borderColor: '#E53935',
borderDash: [5, 5], borderDash: [5, 5],
fill: false, fill: false,
yAxisID: 'y2',
data: [] data: []
}], }],
}, },
@ -122,15 +128,29 @@ export default defineComponent({
scales: { scales: {
x: { x: {
grid: { grid: {
display: false, display: true,
color: gridColor, color: gridColor,
borderColor: 'rgb(0, 0, 0, 0)', borderColor: 'rgb(0, 0, 0, 0)',
}, },
ticks: { ticks: {
display: false, display: false,
maxTicksLimit: 10
}, },
}, },
y: { y: {
min: 0,
stack: 'queue',
stackWeight: 2,
grid: {
color: gridColor,
borderColor: 'rgb(0, 0, 0, 0)',
},
},
y2: {
min: 0,
offset: true,
stack: 'queue',
stackWeight: 1,
grid: { grid: {
color: gridColor, color: gridColor,
borderColor: 'rgb(0, 0, 0, 0)', borderColor: 'rgb(0, 0, 0, 0)',

View file

@ -1,23 +1,25 @@
<template> <template>
<MkTooltip :source="source" ref="tooltip" @closed="$emit('closed')"> <MkTooltip :source="source" ref="tooltip" @closed="$emit('closed')" :max-width="340">
<div class="bqxuuuey"> <div class="bqxuuuey">
<div class="info"> <div class="reaction">
<div>{{ reaction.replace('@.', '') }}</div>
<XReactionIcon :reaction="reaction" :custom-emojis="emojis" class="icon" :no-style="true"/> <XReactionIcon :reaction="reaction" :custom-emojis="emojis" class="icon" :no-style="true"/>
<div class="name">{{ reaction.replace('@.', '') }}</div>
</div>
<div class="users">
<template v-if="users.length <= 10">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
</template>
<template v-if="10 < users.length">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
<span slot="omitted">+{{ count - 10 }}</span>
</template>
</div> </div>
<template v-if="users.length <= 10">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
</template>
<template v-if="10 < users.length">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<MkAvatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<MkUserName :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
<span slot="omitted">+{{ count - 10 }}</span>
</template>
</div> </div>
</MkTooltip> </MkTooltip>
</template> </template>
@ -59,8 +61,11 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.bqxuuuey { .bqxuuuey {
> .info { display: flex;
padding: 0 0 8px 0;
> .reaction {
flex: 1;
max-width: 100px;
text-align: center; text-align: center;
> .icon { > .icon {
@ -68,6 +73,19 @@ export default defineComponent({
width: 60px; width: 60px;
margin: 0 auto; margin: 0 auto;
} }
> .name {
font-size: 0.9em;
}
}
> .users {
flex: 1;
min-width: 0;
font-size: 0.9em;
border-left: solid 0.5px var(--divider);
padding-left: 10px;
margin-left: 10px;
} }
} }
</style> </style>

View file

@ -177,6 +177,7 @@ export default defineComponent({
> span { > span {
font-size: 0.9em; font-size: 0.9em;
line-height: 32px; line-height: 32px;
margin: 0 0 0 4px;
} }
} }
</style> </style>

View file

@ -153,10 +153,4 @@ export default defineComponent({
} }
} }
} }
._fitSide_ .ssazuxis {
> header {
padding: 0 16px;
}
}
</style> </style>

View file

@ -42,8 +42,4 @@ export default defineComponent({
margin-right: 4px; margin-right: 4px;
} }
} }
._fitSide_ .fpezltsf {
border-radius: 0;
}
</style> </style>

View file

@ -50,9 +50,6 @@ export default defineComponent({
border-top: solid 0.5px var(--divider); border-top: solid 0.5px var(--divider);
} }
margin-left: 16px;
margin-right: 16px;
> .title { > .title {
font-size: 0.9em; font-size: 0.9em;
opacity: 0.7; opacity: 0.7;
@ -120,7 +117,7 @@ export default defineComponent({
> .items { > .items {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
grid-gap: 8px; grid-gap: 8px;
padding: 0 16px; padding: 0 16px;

View file

@ -1,6 +1,6 @@
<template> <template>
<transition name="tooltip" appear @after-leave="$emit('closed')"> <transition name="tooltip" appear @after-leave="$emit('closed')">
<div class="buebdbiu _acrylic _shadow" v-show="showing" ref="content"> <div class="buebdbiu _acrylic _shadow" v-show="showing" ref="content" :style="{ maxWidth: maxWidth + 'px' }">
<slot>{{ text }}</slot> <slot>{{ text }}</slot>
</div> </div>
</transition> </transition>
@ -21,7 +21,12 @@ export default defineComponent({
text: { text: {
type: String, type: String,
required: false required: false
} },
maxWidth: {
type: Number,
required: false,
default: 250,
},
}, },
emits: ['closed'], emits: ['closed'],
@ -75,11 +80,12 @@ export default defineComponent({
.buebdbiu { .buebdbiu {
position: absolute; position: absolute;
z-index: 11000; z-index: 11000;
max-width: 240px;
font-size: 0.8em; font-size: 0.8em;
padding: 8px 12px; padding: 8px 12px;
box-sizing: border-box;
text-align: center; text-align: center;
border-radius: 4px; border-radius: 4px;
border: solid 0.5px var(--divider);
pointer-events: none; pointer-events: none;
transform-origin: center bottom; transform-origin: center bottom;
} }

View file

@ -166,8 +166,8 @@ const app = createApp(await (
ui === 'deck' ? import('@client/ui/deck.vue') : ui === 'deck' ? import('@client/ui/deck.vue') :
ui === 'desktop' ? import('@client/ui/desktop.vue') : ui === 'desktop' ? import('@client/ui/desktop.vue') :
ui === 'chat' ? import('@client/ui/chat/index.vue') : ui === 'chat' ? import('@client/ui/chat/index.vue') :
ui === 'pope' ? import('@client/ui/universal.vue') : ui === 'classic' ? import('@client/ui/classic.vue') :
import('@client/ui/default.vue') import('@client/ui/universal.vue')
).then(x => x.default)); ).then(x => x.default));
if (_DEV_) { if (_DEV_) {

View file

@ -2,6 +2,7 @@ import { computed, ref } from 'vue';
import { search } from '@client/scripts/search'; import { search } from '@client/scripts/search';
import * as os from '@client/os'; import * as os from '@client/os';
import { i18n } from '@client/i18n'; import { i18n } from '@client/i18n';
import { ui } from '@client/config';
import { $i } from './account'; import { $i } from './account';
import { unisonReload } from '@client/scripts/unison-reload'; import { unisonReload } from '@client/scripts/unison-reload';
import { router } from './router'; import { router } from './router';
@ -184,35 +185,40 @@ export const menuDef = {
action: (ev) => { action: (ev) => {
os.popupMenu([{ os.popupMenu([{
text: i18n.locale.default, text: i18n.locale.default,
active: ui === 'default' || ui === null,
action: () => { action: () => {
localStorage.setItem('ui', 'default'); localStorage.setItem('ui', 'default');
unisonReload(); unisonReload();
} }
}, { }, {
text: i18n.locale.deck, text: i18n.locale.deck,
active: ui === 'deck',
action: () => { action: () => {
localStorage.setItem('ui', 'deck'); localStorage.setItem('ui', 'deck');
unisonReload(); unisonReload();
} }
}, { }, {
text: 'pope', text: i18n.locale.classic,
active: ui === 'classic',
action: () => { action: () => {
localStorage.setItem('ui', 'pope'); localStorage.setItem('ui', 'classic');
unisonReload(); unisonReload();
} }
}, { }, {
text: 'Chat (β)', text: 'Chat (β)',
active: ui === 'chat',
action: () => { action: () => {
localStorage.setItem('ui', 'chat'); localStorage.setItem('ui', 'chat');
unisonReload(); unisonReload();
} }
}, { }, /*{
text: i18n.locale.desktop + ' (β)', text: i18n.locale.desktop + ' (β)',
active: ui === 'desktop',
action: () => { action: () => {
localStorage.setItem('ui', 'desktop'); localStorage.setItem('ui', 'desktop');
unisonReload(); unisonReload();
} }
}], ev.currentTarget || ev.target); }*/], ev.currentTarget || ev.target);
}, },
}, },
}; };

View file

@ -1,45 +1,42 @@
<template> <template>
<div> <div class="uqshojas">
<MkHeader :info="header"/> <section class="_card _gap ads" v-for="ad in ads">
<div class="uqshojas"> <div class="_content ad">
<section class="_card _gap ads" v-for="ad in ads"> <MkAd v-if="ad.url" :specify="ad"/>
<div class="_content ad"> <MkInput v-model="ad.url" type="url">
<MkAd v-if="ad.url" :specify="ad"/> <template #label>URL</template>
<MkInput v-model="ad.url" type="url"> </MkInput>
<template #label>URL</template> <MkInput v-model="ad.imageUrl">
</MkInput> <template #label>{{ $ts.imageUrl }}</template>
<MkInput v-model="ad.imageUrl"> </MkInput>
<template #label>{{ $ts.imageUrl }}</template> <div style="margin: 32px 0;">
</MkInput> <MkRadio v-model="ad.place" value="square">square</MkRadio>
<div style="margin: 32px 0;"> <MkRadio v-model="ad.place" value="horizontal">horizontal</MkRadio>
<MkRadio v-model="ad.place" value="square">square</MkRadio> <MkRadio v-model="ad.place" value="horizontal-big">horizontal-big</MkRadio>
<MkRadio v-model="ad.place" value="horizontal">horizontal</MkRadio>
<MkRadio v-model="ad.place" value="horizontal-big">horizontal-big</MkRadio>
</div>
<!--
<div style="margin: 32px 0;">
{{ $ts.priority }}
<MkRadio v-model="ad.priority" value="high">{{ $ts.high }}</MkRadio>
<MkRadio v-model="ad.priority" value="middle">{{ $ts.middle }}</MkRadio>
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
</div>
-->
<MkInput v-model="ad.ratio" type="number">
<template #label>{{ $ts.ratio }}</template>
</MkInput>
<MkInput v-model="ad.expiresAt" type="date">
<template #label>{{ $ts.expiration }}</template>
</MkInput>
<MkTextarea v-model="ad.memo">
<template #label>{{ $ts.memo }}</template>
</MkTextarea>
<div class="buttons">
<MkButton class="button" inline @click="save(ad)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton class="button" inline @click="remove(ad)" danger><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
</div>
</div> </div>
</section> <!--
</div> <div style="margin: 32px 0;">
{{ $ts.priority }}
<MkRadio v-model="ad.priority" value="high">{{ $ts.high }}</MkRadio>
<MkRadio v-model="ad.priority" value="middle">{{ $ts.middle }}</MkRadio>
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
</div>
-->
<MkInput v-model="ad.ratio" type="number">
<template #label>{{ $ts.ratio }}</template>
</MkInput>
<MkInput v-model="ad.expiresAt" type="date">
<template #label>{{ $ts.expiration }}</template>
</MkInput>
<MkTextarea v-model="ad.memo">
<template #label>{{ $ts.memo }}</template>
</MkTextarea>
<div class="buttons">
<MkButton class="button" inline @click="save(ad)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton class="button" inline @click="remove(ad)" danger><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
</div>
</div>
</section>
</div> </div>
</template> </template>
@ -68,11 +65,6 @@ export default defineComponent({
title: this.$ts.ads, title: this.$ts.ads,
icon: 'fas fa-audio-description', icon: 'fas fa-audio-description',
bg: 'var(--bg)', bg: 'var(--bg)',
},
header: {
title: this.$ts.ads,
icon: 'fas fa-audio-description',
bg: 'var(--bg)',
actions: [{ actions: [{
asFullButton: true, asFullButton: true,
icon: 'fas fa-plus', icon: 'fas fa-plus',

View file

@ -1,27 +1,23 @@
<template> <template>
<div> <div class="ztgjmzrw">
<MkHeader :info="header"/> <section class="_card _gap announcements" v-for="announcement in announcements">
<div class="_content announcement">
<div class="ztgjmzrw"> <MkInput v-model="announcement.title">
<section class="_card _gap announcements" v-for="announcement in announcements"> <template #label>{{ $ts.title }}</template>
<div class="_content announcement"> </MkInput>
<MkInput v-model="announcement.title"> <MkTextarea v-model="announcement.text">
<template #label>{{ $ts.title }}</template> <template #label>{{ $ts.text }}</template>
</MkInput> </MkTextarea>
<MkTextarea v-model="announcement.text"> <MkInput v-model="announcement.imageUrl">
<template #label>{{ $ts.text }}</template> <template #label>{{ $ts.imageUrl }}</template>
</MkTextarea> </MkInput>
<MkInput v-model="announcement.imageUrl"> <p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p>
<template #label>{{ $ts.imageUrl }}</template> <div class="buttons">
</MkInput> <MkButton class="button" inline @click="save(announcement)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p> <MkButton class="button" inline @click="remove(announcement)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
<div class="buttons">
<MkButton class="button" inline @click="save(announcement)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton class="button" inline @click="remove(announcement)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
</div>
</div> </div>
</section> </div>
</div> </section>
</div> </div>
</template> </template>
@ -48,11 +44,6 @@ export default defineComponent({
title: this.$ts.announcements, title: this.$ts.announcements,
icon: 'fas fa-broadcast-tower', icon: 'fas fa-broadcast-tower',
bg: 'var(--bg)', bg: 'var(--bg)',
},
header: {
title: this.$ts.announcements,
icon: 'fas fa-broadcast-tower',
bg: 'var(--bg)',
actions: [{ actions: [{
asFullButton: true, asFullButton: true,
icon: 'fas fa-plus', icon: 'fas fa-plus',

View file

@ -1,7 +1,5 @@
<template> <template>
<div class="ogwlenmc"> <div class="ogwlenmc">
<MkHeader :info="header"/>
<div class="local" v-if="tab === 'local'"> <div class="local" v-if="tab === 'local'">
<MkInput v-model="query" :debounce="true" type="search" style="margin: var(--margin);"> <MkInput v-model="query" :debounce="true" type="search" style="margin: var(--margin);">
<template #prefix><i class="fas fa-search"></i></template> <template #prefix><i class="fas fa-search"></i></template>
@ -71,12 +69,7 @@ export default defineComponent({
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.customEmojis,
icon: 'fas fa-laugh',
bg: 'var(--bg)',
},
header: computed(() => ({
title: this.$ts.customEmojis, title: this.$ts.customEmojis,
icon: 'fas fa-laugh', icon: 'fas fa-laugh',
bg: 'var(--bg)', bg: 'var(--bg)',

View file

@ -3,17 +3,24 @@
<div class="nav" v-if="!narrow || page == null"> <div class="nav" v-if="!narrow || page == null">
<MkHeader :info="header"></MkHeader> <MkHeader :info="header"></MkHeader>
<div class="lxpfedzu"> <MkSpacer :content-max="700">
<img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> <div class="lxpfedzu">
</div> <div class="banner">
<img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/>
</div>
<MkInfo v-if="noMaintainerInformation" warn class="info">{{ $ts.noMaintainerInformationWarning }} <MkA to="/admin/settings" class="_link">{{ $ts.configure }}</MkA></MkInfo> <MkInfo v-if="noMaintainerInformation" warn class="info">{{ $ts.noMaintainerInformationWarning }} <MkA to="/admin/settings" class="_link">{{ $ts.configure }}</MkA></MkInfo>
<MkInfo v-if="noBotProtection" warn class="info">{{ $ts.noBotProtectionWarning }} <MkA to="/admin/bot-protection" class="_link">{{ $ts.configure }}</MkA></MkInfo> <MkInfo v-if="noBotProtection" warn class="info">{{ $ts.noBotProtectionWarning }} <MkA to="/admin/bot-protection" class="_link">{{ $ts.configure }}</MkA></MkInfo>
<MkSuperMenu :def="menuDef" :grid="page == null"></MkSuperMenu> <MkSuperMenu :def="menuDef" :grid="page == null"></MkSuperMenu>
</div>
</MkSpacer>
</div> </div>
<div class="main"> <div class="main">
<component :is="component" :key="page" @info="onInfo" v-bind="pageProps"/> <MkStickyContainer>
<template #header><MkHeader v-if="childInfo && !childInfo.hideHeader" :info="childInfo"/></template>
<component :is="component" :key="page" @info="onInfo" v-bind="pageProps"/>
</MkStickyContainer>
</div> </div>
</div> </div>
</template> </template>
@ -41,6 +48,10 @@ export default defineComponent({
MkInfo, MkInfo,
}, },
provide: {
shouldOmitHeaderTitle: false,
},
props: { props: {
initialPage: { initialPage: {
type: String, type: String,
@ -50,17 +61,19 @@ export default defineComponent({
setup(props, context) { setup(props, context) {
const indexInfo = { const indexInfo = {
title: i18n.locale.instance, title: i18n.locale.controlPanel,
icon: 'fas fa-cog', icon: 'fas fa-cog',
bg: 'var(--bg)', bg: 'var(--bg)',
hideHeader: true,
}; };
const INFO = ref(indexInfo); const INFO = ref(indexInfo);
const childInfo = ref(null);
const page = ref(props.initialPage); const page = ref(props.initialPage);
const narrow = ref(false); const narrow = ref(false);
const view = ref(null); const view = ref(null);
const el = ref(null); const el = ref(null);
const onInfo = (viewInfo) => { const onInfo = (viewInfo) => {
INFO.value = viewInfo; childInfo.value = viewInfo;
}; };
const pageProps = ref({}); const pageProps = ref({});
@ -306,7 +319,7 @@ export default defineComponent({
[symbols.PAGE_INFO]: INFO, [symbols.PAGE_INFO]: INFO,
menuDef, menuDef,
header: { header: {
title: i18n.locale.controllPanel, title: i18n.locale.controlPanel,
}, },
noMaintainerInformation, noMaintainerInformation,
noBotProtection, noBotProtection,
@ -315,6 +328,7 @@ export default defineComponent({
view, view,
el, el,
onInfo, onInfo,
childInfo,
pageProps, pageProps,
component, component,
invite, invite,
@ -343,25 +357,26 @@ export default defineComponent({
> .main { > .main {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
--baseContentWidth: 100%;
} }
} }
> .nav { > .nav {
> .info { .lxpfedzu {
margin: 16px; > .info {
margin: 16px 0;
}
> .banner {
margin: 16px;
> .icon {
display: block;
margin: auto;
height: 42px;
border-radius: 8px;
}
}
} }
} }
} }
.lxpfedzu {
margin: 16px;
> .icon {
display: block;
margin: auto;
height: 42px;
border-radius: 8px;
}
}
</style> </style>

View file

@ -1,71 +1,67 @@
<template> <template>
<div> <div class="edbbcaef" v-size="{ max: [740] }">
<MkHeader :info="header"/> <div v-if="stats" class="cfcdecdf" style="margin: var(--margin)">
<div class="number _panel">
<div class="edbbcaef" v-size="{ max: [880] }"> <div class="label">Users</div>
<div v-if="stats" class="cfcdecdf" style="margin: var(--margin)"> <div class="value _monospace">
<div class="number _panel"> {{ number(stats.originalUsersCount) }}
<div class="label">Users</div> <MkNumberDiff v-if="usersComparedToThePrevDay != null" class="diff" :value="usersComparedToThePrevDay" v-tooltip="$ts.dayOverDayChanges"><template #before>(</template><template #after>)</template></MkNumberDiff>
<div class="value _monospace">
{{ number(stats.originalUsersCount) }}
<MkNumberDiff v-if="usersComparedToThePrevDay != null" class="diff" :value="usersComparedToThePrevDay" v-tooltip="$ts.dayOverDayChanges"><template #before>(</template><template #after>)</template></MkNumberDiff>
</div>
</div>
<div class="number _panel">
<div class="label">Notes</div>
<div class="value _monospace">
{{ number(stats.originalNotesCount) }}
<MkNumberDiff v-if="notesComparedToThePrevDay != null" class="diff" :value="notesComparedToThePrevDay" v-tooltip="$ts.dayOverDayChanges"><template #before>(</template><template #after>)</template></MkNumberDiff>
</div>
</div> </div>
</div> </div>
<div class="number _panel">
<MkContainer :foldable="true" class="charts"> <div class="label">Notes</div>
<template #header><i class="fas fa-chart-bar"></i>{{ $ts.charts }}</template> <div class="value _monospace">
<div style="padding-top: 12px;"> {{ number(stats.originalNotesCount) }}
<MkInstanceStats :chart-limit="500" :detailed="true"/> <MkNumberDiff v-if="notesComparedToThePrevDay != null" class="diff" :value="notesComparedToThePrevDay" v-tooltip="$ts.dayOverDayChanges"><template #before>(</template><template #after>)</template></MkNumberDiff>
</div> </div>
</MkContainer>
<div class="queue">
<MkContainer :foldable="true" :thin="true" class="deliver">
<template #header>Queue: deliver</template>
<MkQueueChart :connection="queueStatsConnection" domain="deliver"/>
</MkContainer>
<MkContainer :foldable="true" :thin="true" class="inbox">
<template #header>Queue: inbox</template>
<MkQueueChart :connection="queueStatsConnection" domain="inbox"/>
</MkContainer>
</div> </div>
<!--<XMetrics/>-->
<MkFolder style="margin: var(--margin)">
<template #header><i class="fas fa-info-circle"></i> {{ $ts.info }}</template>
<div class="cfcdecdf">
<div class="number _panel">
<div class="label">Misskey</div>
<div class="value _monospace">{{ version }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">Node.js</div>
<div class="value _monospace">{{ serverInfo.node }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">PostgreSQL</div>
<div class="value _monospace">{{ serverInfo.psql }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">Redis</div>
<div class="value _monospace">{{ serverInfo.redis }}</div>
</div>
<div class="number _panel">
<div class="label">Vue</div>
<div class="value _monospace">{{ vueVersion }}</div>
</div>
</div>
</MkFolder>
</div> </div>
<MkContainer :foldable="true" class="charts">
<template #header><i class="fas fa-chart-bar"></i>{{ $ts.charts }}</template>
<div style="padding-top: 12px;">
<MkInstanceStats :chart-limit="500" :detailed="true"/>
</div>
</MkContainer>
<div class="queue">
<MkContainer :foldable="true" :thin="true" class="deliver">
<template #header>Queue: deliver</template>
<MkQueueChart :connection="queueStatsConnection" domain="deliver"/>
</MkContainer>
<MkContainer :foldable="true" :thin="true" class="inbox">
<template #header>Queue: inbox</template>
<MkQueueChart :connection="queueStatsConnection" domain="inbox"/>
</MkContainer>
</div>
<!--<XMetrics/>-->
<MkFolder style="margin: var(--margin)">
<template #header><i class="fas fa-info-circle"></i> {{ $ts.info }}</template>
<div class="cfcdecdf">
<div class="number _panel">
<div class="label">Misskey</div>
<div class="value _monospace">{{ version }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">Node.js</div>
<div class="value _monospace">{{ serverInfo.node }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">PostgreSQL</div>
<div class="value _monospace">{{ serverInfo.psql }}</div>
</div>
<div class="number _panel" v-if="serverInfo">
<div class="label">Redis</div>
<div class="value _monospace">{{ serverInfo.redis }}</div>
</div>
<div class="number _panel">
<div class="label">Vue</div>
<div class="value _monospace">{{ vueVersion }}</div>
</div>
</div>
</MkFolder>
</div> </div>
</template> </template>
@ -107,10 +103,6 @@ export default defineComponent({
icon: 'fas fa-tachometer-alt', icon: 'fas fa-tachometer-alt',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.dashboard,
icon: 'fas fa-tachometer-alt',
},
version, version,
vueVersion, vueVersion,
url, url,
@ -225,12 +217,14 @@ export default defineComponent({
} }
} }
&.max-width_800px { &.max-width_740px {
> .queue { > .queue {
display: block; display: block;
> .deliver, > .deliver,
> .inbox { > .inbox {
width: 100%;
&:not(:first-child) { &:not(:first-child) {
margin-top: var(--margin); margin-top: var(--margin);
margin-left: 0; margin-left: 0;

View file

@ -1,7 +1,5 @@
<template> <template>
<div class="lknzcolw"> <div class="lknzcolw">
<MkHeader :info="header"/>
<div class="users"> <div class="users">
<div class="inputs"> <div class="inputs">
<MkSelect v-model="sort" style="flex: 1;"> <MkSelect v-model="sort" style="flex: 1;">
@ -90,11 +88,6 @@ export default defineComponent({
title: this.$ts.users, title: this.$ts.users,
icon: 'fas fa-users', icon: 'fas fa-users',
bg: 'var(--bg)', bg: 'var(--bg)',
},
header: {
title: this.$ts.users,
icon: 'fas fa-users',
bg: 'var(--bg)',
actions: [{ actions: [{
icon: 'fas fa-search', icon: 'fas fa-search',
text: this.$ts.search, text: this.$ts.search,
@ -109,7 +102,7 @@ export default defineComponent({
icon: 'fas fa-search', icon: 'fas fa-search',
text: this.$ts.lookup, text: this.$ts.lookup,
handler: this.lookupUser handler: this.lookupUser
}] }],
}, },
sort: '+createdAt', sort: '+createdAt',
state: 'all', state: 'all',

View file

@ -1,21 +1,18 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <MkPagination :pagination="pagination" #default="{items}" class="ruryvtyk _content">
<div class="_section"> <section class="_card announcement" v-for="(announcement, i) in items" :key="announcement.id">
<MkPagination :pagination="pagination" #default="{items}" class="ruryvtyk _content"> <div class="_title"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
<section class="_card announcement _gap" v-for="(announcement, i) in items" :key="announcement.id"> <div class="_content">
<div class="_title"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div> <Mfm :text="announcement.text"/>
<div class="_content"> <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
<Mfm :text="announcement.text"/> </div>
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/> <div class="_footer" v-if="$i && !announcement.isRead">
</div> <MkButton @click="read(items, announcement, i)" primary><i class="fas fa-check"></i> {{ $ts.gotIt }}</MkButton>
<div class="_footer" v-if="$i && !announcement.isRead"> </div>
<MkButton @click="read(items, announcement, i)" primary><i class="fas fa-check"></i> {{ $ts.gotIt }}</MkButton> </section>
</div> </MkPagination>
</section> </MkSpacer>
</MkPagination>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -38,11 +35,6 @@ export default defineComponent({
icon: 'fas fa-broadcast-tower', icon: 'fas fa-broadcast-tower',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.announcements,
icon: 'fas fa-broadcast-tower',
bg: 'var(--bg)',
},
pagination: { pagination: {
endpoint: 'announcements', endpoint: 'announcements',
limit: 10, limit: 10,
@ -66,6 +58,10 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.ruryvtyk { .ruryvtyk {
> .announcement { > .announcement {
&:not(:last-child) {
margin-bottom: var(--margin);
}
> ._content { > ._content {
> img { > img {
display: block; display: block;

View file

@ -1,9 +1,6 @@
<template> <template>
<div> <div :class="$style.root">
<MkHeader :info="header"/> <XCategory v-if="tab === 'category'"/>
<div :class="$style.root">
<XCategory v-if="tab === 'category'"/>
</div>
</div> </div>
</template> </template>
@ -25,11 +22,6 @@ export default defineComponent({
icon: 'fas fa-laugh', icon: 'fas fa-laugh',
bg: 'var(--bg)', bg: 'var(--bg)',
})), })),
header: computed(() => ({
title: this.$ts.customEmojis,
icon: 'fas fa-laugh',
bg: 'var(--bg)',
})),
tab: 'category', tab: 'category',
} }
}, },

View file

@ -1,7 +1,5 @@
<template> <template>
<div> <div>
<MkHeader :info="header"/>
<MkSpacer :content-max="1200"> <MkSpacer :content-max="1200">
<div class="lznhrdub"> <div class="lznhrdub">
<div v-if="tab === 'local'"> <div v-if="tab === 'local'">
@ -110,13 +108,7 @@ export default defineComponent({
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.explore,
icon: 'fas fa-hashtag',
bg: 'var(--bg)',
},
tab: 'local',
header: computed(() => ({
title: this.$ts.explore, title: this.$ts.explore,
icon: 'fas fa-hashtag', icon: 'fas fa-hashtag',
bg: 'var(--bg)', bg: 'var(--bg)',
@ -134,6 +126,7 @@ export default defineComponent({
onClick: () => { this.tab = 'search'; }, onClick: () => { this.tab = 'search'; },
},] },]
})), })),
tab: 'local',
pinnedUsers: { endpoint: 'pinned-users' }, pinnedUsers: { endpoint: 'pinned-users' },
popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: {
state: 'alive', state: 'alive',

View file

@ -1,10 +1,7 @@
<template> <template>
<div> <div class="jmelgwjh">
<MkHeader :info="header"/> <div class="body">
<div class="jmelgwjh"> <XNotes class="notes" :pagination="pagination" :detail="true" :prop="'note'" @before="before()" @after="after()"/>
<div class="body">
<XNotes class="notes" :pagination="pagination" :detail="true" :prop="'note'" @before="before()" @after="after()"/>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -28,11 +25,6 @@ export default defineComponent({
icon: 'fas fa-star', icon: 'fas fa-star',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.favorites,
icon: 'fas fa-star',
bg: 'var(--bg)',
},
pagination: { pagination: {
endpoint: 'i/favorites', endpoint: 'i/favorites',
limit: 10, limit: 10,

View file

@ -1,10 +1,7 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <XNotes ref="notes" :pagination="pagination" @before="before" @after="after"/>
<div class="_section"> </MkSpacer>
<XNotes class="_content" ref="notes" :pagination="pagination" @before="before" @after="after"/>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -25,11 +22,6 @@ export default defineComponent({
icon: 'fas fa-fire-alt', icon: 'fas fa-fire-alt',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.featured,
icon: 'fas fa-fire-alt',
bg: 'var(--bg)',
},
pagination: { pagination: {
endpoint: 'notes/featured', endpoint: 'notes/featured',
limit: 10, limit: 10,

View file

@ -1,98 +1,95 @@
<template> <template>
<div> <div class="taeiyria">
<MkHeader :info="header"/> <div class="query">
<div class="taeiyria"> <MkInput v-model="host" :debounce="true" class="">
<div class="query"> <template #prefix><i class="fas fa-search"></i></template>
<MkInput v-model="host" :debounce="true" class=""> <template #label>{{ $ts.host }}</template>
<template #prefix><i class="fas fa-search"></i></template> </MkInput>
<template #label>{{ $ts.host }}</template> <div class="_inputSplit">
</MkInput> <MkSelect v-model="state">
<div class="_inputSplit"> <template #label>{{ $ts.state }}</template>
<MkSelect v-model="state"> <option value="all">{{ $ts.all }}</option>
<template #label>{{ $ts.state }}</template> <option value="federating">{{ $ts.federating }}</option>
<option value="all">{{ $ts.all }}</option> <option value="subscribing">{{ $ts.subscribing }}</option>
<option value="federating">{{ $ts.federating }}</option> <option value="publishing">{{ $ts.publishing }}</option>
<option value="subscribing">{{ $ts.subscribing }}</option> <option value="suspended">{{ $ts.suspended }}</option>
<option value="publishing">{{ $ts.publishing }}</option> <option value="blocked">{{ $ts.blocked }}</option>
<option value="suspended">{{ $ts.suspended }}</option> <option value="notResponding">{{ $ts.notResponding }}</option>
<option value="blocked">{{ $ts.blocked }}</option> </MkSelect>
<option value="notResponding">{{ $ts.notResponding }}</option> <MkSelect v-model="sort">
</MkSelect> <template #label>{{ $ts.sort }}</template>
<MkSelect v-model="sort"> <option value="+pubSub">{{ $ts.pubSub }} ({{ $ts.descendingOrder }})</option>
<template #label>{{ $ts.sort }}</template> <option value="-pubSub">{{ $ts.pubSub }} ({{ $ts.ascendingOrder }})</option>
<option value="+pubSub">{{ $ts.pubSub }} ({{ $ts.descendingOrder }})</option> <option value="+notes">{{ $ts.notes }} ({{ $ts.descendingOrder }})</option>
<option value="-pubSub">{{ $ts.pubSub }} ({{ $ts.ascendingOrder }})</option> <option value="-notes">{{ $ts.notes }} ({{ $ts.ascendingOrder }})</option>
<option value="+notes">{{ $ts.notes }} ({{ $ts.descendingOrder }})</option> <option value="+users">{{ $ts.users }} ({{ $ts.descendingOrder }})</option>
<option value="-notes">{{ $ts.notes }} ({{ $ts.ascendingOrder }})</option> <option value="-users">{{ $ts.users }} ({{ $ts.ascendingOrder }})</option>
<option value="+users">{{ $ts.users }} ({{ $ts.descendingOrder }})</option> <option value="+following">{{ $ts.following }} ({{ $ts.descendingOrder }})</option>
<option value="-users">{{ $ts.users }} ({{ $ts.ascendingOrder }})</option> <option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option>
<option value="+following">{{ $ts.following }} ({{ $ts.descendingOrder }})</option> <option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option>
<option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option> <option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option>
<option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option> <option value="+caughtAt">{{ $ts.registeredAt }} ({{ $ts.descendingOrder }})</option>
<option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option> <option value="-caughtAt">{{ $ts.registeredAt }} ({{ $ts.ascendingOrder }})</option>
<option value="+caughtAt">{{ $ts.registeredAt }} ({{ $ts.descendingOrder }})</option> <option value="+lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.descendingOrder }})</option>
<option value="-caughtAt">{{ $ts.registeredAt }} ({{ $ts.ascendingOrder }})</option> <option value="-lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.ascendingOrder }})</option>
<option value="+lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.descendingOrder }})</option> <option value="+driveUsage">{{ $ts.driveUsage }} ({{ $ts.descendingOrder }})</option>
<option value="-lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.ascendingOrder }})</option> <option value="-driveUsage">{{ $ts.driveUsage }} ({{ $ts.ascendingOrder }})</option>
<option value="+driveUsage">{{ $ts.driveUsage }} ({{ $ts.descendingOrder }})</option> <option value="+driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.descendingOrder }})</option>
<option value="-driveUsage">{{ $ts.driveUsage }} ({{ $ts.ascendingOrder }})</option> <option value="-driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.ascendingOrder }})</option>
<option value="+driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.descendingOrder }})</option> </MkSelect>
<option value="-driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.ascendingOrder }})</option>
</MkSelect>
</div>
</div> </div>
<MkPagination :pagination="pagination" #default="{items}" ref="instances" :key="host + state">
<div class="dqokceoi">
<MkA class="instance" v-for="instance in items" :key="instance.id" :to="`/instance-info/${instance.host}`">
<div class="host"><img :src="instance.faviconUrl">{{ instance.host }}</div>
<div class="table">
<div class="cell">
<div class="key">{{ $ts.registeredAt }}</div>
<div class="value"><MkTime :time="instance.caughtAt"/></div>
</div>
<div class="cell">
<div class="key">{{ $ts.software }}</div>
<div class="value">{{ instance.softwareName || `(${$ts.unknown})` }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.version }}</div>
<div class="value">{{ instance.softwareVersion || `(${$ts.unknown})` }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.users }}</div>
<div class="value">{{ instance.usersCount }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.notes }}</div>
<div class="value">{{ instance.notesCount }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.sent }}</div>
<div class="value"><MkTime v-if="instance.latestRequestSentAt" :time="instance.latestRequestSentAt"/><span v-else>N/A</span></div>
</div>
<div class="cell">
<div class="key">{{ $ts.received }}</div>
<div class="value"><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></div>
</div>
</div>
<div class="footer">
<span class="status" :class="getStatus(instance)">{{ getStatus(instance) }}</span>
<span class="pubSub">
<span class="sub" v-if="instance.followersCount > 0"><i class="fas fa-caret-down icon"></i>Sub</span>
<span class="sub" v-else><i class="fas fa-caret-down icon"></i>-</span>
<span class="pub" v-if="instance.followingCount > 0"><i class="fas fa-caret-up icon"></i>Pub</span>
<span class="pub" v-else><i class="fas fa-caret-up icon"></i>-</span>
</span>
<span class="right">
<span class="latestStatus">{{ instance.latestStatus || '-' }}</span>
<span class="lastCommunicatedAt"><MkTime :time="instance.lastCommunicatedAt"/></span>
</span>
</div>
</MkA>
</div>
</MkPagination>
</div> </div>
<MkPagination :pagination="pagination" #default="{items}" ref="instances" :key="host + state">
<div class="dqokceoi">
<MkA class="instance" v-for="instance in items" :key="instance.id" :to="`/instance-info/${instance.host}`">
<div class="host"><img :src="instance.faviconUrl">{{ instance.host }}</div>
<div class="table">
<div class="cell">
<div class="key">{{ $ts.registeredAt }}</div>
<div class="value"><MkTime :time="instance.caughtAt"/></div>
</div>
<div class="cell">
<div class="key">{{ $ts.software }}</div>
<div class="value">{{ instance.softwareName || `(${$ts.unknown})` }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.version }}</div>
<div class="value">{{ instance.softwareVersion || `(${$ts.unknown})` }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.users }}</div>
<div class="value">{{ instance.usersCount }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.notes }}</div>
<div class="value">{{ instance.notesCount }}</div>
</div>
<div class="cell">
<div class="key">{{ $ts.sent }}</div>
<div class="value"><MkTime v-if="instance.latestRequestSentAt" :time="instance.latestRequestSentAt"/><span v-else>N/A</span></div>
</div>
<div class="cell">
<div class="key">{{ $ts.received }}</div>
<div class="value"><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></div>
</div>
</div>
<div class="footer">
<span class="status" :class="getStatus(instance)">{{ getStatus(instance) }}</span>
<span class="pubSub">
<span class="sub" v-if="instance.followersCount > 0"><i class="fas fa-caret-down icon"></i>Sub</span>
<span class="sub" v-else><i class="fas fa-caret-down icon"></i>-</span>
<span class="pub" v-if="instance.followingCount > 0"><i class="fas fa-caret-up icon"></i>Pub</span>
<span class="pub" v-else><i class="fas fa-caret-up icon"></i>-</span>
</span>
<span class="right">
<span class="latestStatus">{{ instance.latestStatus || '-' }}</span>
<span class="lastCommunicatedAt"><MkTime :time="instance.lastCommunicatedAt"/></span>
</span>
</div>
</MkA>
</div>
</MkPagination>
</div> </div>
</template> </template>
@ -122,11 +119,6 @@ export default defineComponent({
icon: 'fas fa-globe', icon: 'fas fa-globe',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.federation,
icon: 'fas fa-globe',
bg: 'var(--bg)',
},
host: '', host: '',
state: 'federating', state: 'federating',
sort: '+pubSub', sort: '+pubSub',

View file

@ -1,10 +1,7 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <XNotes :pagination="pagination" @before="before()" @after="after()"/>
<div class="_section"> </MkSpacer>
<XNotes class="_content" :pagination="pagination" @before="before()" @after="after()"/>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -25,11 +22,6 @@ export default defineComponent({
icon: 'fas fa-at', icon: 'fas fa-at',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.mentions,
icon: 'fas fa-at',
bg: 'var(--bg)',
},
pagination: { pagination: {
endpoint: 'notes/mentions', endpoint: 'notes/mentions',
limit: 10, limit: 10,

View file

@ -1,10 +1,7 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <XNotes :pagination="pagination" @before="before()" @after="after()"/>
<div> </MkSpacer>
<XNotes :pagination="pagination" @before="before()" @after="after()"/>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -25,11 +22,6 @@ export default defineComponent({
icon: 'fas fa-envelope', icon: 'fas fa-envelope',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.directNotes,
icon: 'fas fa-envelope',
bg: 'var(--bg)',
},
pagination: { pagination: {
endpoint: 'notes/mentions', endpoint: 'notes/mentions',
limit: 10, limit: 10,

View file

@ -1,8 +1,6 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <div class="yweeujhr" v-size="{ max: [400] }">
<div class="yweeujhr _root" v-size="{ max: [400] }">
<MkButton @click="start" primary class="start"><i class="fas fa-plus"></i> {{ $ts.startMessaging }}</MkButton> <MkButton @click="start" primary class="start"><i class="fas fa-plus"></i> {{ $ts.startMessaging }}</MkButton>
<div class="history" v-if="messages.length > 0"> <div class="history" v-if="messages.length > 0">
@ -37,7 +35,7 @@
</div> </div>
<MkLoading v-if="fetching"/> <MkLoading v-if="fetching"/>
</div> </div>
</div> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -60,11 +58,6 @@ export default defineComponent({
icon: 'fas fa-comments', icon: 'fas fa-comments',
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
header: {
title: this.$ts.messaging,
icon: 'fas fa-comments',
bg: 'var(--bg)',
},
fetching: true, fetching: true,
moreFetching: false, moreFetching: false,
messages: [], messages: [],
@ -177,7 +170,7 @@ export default defineComponent({
.yweeujhr { .yweeujhr {
> .start { > .start {
margin: var(--margin) auto var(--margin) auto; margin: 0 auto var(--margin) auto;
} }
> .history { > .history {

View file

@ -1,16 +1,13 @@
<template> <template>
<div> <div class="qkcjvfiv">
<MkHeader :info="header"/> <MkButton @click="create" primary class="add"><i class="fas fa-plus"></i> {{ $ts.createList }}</MkButton>
<div class="qkcjvfiv">
<MkButton @click="create" primary class="add"><i class="fas fa-plus"></i> {{ $ts.createList }}</MkButton>
<MkPagination :pagination="pagination" #default="{items}" class="lists _content" ref="list"> <MkPagination :pagination="pagination" #default="{items}" class="lists _content" ref="list">
<MkA v-for="list in items" :key="list.id" class="list _panel" :to="`/my/lists/${ list.id }`"> <MkA v-for="list in items" :key="list.id" class="list _panel" :to="`/my/lists/${ list.id }`">
<div class="name">{{ list.name }}</div> <div class="name">{{ list.name }}</div>
<MkAvatars :user-ids="list.userIds"/> <MkAvatars :user-ids="list.userIds"/>
</MkA> </MkA>
</MkPagination> </MkPagination>
</div>
</div> </div>
</template> </template>
@ -35,15 +32,10 @@ export default defineComponent({
title: this.$ts.manageLists, title: this.$ts.manageLists,
icon: 'fas fa-list-ul', icon: 'fas fa-list-ul',
bg: 'var(--bg)', bg: 'var(--bg)',
},
header: {
title: this.$ts.manageLists,
icon: 'fas fa-list-ul',
bg: 'var(--bg)',
action: { action: {
icon: 'fas fa-plus', icon: 'fas fa-plus',
handler: this.create handler: this.create
} },
}, },
pagination: { pagination: {
endpoint: 'users/lists/list', endpoint: 'users/lists/list',

View file

@ -1,37 +1,34 @@
<template> <template>
<div> <div class="mk-list-page">
<MkHeader v-if="header" :info="header"/> <transition name="zoom" mode="out-in">
<div class="mk-list-page"> <div v-if="list" class="_section">
<transition name="zoom" mode="out-in"> <div class="_content">
<div v-if="list" class="_section"> <MkButton inline @click="addUser()">{{ $ts.addUser }}</MkButton>
<div class="_content"> <MkButton inline @click="renameList()">{{ $ts.rename }}</MkButton>
<MkButton inline @click="addUser()">{{ $ts.addUser }}</MkButton> <MkButton inline @click="deleteList()">{{ $ts.delete }}</MkButton>
<MkButton inline @click="renameList()">{{ $ts.rename }}</MkButton>
<MkButton inline @click="deleteList()">{{ $ts.delete }}</MkButton>
</div>
</div> </div>
</transition> </div>
</transition>
<transition name="zoom" mode="out-in"> <transition name="zoom" mode="out-in">
<div v-if="list" class="_section members _gap"> <div v-if="list" class="_section members _gap">
<div class="_title">{{ $ts.members }}</div> <div class="_title">{{ $ts.members }}</div>
<div class="_content"> <div class="_content">
<div class="users"> <div class="users">
<div class="user _panel" v-for="user in users" :key="user.id"> <div class="user _panel" v-for="user in users" :key="user.id">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/> <MkAvatar :user="user" class="avatar" :show-indicator="true"/>
<div class="body"> <div class="body">
<MkUserName :user="user" class="name"/> <MkUserName :user="user" class="name"/>
<MkAcct :user="user" class="acct"/> <MkAcct :user="user" class="acct"/>
</div> </div>
<div class="action"> <div class="action">
<button class="_button" @click="removeUser(user)"><i class="fas fa-times"></i></button> <button class="_button" @click="removeUser(user)"><i class="fas fa-times"></i></button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</transition> </div>
</div> </transition>
</div> </div>
</template> </template>
@ -53,10 +50,6 @@ export default defineComponent({
title: this.list.name, title: this.list.name,
icon: 'fas fa-list-ul', icon: 'fas fa-list-ul',
} : null), } : null),
header: computed(() => this.list ? {
title: this.list.name,
icon: 'fas fa-list-ul',
} : null),
list: null, list: null,
users: [], users: [],
}; };

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="fcuexfpr"> <MkSpacer :content-max="800">
<div class="_root"> <div class="fcuexfpr">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<div v-if="note" class="note"> <div v-if="note" class="note">
<div class="_gap" v-if="showNext"> <div class="_gap" v-if="showNext">
@ -34,7 +34,7 @@
<MkLoading v-else/> <MkLoading v-else/>
</transition> </transition>
</div> </div>
</div> </MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -153,54 +153,52 @@ export default defineComponent({
.fcuexfpr { .fcuexfpr {
background: var(--bg); background: var(--bg);
> ._root { > .note {
> .note { > .main {
> .main { > .load {
> .load { min-width: 0;
min-width: 0; margin: 0 auto;
margin: 0 auto; border-radius: 999px;
border-radius: 999px;
&.next { &.next {
margin-bottom: var(--margin); margin-bottom: var(--margin);
}
&.prev {
margin-top: var(--margin);
}
} }
&.prev {
margin-top: var(--margin);
}
}
> .note {
> .note { > .note {
> .note { border-radius: var(--radius);
border-radius: var(--radius); background: var(--panel);
background: var(--panel); }
} }
> .clips {
> .title {
font-weight: bold;
padding: 12px;
} }
> .clips { > .item {
> .title { display: block;
font-weight: bold; padding: 16px;
padding: 12px;
> .description {
padding: 8px 0;
} }
> .item { > .user {
display: block; $height: 32px;
padding: 16px; padding-top: 16px;
border-top: solid 0.5px var(--divider);
line-height: $height;
> .description { > .avatar {
padding: 8px 0; width: $height;
} height: $height;
> .user {
$height: 32px;
padding-top: 16px;
border-top: solid 0.5px var(--divider);
line-height: $height;
> .avatar {
width: $height;
height: $height;
}
} }
} }
} }

View file

@ -1,12 +1,9 @@
<template> <template>
<div> <MkSpacer :content-max="800">
<MkHeader :info="header"/> <div class="clupoqwt">
<MkSpacer :content-max="800"> <XNotifications class="notifications" @before="before" @after="after" :include-types="includeTypes" :unread-only="tab === 'unread'"/>
<div class="clupoqwt"> </div>
<XNotifications class="notifications" @before="before" @after="after" :include-types="includeTypes" :unread-only="tab === 'unread'"/> </MkSpacer>
</div>
</MkSpacer>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -24,14 +21,7 @@ export default defineComponent({
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.notifications,
icon: 'fas fa-bell',
bg: 'var(--bg)',
},
tab: 'all',
includeTypes: null,
header: computed(() => ({
title: this.$ts.notifications, title: this.$ts.notifications,
icon: 'fas fa-bell', icon: 'fas fa-bell',
bg: 'var(--bg)', bg: 'var(--bg)',
@ -57,6 +47,8 @@ export default defineComponent({
onClick: () => { this.tab = 'unread'; }, onClick: () => { this.tab = 'unread'; },
},] },]
})), })),
tab: 'all',
includeTypes: null,
}; };
}, },

View file

@ -1,82 +1,78 @@
<template> <template>
<div> <div>
<MkHeader :info="header"/> <div class="jqqmcavi" style="margin: 16px;">
<MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="fas fa-external-link-square-alt"></i> {{ $ts._pages.viewPage }}</MkButton>
<MkButton inline @click="save" primary class="button" v-if="!readonly"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<MkButton inline @click="duplicate" class="button" v-if="pageId"><i class="fas fa-copy"></i> {{ $ts.duplicate }}</MkButton>
<MkButton inline @click="del" class="button" v-if="pageId && !readonly" danger><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
</div>
<div class="_root"> <div v-if="tab === 'settings'">
<div class="jqqmcavi" style="margin: 16px;"> <div style="padding: 16px;" class="_formRoot">
<MkButton v-if="pageId" class="button" inline link :to="`/@${ author.username }/pages/${ currentName }`"><i class="fas fa-external-link-square-alt"></i> {{ $ts._pages.viewPage }}</MkButton> <MkInput v-model="title" class="_formBlock">
<MkButton inline @click="save" primary class="button" v-if="!readonly"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> <template #label>{{ $ts._pages.title }}</template>
<MkButton inline @click="duplicate" class="button" v-if="pageId"><i class="fas fa-copy"></i> {{ $ts.duplicate }}</MkButton> </MkInput>
<MkButton inline @click="del" class="button" v-if="pageId && !readonly" danger><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
</div>
<div v-if="tab === 'settings'"> <MkInput v-model="summary" class="_formBlock">
<div style="padding: 16px;" class="_formRoot"> <template #label>{{ $ts._pages.summary }}</template>
<MkInput v-model="title" class="_formBlock"> </MkInput>
<template #label>{{ $ts._pages.title }}</template>
</MkInput>
<MkInput v-model="summary" class="_formBlock"> <MkInput v-model="name" class="_formBlock">
<template #label>{{ $ts._pages.summary }}</template> <template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
</MkInput> <template #label>{{ $ts._pages.url }}</template>
</MkInput>
<MkInput v-model="name" class="_formBlock"> <MkSwitch v-model="alignCenter" class="_formBlock">{{ $ts._pages.alignCenter }}</MkSwitch>
<template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
<template #label>{{ $ts._pages.url }}</template>
</MkInput>
<MkSwitch v-model="alignCenter" class="_formBlock">{{ $ts._pages.alignCenter }}</MkSwitch> <MkSelect v-model="font" class="_formBlock">
<template #label>{{ $ts._pages.font }}</template>
<option value="serif">{{ $ts._pages.fontSerif }}</option>
<option value="sans-serif">{{ $ts._pages.fontSansSerif }}</option>
</MkSelect>
<MkSelect v-model="font" class="_formBlock"> <MkSwitch v-model="hideTitleWhenPinned" class="_formBlock">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch>
<template #label>{{ $ts._pages.font }}</template>
<option value="serif">{{ $ts._pages.fontSerif }}</option>
<option value="sans-serif">{{ $ts._pages.fontSansSerif }}</option>
</MkSelect>
<MkSwitch v-model="hideTitleWhenPinned" class="_formBlock">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch> <div class="eyeCatch">
<MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="fas fa-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton>
<div class="eyeCatch"> <div v-else-if="eyeCatchingImage">
<MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="fas fa-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton> <img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/>
<div v-else-if="eyeCatchingImage"> <MkButton @click="removeEyeCatchingImage()" v-if="!readonly"><i class="fas fa-trash-alt"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton>
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/>
<MkButton @click="removeEyeCatchingImage()" v-if="!readonly"><i class="fas fa-trash-alt"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div v-else-if="tab === 'contents'"> <div v-else-if="tab === 'contents'">
<div style="padding: 16px;"> <div style="padding: 16px;">
<XBlocks class="content" v-model="content" :hpml="hpml"/> <XBlocks class="content" v-model="content" :hpml="hpml"/>
<MkButton @click="add()" v-if="!readonly"><i class="fas fa-plus"></i></MkButton> <MkButton @click="add()" v-if="!readonly"><i class="fas fa-plus"></i></MkButton>
</div>
</div> </div>
</div>
<div v-else-if="tab === 'variables'"> <div v-else-if="tab === 'variables'">
<div class="qmuvgica"> <div class="qmuvgica">
<XDraggable tag="div" class="variables" v-show="variables.length > 0" v-model="variables" item-key="name" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5"> <XDraggable tag="div" class="variables" v-show="variables.length > 0" v-model="variables" item-key="name" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5">
<template #item="{element}"> <template #item="{element}">
<XVariable <XVariable
:modelValue="element" :modelValue="element"
:removable="true" :removable="true"
@remove="() => removeVariable(element)" @remove="() => removeVariable(element)"
:hpml="hpml" :hpml="hpml"
:name="element.name" :name="element.name"
:title="element.name" :title="element.name"
:draggable="true" :draggable="true"
/> />
</template> </template>
</XDraggable> </XDraggable>
<MkButton @click="addVariable()" class="add" v-if="!readonly"><i class="fas fa-plus"></i></MkButton> <MkButton @click="addVariable()" class="add" v-if="!readonly"><i class="fas fa-plus"></i></MkButton>
</div>
</div> </div>
</div>
<div v-else-if="tab === 'script'"> <div v-else-if="tab === 'script'">
<div> <div>
<MkTextarea class="_code" v-model="script"/> <MkTextarea class="_code" v-model="script"/>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -131,21 +127,6 @@ export default defineComponent({
data() { data() {
return { return {
[symbols.PAGE_INFO]: computed(() => { [symbols.PAGE_INFO]: computed(() => {
let title = this.$ts._pages.newPage;
if (this.initPageId) {
title = this.$ts._pages.editPage;
}
else if (this.initPageName && this.initUser) {
title = this.$ts._pages.readPage;
}
return {
title: title,
icon: 'fas fa-pencil-alt',
bg: 'var(--bg)',
};
}),
tab: 'settings',
header: computed(() => {
let title = this.$ts._pages.newPage; let title = this.$ts._pages.newPage;
if (this.initPageId) { if (this.initPageId) {
title = this.$ts._pages.editPage; title = this.$ts._pages.editPage;
@ -177,9 +158,10 @@ export default defineComponent({
title: this.$ts.script, title: this.$ts.script,
icon: 'fas fa-code', icon: 'fas fa-code',
onClick: () => { this.tab = 'script'; }, onClick: () => { this.tab = 'script'; },
}] }],
}; };
}), }),
tab: 'settings',
author: this.$i, author: this.$i,
readonly: false, readonly: false,
page: null, page: null,

View file

@ -1,65 +1,61 @@
<template> <template>
<div> <div>
<MkHeader :info="header"/> <transition name="fade" mode="out-in">
<div v-if="page" class="xcukqgmh" :key="page.id" v-size="{ max: [450] }">
<div class="_root"> <div class="_block main">
<transition name="fade" mode="out-in"> <!--
<div v-if="page" class="xcukqgmh" :key="page.id" v-size="{ max: [450] }"> <div class="header">
<div class="_block main"> <h1>{{ page.title }}</h1>
<!-- </div>
<div class="header"> -->
<h1>{{ page.title }}</h1> <div class="banner">
<img :src="page.eyeCatchingImage.url" v-if="page.eyeCatchingImageId"/>
</div>
<div class="content">
<XPage :page="page"/>
</div>
<div class="actions">
<div class="like">
<MkButton class="button" @click="unlike()" v-if="page.isLiked" v-tooltip="$ts._pages.unlike" primary><i class="fas fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton>
<MkButton class="button" @click="like()" v-else v-tooltip="$ts._pages.like"><i class="far fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton>
</div> </div>
--> <div class="other">
<div class="banner"> <button class="_button" @click="shareWithNote" v-tooltip="$ts.shareWithNote" v-click-anime><i class="fas fa-retweet fa-fw"></i></button>
<img :src="page.eyeCatchingImage.url" v-if="page.eyeCatchingImageId"/> <button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
</div>
<div class="content">
<XPage :page="page"/>
</div>
<div class="actions">
<div class="like">
<MkButton class="button" @click="unlike()" v-if="page.isLiked" v-tooltip="$ts._pages.unlike" primary><i class="fas fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton>
<MkButton class="button" @click="like()" v-else v-tooltip="$ts._pages.like"><i class="far fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton>
</div>
<div class="other">
<button class="_button" @click="shareWithNote" v-tooltip="$ts.shareWithNote" v-click-anime><i class="fas fa-retweet fa-fw"></i></button>
<button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
</div>
</div>
<div class="user">
<MkAvatar :user="page.user" class="avatar"/>
<div class="name">
<MkUserName :user="page.user" style="display: block;"/>
<MkAcct :user="page.user"/>
</div>
<MkFollowButton v-if="!$i || $i.id != page.user.id" :user="page.user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
</div>
<div class="links">
<MkA :to="`/@${username}/pages/${pageName}/view-source`" class="link">{{ $ts._pages.viewSource }}</MkA>
<template v-if="$i && $i.id === page.userId">
<MkA :to="`/pages/edit/${page.id}`" class="link">{{ $ts._pages.editThisPage }}</MkA>
<button v-if="$i.pinnedPageId === page.id" @click="pin(false)" class="link _textButton">{{ $ts.unpin }}</button>
<button v-else @click="pin(true)" class="link _textButton">{{ $ts.pin }}</button>
</template>
</div> </div>
</div> </div>
<div class="footer"> <div class="user">
<div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div> <MkAvatar :user="page.user" class="avatar"/>
<div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div> <div class="name">
<MkUserName :user="page.user" style="display: block;"/>
<MkAcct :user="page.user"/>
</div>
<MkFollowButton v-if="!$i || $i.id != page.user.id" :user="page.user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
</div>
<div class="links">
<MkA :to="`/@${username}/pages/${pageName}/view-source`" class="link">{{ $ts._pages.viewSource }}</MkA>
<template v-if="$i && $i.id === page.userId">
<MkA :to="`/pages/edit/${page.id}`" class="link">{{ $ts._pages.editThisPage }}</MkA>
<button v-if="$i.pinnedPageId === page.id" @click="pin(false)" class="link _textButton">{{ $ts.unpin }}</button>
<button v-else @click="pin(true)" class="link _textButton">{{ $ts.pin }}</button>
</template>
</div> </div>
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
<MkContainer :max-height="300" :foldable="true" class="other">
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
<MkPagination :pagination="otherPostsPagination" #default="{items}">
<MkPagePreview v-for="page in items" :page="page" :key="page.id" class="_gap"/>
</MkPagination>
</MkContainer>
</div> </div>
<MkError v-else-if="error" @retry="fetch()"/> <div class="footer">
<MkLoading v-else/> <div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div>
</transition> <div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div>
</div> </div>
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
<MkContainer :max-height="300" :foldable="true" class="other">
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
<MkPagination :pagination="otherPostsPagination" #default="{items}">
<MkPagePreview v-for="page in items" :page="page" :key="page.id" class="_gap"/>
</MkPagination>
</MkContainer>
</div>
<MkError v-else-if="error" @retry="fetch()"/>
<MkLoading v-else/>
</transition>
</div> </div>
</template> </template>
@ -101,10 +97,6 @@ export default defineComponent({
[symbols.PAGE_INFO]: computed(() => this.page ? { [symbols.PAGE_INFO]: computed(() => this.page ? {
title: computed(() => this.page.title || this.page.name), title: computed(() => this.page.title || this.page.name),
avatar: this.page.user, avatar: this.page.user,
} : null),
header: computed(() => this.page ? {
title: computed(() => this.page.title || this.page.name),
avatar: this.page.user,
path: `/@${this.page.user.username}/pages/${this.page.name}`, path: `/@${this.page.user.username}/pages/${this.page.name}`,
share: { share: {
title: this.page.title || this.page.name, title: this.page.title || this.page.name,

View file

@ -1,37 +1,33 @@
<template> <template>
<div> <MkSpacer>
<MkHeader :info="header"/> <!-- TODO: MkHeaderに統合 -->
<MkTab v-model="tab" v-if="$i">
<option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._pages.featured }}</option>
<option value="my"><i class="fas fa-edit"></i> {{ $ts._pages.my }}</option>
<option value="liked"><i class="fas fa-heart"></i> {{ $ts._pages.liked }}</option>
</MkTab>
<MkSpacer> <div class="_section">
<!-- TODO: MkHeaderに統合 --> <div class="rknalgpo _content" v-if="tab === 'featured'">
<MkTab v-model="tab" v-if="$i"> <MkPagination :pagination="featuredPagesPagination" #default="{items}">
<option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._pages.featured }}</option> <MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
<option value="my"><i class="fas fa-edit"></i> {{ $ts._pages.my }}</option> </MkPagination>
<option value="liked"><i class="fas fa-heart"></i> {{ $ts._pages.liked }}</option>
</MkTab>
<div class="_section">
<div class="rknalgpo _content" v-if="tab === 'featured'">
<MkPagination :pagination="featuredPagesPagination" #default="{items}">
<MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
</MkPagination>
</div>
<div class="rknalgpo _content my" v-if="tab === 'my'">
<MkButton class="new" @click="create()"><i class="fas fa-plus"></i></MkButton>
<MkPagination :pagination="myPagesPagination" #default="{items}">
<MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
</MkPagination>
</div>
<div class="rknalgpo _content" v-if="tab === 'liked'">
<MkPagination :pagination="likedPagesPagination" #default="{items}">
<MkPagePreview v-for="like in items" class="ckltabjg" :page="like.page" :key="like.page.id"/>
</MkPagination>
</div>
</div> </div>
</MkSpacer>
</div> <div class="rknalgpo _content my" v-if="tab === 'my'">
<MkButton class="new" @click="create()"><i class="fas fa-plus"></i></MkButton>
<MkPagination :pagination="myPagesPagination" #default="{items}">
<MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/>
</MkPagination>
</div>
<div class="rknalgpo _content" v-if="tab === 'liked'">
<MkPagination :pagination="likedPagesPagination" #default="{items}">
<MkPagePreview v-for="like in items" class="ckltabjg" :page="like.page" :key="like.page.id"/>
</MkPagination>
</div>
</div>
</MkSpacer>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -52,11 +48,6 @@ export default defineComponent({
title: this.$ts.pages, title: this.$ts.pages,
icon: 'fas fa-sticky-note', icon: 'fas fa-sticky-note',
bg: 'var(--bg)', bg: 'var(--bg)',
},
header: {
title: this.$ts.pages,
icon: 'fas fa-sticky-note',
bg: 'var(--bg)',
actions: [{ actions: [{
icon: 'fas fa-plus', icon: 'fas fa-plus',
text: this.$ts.create, text: this.$ts.create,

View file

@ -1,10 +1,7 @@
<template> <template>
<div> <div class="_section">
<MkHeader :info="header"/> <div class="_content">
<div class="_section"> <XNotes ref="notes" :pagination="pagination" @before="before" @after="after"/>
<div class="_content">
<XNotes ref="notes" :pagination="pagination" @before="before" @after="after"/>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -26,10 +23,6 @@ export default defineComponent({
title: computed(() => this.$t('searchWith', { q: this.$route.query.q })), title: computed(() => this.$t('searchWith', { q: this.$route.query.q })),
icon: 'fas fa-search', icon: 'fas fa-search',
}, },
header: {
title: computed(() => this.$t('searchWith', { q: this.$route.query.q })),
icon: 'fas fa-search',
},
pagination: { pagination: {
endpoint: 'notes/search', endpoint: 'notes/search',
limit: 10, limit: 10,

View file

@ -35,7 +35,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import * as tinycolor from 'tinycolor2'; import * as tinycolor from 'tinycolor2';
import ApexCharts from 'apexcharts';
import FormButton from '@client/components/debobigego/button.vue'; import FormButton from '@client/components/debobigego/button.vue';
import FormGroup from '@client/components/debobigego/group.vue'; import FormGroup from '@client/components/debobigego/group.vue';
import FormKeyValueView from '@client/components/debobigego/key-value-view.vue'; import FormKeyValueView from '@client/components/debobigego/key-value-view.vue';
@ -44,6 +43,8 @@ import * as os from '@client/os';
import bytes from '@client/filters/bytes'; import bytes from '@client/filters/bytes';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
// TODO: render chart
export default defineComponent({ export default defineComponent({
components: { components: {
FormBase, FormBase,
@ -117,104 +118,6 @@ export default defineComponent({
}); });
}, },
renderChart() {
os.api('charts/user/drive', {
userId: this.$i.id,
span: 'day',
limit: 21
}).then(stats => {
const addition = [];
const deletion = [];
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
for (let i = 0; i < 21; i++) {
const x = new Date(y, m, d - i);
addition.push([
x,
stats.incSize[i]
]);
deletion.push([
x,
-stats.decSize[i]
]);
}
const chart = new ApexCharts(this.$refs.chart, {
chart: {
type: 'bar',
stacked: true,
height: 150,
toolbar: {
show: false
},
zoom: {
enabled: false
}
},
plotOptions: {
bar: {
columnWidth: '80%'
}
},
grid: {
clipMarkers: false,
borderColor: 'rgba(0, 0, 0, 0.1)',
xaxis: {
lines: {
show: true,
}
},
},
tooltip: {
shared: true,
intersect: false,
theme: this.$store.state.darkMode ? 'dark' : 'light',
},
dataLabels: {
enabled: false
},
legend: {
show: false
},
series: [{
name: 'Additions',
data: addition
}, {
name: 'Deletions',
data: deletion
}],
xaxis: {
type: 'datetime',
labels: {
style: {
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--fg')).toRgbString()
}
},
axisBorder: {
color: 'rgba(0, 0, 0, 0.1)'
},
axisTicks: {
color: 'rgba(0, 0, 0, 0.1)'
},
crosshairs: {
width: 1,
opacity: 1
}
},
yaxis: {
labels: {
formatter: v => bytes(v, 0),
style: {
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--fg')).toRgbString()
}
}
}
});
chart.render();
});
},
bytes bytes
} }
}); });

View file

@ -1,9 +1,13 @@
<template> <template>
<div class="vvcocwet" :class="{ wide: !narrow }" ref="el"> <div class="vvcocwet" :class="{ wide: !narrow }" ref="el">
<div class="nav" v-if="!narrow || page == null"> <div class="nav" v-if="!narrow || page == null">
<div class="title">{{ $ts.settings }}</div> <MkSpacer :content-max="700">
<MkInfo v-if="emailNotConfigured" warn class="info">{{ $ts.emailNotConfiguredWarning }} <MkA to="/settings/email" class="_link">{{ $ts.configure }}</MkA></MkInfo> <div class="baaadecd">
<MkSuperMenu :def="menuDef" :grid="page == null"></MkSuperMenu> <div class="title">{{ $ts.settings }}</div>
<MkInfo v-if="emailNotConfigured" warn class="info">{{ $ts.emailNotConfiguredWarning }} <MkA to="/settings/email" class="_link">{{ $ts.configure }}</MkA></MkInfo>
<MkSuperMenu :def="menuDef" :grid="page == null"></MkSuperMenu>
</div>
</MkSpacer>
</div> </div>
<div class="main"> <div class="main">
<component :is="component" :key="page" v-bind="pageProps"/> <component :is="component" :key="page" v-bind="pageProps"/>
@ -41,6 +45,7 @@ export default defineComponent({
title: i18n.locale.settings, title: i18n.locale.settings,
icon: 'fas fa-cog', icon: 'fas fa-cog',
bg: 'var(--bg)', bg: 'var(--bg)',
hideHeader: true,
}; };
const INFO = ref(indexInfo); const INFO = ref(indexInfo);
const page = ref(props.initialPage); const page = ref(props.initialPage);
@ -271,22 +276,24 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.vvcocwet { .vvcocwet {
> .nav { > .nav {
> .title { .baaadecd {
margin: 16px; > .title {
font-size: 1.5em; margin: 16px;
font-weight: bold; font-size: 1.5em;
} font-weight: bold;
}
> .info { > .info {
margin: 0 16px; margin: 0 16px;
} }
> .accounts { > .accounts {
> .avatar { > .avatar {
display: block; display: block;
width: 50px; width: 50px;
height: 50px; height: 50px;
margin: 8px auto 16px auto; margin: 8px auto 16px auto;
}
} }
} }
} }
@ -302,8 +309,10 @@ export default defineComponent({
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
> .title { .baaadecd {
margin: 24px; > .title {
margin: 24px 0;
}
} }
} }
@ -311,7 +320,6 @@ export default defineComponent({
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow: auto; overflow: auto;
--baseContentWidth: 100%;
} }
} }
} }

View file

@ -1,21 +1,18 @@
<template> <template>
<div v-hotkey.global="keymap"> <div class="cmuxhskf" v-size="{ min: [800] }" v-hotkey.global="keymap">
<MkHeader :info="header"/> <XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
<div class="cmuxhskf" v-size="{ min: [800] }"> <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div> <div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<div class="tl _block"> <div class="tl _block">
<XTimeline ref="tl" class="tl" <XTimeline ref="tl" class="tl"
:key="src" :key="src"
:src="src" :src="src"
:sound="true" :sound="true"
@before="before()" @before="before()"
@after="after()" @after="after()"
@queue="queueUpdated" @queue="queueUpdated"
/> />
</div>
</div> </div>
</div> </div>
</template> </template>
@ -46,11 +43,6 @@ export default defineComponent({
title: this.$ts.timeline, title: this.$ts.timeline,
icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home', icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home',
bg: 'var(--bg)', bg: 'var(--bg)',
})),
header: computed(() => ({
title: this.$ts.timeline,
icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home',
bg: 'var(--bg)',
actions: [{ actions: [{
icon: 'fas fa-list-ul', icon: 'fas fa-list-ul',
text: this.$ts.lists, text: this.$ts.lists,
@ -92,7 +84,7 @@ export default defineComponent({
icon: 'fas fa-globe', icon: 'fas fa-globe',
iconOnly: true, iconOnly: true,
onClick: () => { this.src = 'global'; this.saveSrc(); }, onClick: () => { this.src = 'global'; this.saveSrc(); },
}] }],
})), })),
}; };
}, },

View file

@ -3,20 +3,21 @@
<template #header><i class="fas fa-chart-bar" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template> <template #header><i class="fas fa-chart-bar" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template>
<div style="padding: 8px;"> <div style="padding: 8px;">
<div ref="chart"></div> <MkChart src="per-user-notes" :args="{ user, withoutAll: true }" span="day" :limit="limit" :stacked="true" :detailed="false" :aspect-ratio="6"/>
</div> </div>
</MkContainer> </MkContainer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import ApexCharts from 'apexcharts';
import * as os from '@client/os'; import * as os from '@client/os';
import MkContainer from '@client/components/ui/container.vue'; import MkContainer from '@client/components/ui/container.vue';
import MkChart from '@client/components/chart.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
MkContainer, MkContainer,
MkChart,
}, },
props: { props: {
user: { user: {
@ -29,96 +30,5 @@ export default defineComponent({
default: 40 default: 40
} }
}, },
data() {
return {
fetching: true,
data: [],
peak: null,
};
},
mounted() {
os.api('charts/user/notes', {
userId: this.user.id,
span: 'day',
limit: this.limit
}).then(stats => {
const normal = [];
const reply = [];
const renote = [];
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();
for (let i = 0; i < this.limit; i++) {
const x = new Date(y, m, d - i);
normal.push([
x,
stats.diffs.normal[i]
]);
reply.push([
x,
stats.diffs.reply[i]
]);
renote.push([
x,
stats.diffs.renote[i]
]);
}
const chart = new ApexCharts(this.$refs.chart, {
chart: {
type: 'bar',
stacked: true,
height: 100,
sparkline: {
enabled: true
},
},
plotOptions: {
bar: {
columnWidth: '40%'
}
},
dataLabels: {
enabled: false
},
grid: {
clipMarkers: false,
padding: {
top: 0,
right: 8,
bottom: 0,
left: 8
}
},
tooltip: {
shared: true,
intersect: false,
theme: this.$store.state.darkMode ? 'dark' : 'light',
},
series: [{
name: 'Normal',
data: normal
}, {
name: 'Reply',
data: reply
}, {
name: 'Renote',
data: renote
}],
xaxis: {
type: 'datetime',
crosshairs: {
width: 1,
opacity: 1
}
}
});
chart.render();
});
}
}); });
</script> </script>

View file

@ -65,11 +65,4 @@ export default defineComponent({
background: var(--bg); background: var(--bg);
} }
} }
._fitSide_ .yrzkoczt {
> .tab {
padding-left: var(--margin);
padding-right: var(--margin);
}
}
</style> </style>

View file

@ -1,87 +1,86 @@
<template> <template>
<div> <transition name="fade" mode="out-in">
<MkHeader :info="header"/> <div class="ftskorzw wide" v-if="user && narrow === false">
<transition name="fade" mode="out-in"> <MkRemoteCaution v-if="user.host != null" :href="user.url"/>
<div class="ftskorzw wide" v-if="user && narrow === false">
<MkRemoteCaution v-if="user.host != null" :href="user.url"/>
<div class="banner-container" :style="style"> <div class="banner-container" :style="style">
<div class="banner" ref="banner" :style="style"></div> <div class="banner" ref="banner" :style="style"></div>
</div>
<div class="contents">
<div class="side _forceContainerFull_">
<MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/>
<div class="name">
<MkUserName :user="user" :nowrap="false" class="name"/>
<MkAcct :user="user" :detail="true" class="acct"/>
</div>
<div class="followed" v-if="$i && $i.id != user.id && user.isFollowed"><span>{{ $ts.followsYou }}</span></div>
<div class="status">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
<b>{{ number(user.notesCount) }}</b>
<span>{{ $ts.notes }}</span>
</MkA>
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
<b>{{ number(user.followingCount) }}</b>
<span>{{ $ts.following }}</span>
</MkA>
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
<b>{{ number(user.followersCount) }}</b>
<span>{{ $ts.followers }}</span>
</MkA>
</div>
<div class="description">
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/>
<p v-else class="empty">{{ $ts.noAccountDescription }}</p>
</div>
<div class="fields system">
<dl class="field" v-if="user.location">
<dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt>
<dd class="value">{{ user.location }}</dd>
</dl>
<dl class="field" v-if="user.birthday">
<dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt>
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd>
</dl>
<dl class="field">
<dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt>
<dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd>
</dl>
</div>
<div class="fields" v-if="user.fields.length > 0">
<dl class="field" v-for="(field, i) in user.fields" :key="i">
<dt class="name">
<Mfm :text="field.name" :plain="true" :custom-emojis="user.emojis" :colored="false"/>
</dt>
<dd class="value">
<Mfm :text="field.value" :author="user" :i="$i" :custom-emojis="user.emojis" :colored="false"/>
</dd>
</dl>
</div>
<XActivity :user="user" :key="user.id" class="_gap"/>
<XPhotos :user="user" :key="user.id" class="_gap"/>
</div> </div>
<div class="contents"> <div class="main">
<div class="side _forceContainerFull_"> <div class="actions">
<MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/> <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
<div class="name"> <MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
<MkUserName :user="user" :nowrap="false" class="name"/>
<MkAcct :user="user" :detail="true" class="acct"/>
</div>
<div class="followed" v-if="$i && $i.id != user.id && user.isFollowed"><span>{{ $ts.followsYou }}</span></div>
<div class="status">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
<b>{{ number(user.notesCount) }}</b>
<span>{{ $ts.notes }}</span>
</MkA>
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
<b>{{ number(user.followingCount) }}</b>
<span>{{ $ts.following }}</span>
</MkA>
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
<b>{{ number(user.followersCount) }}</b>
<span>{{ $ts.followers }}</span>
</MkA>
</div>
<div class="description">
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/>
<p v-else class="empty">{{ $ts.noAccountDescription }}</p>
</div>
<div class="fields system">
<dl class="field" v-if="user.location">
<dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt>
<dd class="value">{{ user.location }}</dd>
</dl>
<dl class="field" v-if="user.birthday">
<dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt>
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd>
</dl>
<dl class="field">
<dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt>
<dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd>
</dl>
</div>
<div class="fields" v-if="user.fields.length > 0">
<dl class="field" v-for="(field, i) in user.fields" :key="i">
<dt class="name">
<Mfm :text="field.name" :plain="true" :custom-emojis="user.emojis" :colored="false"/>
</dt>
<dd class="value">
<Mfm :text="field.value" :author="user" :i="$i" :custom-emojis="user.emojis" :colored="false"/>
</dd>
</dl>
</div>
<XActivity :user="user" :key="user.id" class="_gap"/>
<XPhotos :user="user" :key="user.id" class="_gap"/>
</div> </div>
<div class="main"> <template v-if="page === 'index'">
<div class="actions"> <div v-if="user.pinnedNotes.length > 0" class="_gap">
<button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> <XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/>
<MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
</div> </div>
<template v-if="page === 'index'"> <div class="_gap">
<div v-if="user.pinnedNotes.length > 0" class="_gap"> <XUserTimeline :user="user"/>
<XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> </div>
</div> </template>
<div class="_gap"> <XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_gap"/>
<XUserTimeline :user="user"/> <XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_gap"/>
</div> <XClips v-else-if="page === 'clips'" :user="user" class="_gap"/>
</template> <XPages v-else-if="page === 'pages'" :user="user" class="_gap"/>
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_gap"/>
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_gap"/>
<XClips v-else-if="page === 'clips'" :user="user" class="_gap"/>
<XPages v-else-if="page === 'pages'" :user="user" class="_gap"/>
</div>
</div> </div>
</div> </div>
<div class="ftskorzw narrow _root" v-else-if="user && narrow === true" v-size="{ max: [500] }"> </div>
<MkSpacer v-else-if="user && narrow === true" :content-max="800">
<div class="ftskorzw narrow" v-size="{ max: [500] }">
<!-- TODO --> <!-- TODO -->
<!-- <div class="punished" v-if="user.isSuspended"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSuspended }}</div> --> <!-- <div class="punished" v-if="user.isSuspended"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSuspended }}</div> -->
<!-- <div class="punished" v-if="user.isSilenced"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSilenced }}</div> --> <!-- <div class="punished" v-if="user.isSilenced"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSilenced }}</div> -->
@ -173,7 +172,7 @@
</div> </div>
<MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo> <MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo>
<XPhotos :user="user" :key="user.id"/> <XPhotos :user="user" :key="user.id"/>
<XActivity :user="user" :key="user.id"/> <XActivity :user="user" :key="user.id" style="margin-top: var(--margin);"/>
</div> </div>
<div> <div>
<XUserTimeline :user="user"/> <XUserTimeline :user="user"/>
@ -187,10 +186,10 @@
<XGallery v-else-if="page === 'gallery'" :user="user" class="_gap"/> <XGallery v-else-if="page === 'gallery'" :user="user" class="_gap"/>
</div> </div>
</div> </div>
<MkError v-else-if="error" @retry="fetch()"/> </MkSpacer>
<MkLoading v-else/> <MkError v-else-if="error" @retry="fetch()"/>
</transition> <MkLoading v-else/>
</div> </transition>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -248,14 +247,6 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.user ? { [symbols.PAGE_INFO]: computed(() => this.user ? {
icon: 'fas fa-user', icon: 'fas fa-user',
title: this.user.name ? `${this.user.name} (@${this.user.username})` : `@${this.user.username}`,
path: `/@${this.user.username}`,
share: {
title: this.user.name,
},
bg: 'var(--bg)',
} : null),
header: computed(() => this.user ? {
title: this.user.name ? `${this.user.name} (@${this.user.username})` : `@${this.user.username}`, title: this.user.name ? `${this.user.name} (@${this.user.username})` : `@${this.user.username}`,
subtitle: `@${getAcct(this.user)}`, subtitle: `@${getAcct(this.user)}`,
userName: this.user, userName: this.user,
@ -290,7 +281,7 @@ export default defineComponent({
title: this.$ts.gallery, title: this.$ts.gallery,
icon: 'fas fa-icons', icon: 'fas fa-icons',
onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/gallery'); }, onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/gallery'); },
}] }],
} : null), } : null),
user: null, user: null,
error: null, error: null,
@ -833,16 +824,4 @@ export default defineComponent({
} }
} }
} }
._fitSide_ .ftskorzw.narrow {
> .profile {
> .warn {
margin: 0;
}
> .main {
margin-top: 0;
}
}
}
</style> </style>

View file

@ -144,7 +144,7 @@ export const defaultStore = markRaw(new Storage('base', {
}, },
useBlurEffect: { useBlurEffect: {
where: 'device', where: 'device',
default: false default: true
}, },
showFixedPostForm: { showFixedPostForm: {
where: 'device', where: 'device',

View file

@ -1,7 +1,6 @@
@charset "utf-8"; @charset "utf-8";
:root { :root {
--baseContentWidth: 760px;
--radius: 12px; --radius: 12px;
--marginFull: 16px; --marginFull: 16px;
--marginHalf: 10px; --marginHalf: 10px;
@ -350,21 +349,6 @@ hr {
} }
// TODO: 廃止 // TODO: 廃止
._root {
box-sizing: border-box;
margin: var(--root-margin, 32px) auto;
max-width: min(var(--baseContentWidth), calc(100% - (var(--root-margin, 32px) * 2)));
// 子marginが突き抜けるのを防ぐため
// https://stackoverflow.com/questions/1762539/margin-on-child-element-moves-parent-element
padding-top: 1px;
margin-top: calc(var(--root-margin, 32px) - 1px);
@media (max-width: 500px) {
--root-margin: 10px;
}
}
._monolithic_ { ._monolithic_ {
._section:not(:empty) { ._section:not(:empty) {
box-sizing: border-box; box-sizing: border-box;
@ -380,33 +364,6 @@ hr {
} }
} }
._fitSide_ {
--root-margin: 0px;
--baseContentWidth: 100%;
--panelBorder: none;
._block {
//border-top: solid 0.5px var(--divider);
//border-bottom: solid 0.5px var(--divider);
border-radius: 0;
box-shadow: none;
}
._isolated {
margin: var(--margin);
}
._block._isolated {
border-radius: var(--radius);
}
@media (max-width: 500px) {
._root {
--root-margin: 0px;
}
}
}
._narrow_ ._card { ._narrow_ ._card {
> ._title { > ._title {
padding: 16px; padding: 16px;

View file

@ -26,7 +26,7 @@
</template> </template>
<div class="divider"></div> <div class="divider"></div>
<MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" v-click-anime> <MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" v-click-anime>
<i class="fas fa-server fa-fw"></i><span class="text">{{ $ts.instance }}</span> <i class="fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
</MkA> </MkA>
<button class="item _button" @click="more" v-click-anime> <button class="item _button" @click="more" v-click-anime>
<i class="fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span> <i class="fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>

View file

@ -3,7 +3,7 @@
<header class="header" @contextmenu.prevent.stop="onContextmenu"> <header class="header" @contextmenu.prevent.stop="onContextmenu">
<MkHeader class="title" :info="pageInfo" :center="false"/> <MkHeader class="title" :info="pageInfo" :center="false"/>
</header> </header>
<component :is="component" v-bind="props" :ref="changePage" class="body _fitSide_"/> <component :is="component" v-bind="props" :ref="changePage" class="body"/>
</div> </div>
</template> </template>

View file

@ -13,8 +13,8 @@
</component> </component>
</template> </template>
<div class="divider"></div> <div class="divider"></div>
<MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime v-tooltip="$ts.instance"> <MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime v-tooltip="$ts.controlPanel">
<i class="fas fa-server fa-fw"></i> <i class="fas fa-door-open fa-fw"></i>
</MkA> </MkA>
<button class="item _button" @click="more" v-click-anime> <button class="item _button" @click="more" v-click-anime>
<i class="fas fa-ellipsis-h fa-fw"></i> <i class="fas fa-ellipsis-h fa-fw"></i>

View file

@ -21,7 +21,7 @@
</template> </template>
<div class="divider"></div> <div class="divider"></div>
<MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime> <MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/admin" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime>
<i class="fas fa-server fa-fw"></i><span class="text">{{ $ts.instance }}</span> <i class="fas fa-door-open fa-fw"></i><span class="text">{{ $ts.controlPanel }}</span>
</MkA> </MkA>
<button class="item _button" @click="more" v-click-anime> <button class="item _button" @click="more" v-click-anime>
<i class="fas fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span> <i class="fas fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span>

View file

@ -13,14 +13,17 @@
</template> </template>
<main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }"> <main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
<div class="content" :class="{ _fitSide_: !fullView }"> <div class="content">
<router-view v-slot="{ Component }"> <MkStickyContainer>
<transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition"> <template #header><MkHeader v-if="pageInfo && !pageInfo.hideHeader" :info="pageInfo"/></template>
<keep-alive :include="['timeline']"> <router-view v-slot="{ Component }">
<component :is="Component" :ref="changePage"/> <transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
</keep-alive> <keep-alive :include="['timeline']">
</transition> <component :is="Component" :ref="changePage"/>
</router-view> </keep-alive>
</transition>
</router-view>
</MkStickyContainer>
</div> </div>
</main> </main>
@ -61,7 +64,7 @@
import { defineComponent, defineAsyncComponent, markRaw } from 'vue'; import { defineComponent, defineAsyncComponent, markRaw } from 'vue';
import { instanceName } from '@client/config'; import { instanceName } from '@client/config';
import { StickySidebar } from '@client/scripts/sticky-sidebar'; import { StickySidebar } from '@client/scripts/sticky-sidebar';
import XSidebar from './default.sidebar.vue'; import XSidebar from './classic.sidebar.vue';
import XDrawerSidebar from '@client/ui/_common_/sidebar.vue'; import XDrawerSidebar from '@client/ui/_common_/sidebar.vue';
import XCommon from './_common_/common.vue'; import XCommon from './_common_/common.vue';
import * as os from '@client/os'; import * as os from '@client/os';
@ -76,8 +79,8 @@ export default defineComponent({
XCommon, XCommon,
XSidebar, XSidebar,
XDrawerSidebar, XDrawerSidebar,
XHeaderMenu: defineAsyncComponent(() => import('./default.header.vue')), XHeaderMenu: defineAsyncComponent(() => import('./classic.header.vue')),
XWidgets: defineAsyncComponent(() => import('./default.widgets.vue')), XWidgets: defineAsyncComponent(() => import('./classic.widgets.vue')),
}, },
provide() { provide() {

View file

@ -7,13 +7,16 @@
</template> </template>
</template> </template>
<router-view v-slot="{ Component }" class="_fitSide_"> <MkStickyContainer>
<transition> <template #header><MkHeader v-if="pageInfo && !pageInfo.hideHeader" :info="pageInfo"/></template>
<keep-alive :include="['timeline']"> <router-view v-slot="{ Component }">
<component :is="Component" :ref="changePage" @contextmenu.stop="onContextmenu"/> <transition>
</keep-alive> <keep-alive :include="['timeline']">
</transition> <component :is="Component" :ref="changePage" @contextmenu.stop="onContextmenu"/>
</router-view> </keep-alive>
</transition>
</router-view>
</MkStickyContainer>
</XColumn> </XColumn>
</template> </template>

View file

@ -5,13 +5,16 @@
<div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }"> <div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
<main ref="main"> <main ref="main">
<div class="content"> <div class="content">
<router-view v-slot="{ Component }"> <MkStickyContainer>
<transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition"> <template #header><MkHeader v-if="pageInfo && !pageInfo.hideHeader" :info="pageInfo"/></template>
<keep-alive :include="['timeline']"> <router-view v-slot="{ Component }">
<component :is="Component" :ref="changePage"/> <transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
</keep-alive> <keep-alive :include="['timeline']">
</transition> <component :is="Component" :ref="changePage"/>
</router-view> </keep-alive>
</transition>
</router-view>
</MkStickyContainer>
</div> </div>
<div class="spacer"></div> <div class="spacer"></div>
</main> </main>
@ -55,7 +58,7 @@ import { instanceName } from '@client/config';
import { StickySidebar } from '@client/scripts/sticky-sidebar'; import { StickySidebar } from '@client/scripts/sticky-sidebar';
import XSidebar from '@client/ui/_common_/sidebar.vue'; import XSidebar from '@client/ui/_common_/sidebar.vue';
import XCommon from './_common_/common.vue'; import XCommon from './_common_/common.vue';
import XSide from './default.side.vue'; import XSide from './classic.side.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import { menuDef } from '@client/menu'; import { menuDef } from '@client/menu';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';

View file

@ -3,7 +3,7 @@
<template #header><i class="fas fa-bell"></i>{{ $ts.notifications }}</template> <template #header><i class="fas fa-bell"></i>{{ $ts.notifications }}</template>
<template #func><button @click="configure()" class="_button"><i class="fas fa-cog"></i></button></template> <template #func><button @click="configure()" class="_button"><i class="fas fa-cog"></i></button></template>
<div class="_fitSide_"> <div>
<XNotifications :include-types="props.includingTypes"/> <XNotifications :include-types="props.includingTypes"/>
</div> </div>
</MkContainer> </MkContainer>

View file

@ -34,8 +34,8 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
ひとつのストリーム上で、同時に複数のチャンネルに接続することができます。 ひとつのストリーム上で、同時に複数のチャンネルに接続することができます。
### チャンネルに接続する ### 连接到频道
チャンネルに接続するには、次のようなデータをJSONでストリームに送信します: 要连接到频道请将JSON数据发送到流
```json ```json
{ {
@ -51,16 +51,16 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
``` ```
其中: 其中:
* `channel`には接続したいチャンネル名を設定します。チャンネルの種類については後述します * `channel`には接続したいチャンネル名を設定します。频道类型将在后面说明
* `id`にはそのチャンネルとやり取りするための任意のIDを設定します。ストリームでは様々なメッセージが流れるので、そのメッセージがどのチャンネルからのものなのか識別する必要があるからです。このIDは、UUIDや、乱数のようなもので構いません。 * `id`にはそのチャンネルとやり取りするための任意のIDを設定します。ストリームでは様々なメッセージが流れるので、そのメッセージがどのチャンネルからのものなのか識別する必要があるからです。このIDは、UUIDや、乱数のようなもので構いません。
* `params`はチャンネルに接続する際のパラメータです。チャンネルによって接続時に必要とされるパラメータは異なります。パラメータ不要のチャンネルに接続する際は、このプロパティは省略可能です。 * `params`はチャンネルに接続する際のパラメータです。チャンネルによって接続時に必要とされるパラメータは異なります。パラメータ不要のチャンネルに接続する際は、このプロパティは省略可能です。
<div class="info"> IDはチャンネルごとではなく「チャンネルの接続ごと」です。なぜなら、同じチャンネルに異なるパラメータで複数接続するケースもあるからです。</div> <div class="info"> IDはチャンネルごとではなく「チャンネルの接続ごと」です。なぜなら、同じチャンネルに異なるパラメータで複数接続するケースもあるからです。</div>
### チャンネルからのメッセージを受け取る ### 从频道接收消息
例えばタイムラインのチャンネルなら、新しい投稿があった時にメッセージを発します。そのメッセージを受け取ることで、タイムラインに新しい投稿がされたことをリアルタイムで知ることができます。 例えばタイムラインのチャンネルなら、新しい投稿があった時にメッセージを発します。そのメッセージを受け取ることで、タイムラインに新しい投稿がされたことをリアルタイムで知ることができます。
チャンネルがメッセージを発すると、次のようなデータがJSONでストリームに流れてきます: 当频道发送消息时以下数据将以JSON格式传输到流中
```json ```json
{ {
type: 'channel', type: 'channel',
@ -79,10 +79,10 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
* `type`にはメッセージの種類が設定されます。チャンネルによって、どのような種類のメッセージが流れてくるかは異なります。 * `type`にはメッセージの種類が設定されます。チャンネルによって、どのような種類のメッセージが流れてくるかは異なります。
* `body`にはメッセージの内容が設定されます。チャンネルによって、どのような内容のメッセージが流れてくるかは異なります。 * `body`にはメッセージの内容が設定されます。チャンネルによって、どのような内容のメッセージが流れてくるかは異なります。
### チャンネルに向けてメッセージを送信する ### 向频道发送消息
チャンネルによっては、メッセージを受け取るだけでなく、こちらから何かメッセージを送信し、何らかの操作を行える場合があります。 チャンネルによっては、メッセージを受け取るだけでなく、こちらから何かメッセージを送信し、何らかの操作を行える場合があります。
チャンネルにメッセージを送信するには、次のようなデータをJSONでストリームに送信します: 要将消息发送到频道请将JSON格式数据发送到流
```json ```json
{ {
type: 'channel', type: 'channel',
@ -101,7 +101,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
* `type`にはメッセージの種類を設定します。チャンネルによって、どのような種類のメッセージを受け付けるかは異なります。 * `type`にはメッセージの種類を設定します。チャンネルによって、どのような種類のメッセージを受け付けるかは異なります。
* `body`にはメッセージの内容を設定します。チャンネルによって、どのような内容のメッセージを受け付けるかは異なります。 * `body`にはメッセージの内容を設定します。チャンネルによって、どのような内容のメッセージを受け付けるかは異なります。
### チャンネルから切断する ### 断开频道连接
チャンネルから切断するには、次のようなデータをJSONでストリームに送信します: チャンネルから切断するには、次のようなデータをJSONでストリームに送信します:
```json ```json
@ -116,7 +116,7 @@ MisskeyのストリーミングAPIにはチャンネルという概念があり
其中: 其中:
* `id`には前述したそのチャンネルに接続する際に設定したIDを設定します。 * `id`には前述したそのチャンネルに接続する際に設定したIDを設定します。
## ストリームを経由してAPIリクエストする ## 通过流发送API请求
ストリームを経由してAPIリクエストすると、HTTPリクエストを発生させずにAPIを利用できます。そのため、コードを簡潔にできたり、パフォーマンスの向上を見込めるかもしれません。 ストリームを経由してAPIリクエストすると、HTTPリクエストを発生させずにAPIを利用できます。そのため、コードを簡潔にできたり、パフォーマンスの向上を見込めるかもしれません。
@ -207,7 +207,7 @@ Misskeyは投稿のキャプチャと呼ばれる仕組みを提供していま
* `body`内の`type`に、イベントの種類が設定されます。 * `body`内の`type`に、イベントの種類が設定されます。
* `body`内の`body`に、イベントの詳細が設定されます。 * `body`内の`body`に、イベントの詳細が設定されます。
#### イベントの種類 #### 事件类型
##### `reacted` ##### `reacted`
その投稿にリアクションがされた時に発生します。 その投稿にリアクションがされた時に発生します。
@ -233,7 +233,7 @@ Misskeyは投稿のキャプチャと呼ばれる仕組みを提供していま
##### `deleted` ##### `deleted`
その投稿が削除された時に発生します。 その投稿が削除された時に発生します。
* `deletedAt`に、削除日時が設定されます * `deletedAt`表示删除的日期和时间
例: 例:
```json ```json

View file

@ -1 +1 @@
export const twemojiSvgBase = 'https://twemoji.maxcdn.com/v/latest/svg'; export const twemojiSvgBase = '/twemoji';

View file

@ -155,6 +155,14 @@ export class UserRepository extends Repository<User> {
); );
} }
public getAvatarUrl(user: User): string {
if (user.avatarUrl) {
return user.avatarUrl;
} else {
return `${config.url}/random-avatar/${user.id}`;
}
}
public async pack( public async pack(
src: User['id'] | User, src: User['id'] | User,
me?: { id: User['id'] } | null | undefined, me?: { id: User['id'] } | null | undefined,
@ -186,7 +194,7 @@ export class UserRepository extends Repository<User> {
name: user.name, name: user.name,
username: user.username, username: user.username,
host: user.host, host: user.host,
avatarUrl: user.avatarUrl ? user.avatarUrl : config.url + '/avatar/' + user.id, avatarUrl: this.getAvatarUrl(user),
avatarBlurhash: user.avatarBlurhash, avatarBlurhash: user.avatarBlurhash,
avatarColor: null, // 後方互換性のため avatarColor: null, // 後方互換性のため
isAdmin: user.isAdmin || falsy, isAdmin: user.isAdmin || falsy,

View file

@ -26,6 +26,7 @@ import { networkChart } from '@/services/chart/index';
import { genAvatar } from '@/misc/gen-avatar'; import { genAvatar } from '@/misc/gen-avatar';
import { createTemp } from '@/misc/create-temp'; import { createTemp } from '@/misc/create-temp';
import { publishMainStream } from '@/services/stream'; import { publishMainStream } from '@/services/stream';
import { parseAcct } from '@/misc/acct';
export const serverLogger = new Logger('server', 'gray', false); export const serverLogger = new Logger('server', 'gray', false);
@ -68,7 +69,22 @@ router.use(activityPub.routes());
router.use(nodeinfo.routes()); router.use(nodeinfo.routes());
router.use(wellKnown.routes()); router.use(wellKnown.routes());
router.get('/avatar/:x', async ctx => { router.get('/avatar/@:acct', async ctx => {
const { username, host } = parseAcct(ctx.params.acct);
const user = await Users.findOne({
usernameLower: username.toLowerCase(),
host: host === config.host ? null : host,
isSuspended: false
});
if (user) {
ctx.redirect(Users.getAvatarUrl(user));
} else {
ctx.redirect('/static-assets/user-unknown.png');
}
});
router.get('/random-avatar/:x', async ctx => {
const [temp] = await createTemp(); const [temp] = await createTemp();
await genAvatar(ctx.params.x, fs.createWriteStream(temp)); await genAvatar(ctx.params.x, fs.createWriteStream(temp));
ctx.set('Content-Type', 'image/png'); ctx.set('Content-Type', 'image/png');

View file

@ -101,6 +101,22 @@ router.get('/apple-touch-icon.png', async ctx => {
}); });
}); });
router.get('/twemoji/(.*)', async ctx => {
const path = ctx.path.replace('/twemoji/', '');
if (!path.match(/^[0-9a-f-]+\.svg$/)) {
ctx.status = 404;
return;
}
ctx.set('Content-Security-Policy', `default-src 'none'; style-src 'unsafe-inline'`);
await send(ctx as any, path, {
root: `${_dirname}/../../../node_modules/@discordapp/twemoji/dist/svg/`,
maxage: ms('30 days'),
});
});
// ServiceWorker // ServiceWorker
router.get('/sw.js', async ctx => { router.get('/sw.js', async ctx => {
await send(ctx as any, `/sw.${config.version}.js`, { await send(ctx as any, `/sw.${config.version}.js`, {

View file

@ -91,6 +91,18 @@ describe('Fetch resource', () => {
assert.strictEqual(res.status, 200); assert.strictEqual(res.status, 200);
assert.strictEqual(res.type, 'image/png'); assert.strictEqual(res.type, 'image/png');
})); }));
it('GET twemoji svg', async(async () => {
const res = await simpleGet('/twemoji/2764.svg');
assert.strictEqual(res.status, 200);
assert.strictEqual(res.type, 'image/svg+xml');
}));
it('GET twemoji svg with hyphen', async(async () => {
const res = await simpleGet('/twemoji/2764-fe0f-200d-1f525.svg');
assert.strictEqual(res.status, 200);
assert.strictEqual(res.type, 'image/svg+xml');
}));
}); });
describe('/@:username', () => { describe('/@:username', () => {

387
yarn.lock
View file

@ -108,6 +108,16 @@
ky "^0.25.1" ky "^0.25.1"
ky-universal "^0.8.2" ky-universal "^0.8.2"
"@discordapp/twemoji@13.1.0":
version "13.1.0"
resolved "https://registry.yarnpkg.com/@discordapp/twemoji/-/twemoji-13.1.0.tgz#6b25f3958fa8fd68692248c87776bc737fd009a9"
integrity sha512-KEw/te+ylD2MHutzigafyptv0kdTU05Dbgxr9Y5J9IAQw8PbFz16nKtlPnJtA23BLp9fZQeNXzUmegkRi7fpDA==
dependencies:
fs-extra "^8.0.1"
jsonfile "^5.0.0"
twemoji-parser "13.1.0"
universalify "^0.1.2"
"@discoveryjs/json-ext@^0.5.0": "@discoveryjs/json-ext@^0.5.0":
version "0.5.2" version "0.5.2"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752"
@ -591,10 +601,10 @@
"@types/minimatch" "*" "@types/minimatch" "*"
"@types/node" "*" "@types/node" "*"
"@types/glob@7.1.4": "@types/glob@7.2.0":
version "7.1.4" version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
dependencies: dependencies:
"@types/minimatch" "*" "@types/minimatch" "*"
"@types/node" "*" "@types/node" "*"
@ -643,10 +653,10 @@
resolved "https://registry.yarnpkg.com/@types/is-url/-/is-url-1.2.30.tgz#85567e8bee4fee69202bc3448f9fb34b0d56c50a" resolved "https://registry.yarnpkg.com/@types/is-url/-/is-url-1.2.30.tgz#85567e8bee4fee69202bc3448f9fb34b0d56c50a"
integrity sha512-AnlNFwjzC8XLda5VjRl4ItSd8qp8pSNowvsut0WwQyBWHpOxjxRJm8iO6uETWqEyLdYdb9/1j+Qd9gQ4l5I4fw== integrity sha512-AnlNFwjzC8XLda5VjRl4ItSd8qp8pSNowvsut0WwQyBWHpOxjxRJm8iO6uETWqEyLdYdb9/1j+Qd9gQ4l5I4fw==
"@types/js-yaml@4.0.3": "@types/js-yaml@4.0.4":
version "4.0.3" version "4.0.4"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.3.tgz#9f33cd6fbf0d5ec575dc8c8fc69c7fec1b4eb200" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.4.tgz#cc38781257612581a1a0eb25f1709d2b06812fce"
integrity sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg== integrity sha512-AuHubXUmg0AzkXH0Mx6sIxeY/1C110mm/EkE/gB1sTRz3h2dao2W/63q42SlVST+lICxz5Oki2hzYA6+KnnieQ==
"@types/jsdom@16.2.13": "@types/jsdom@16.2.13":
version "16.2.13" version "16.2.13"
@ -790,10 +800,10 @@
dependencies: dependencies:
"@types/koa" "*" "@types/koa" "*"
"@types/koa__multer@2.0.3": "@types/koa__multer@2.0.4":
version "2.0.3" version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/koa__multer/-/koa__multer-2.0.3.tgz#8ad84281eaee82717c2b26cbb10b13b0c83cc536" resolved "https://registry.yarnpkg.com/@types/koa__multer/-/koa__multer-2.0.4.tgz#e0f0fd1800a46b51886bebab480a57100f2488b0"
integrity sha512-nxVUQIBYxjLSDScxe2YlHL8uJpuPtElEK15Q7D51hD6TwfFKe+7Ji/8Q8ewwzUlFWiuOnFbuXdy/HIjgQiTSHA== integrity sha512-WRkshXhE5rpYFUbbtAjyMhdOOSdbu1XX+2AQlRNM6AZtgxd0/WXMU4lrP7e9tk5HWVTWbx8DOOsVBmfHjSGJ4w==
dependencies: dependencies:
"@types/koa" "*" "@types/koa" "*"
@ -817,10 +827,10 @@
"@types/linkify-it" "*" "@types/linkify-it" "*"
"@types/mdurl" "*" "@types/mdurl" "*"
"@types/matter-js@0.17.5": "@types/matter-js@0.17.6":
version "0.17.5" version "0.17.6"
resolved "https://registry.yarnpkg.com/@types/matter-js/-/matter-js-0.17.5.tgz#b7ddd422cf5980f01531dfed60fc11682a1adbb9" resolved "https://registry.yarnpkg.com/@types/matter-js/-/matter-js-0.17.6.tgz#525bb33a7289105e1981ef51b987972fa9739011"
integrity sha512-s4j6htb+NZNQyo2jP96uZ93aPn0fCw0RP1YnEDmKkIKpOVxvNWdEEPPj3U+9xezp3eQChvWOwHcR815rEBWexA== integrity sha512-i6WLNuM7/89SLqO2aOyaUkom9tc3B/qo4ekh7BD99xQ8+wOVVZO0F4RzKNYZCaFwr+xp3pK3oIb6sSVjLpz+pA==
"@types/mdurl@*": "@types/mdurl@*":
version "1.0.2" version "1.0.2"
@ -855,10 +865,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50"
integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA== integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA==
"@types/node@16.10.3": "@types/node@16.11.4":
version "16.10.3" version "16.11.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.4.tgz#90771124822d6663814f7c1c9b45a6654d8fd964"
integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ== integrity sha512-TMgXmy0v2xWyuCSCJM6NCna2snndD8yvQF67J29ipdzMcsPa9u+o0tjF5+EQNdhcuZplYuouYqpc4zcd5I6amQ==
"@types/node@^14.11.8", "@types/node@^14.14.31", "@types/node@^14.14.41": "@types/node@^14.11.8", "@types/node@^14.14.31", "@types/node@^14.14.41":
version "14.17.9" version "14.17.9"
@ -894,10 +904,10 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==
"@types/parse5@6.0.1": "@types/parse5@6.0.2":
version "6.0.1" version "6.0.2"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.1.tgz#f8ae4fbcd2b9ba4ff934698e28778961f9cb22ca" resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.2.tgz#99f6b72d82e34cea03a4d8f2ed72114d909c1c61"
integrity sha512-ARATsLdrGPUnaBvxLhUlnltcMgn7pQG312S8ccdYlnyijabrX9RN/KN/iGj9Am96CoW8e/K9628BA7Bv4XHdrA== integrity sha512-+hQX+WyJAOne7Fh3zF5CxPemILIbuhNcqHHodzK9caYOLnC8pD5efmPleRnw0z++LfKUC/sVNMwk0Gap+B0baA==
"@types/parsimmon@1.10.6": "@types/parsimmon@1.10.6":
version "1.10.6" version "1.10.6"
@ -1060,10 +1070,10 @@
resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706" resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706"
integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ== integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==
"@types/tmp@0.2.1": "@types/tmp@0.2.2":
version "0.2.1" version "0.2.2"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.1.tgz#83ecf4ec22a8c218c71db25f316619fe5b986011" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.2.2.tgz#424537a3b91828cb26aaf697f21ae3cd1b69f7e7"
integrity sha512-7cTXwKP/HLOPVgjg+YhBdQ7bMiobGMuoBmrGmqwIWJv8elC6t1DfVc/mn4fD9UE1IjhwmhaQ5pGVXkmXbH0rhg== integrity sha512-MhSa0yylXtVMsyT8qFpHA1DLHj4DvQGH5ntxrhHSh8PxUVNi35Wk+P5hVgqbO2qZqOotqr9jaoPRL+iRjWYm/A==
"@types/tough-cookie@*": "@types/tough-cookie@*":
version "4.0.0" version "4.0.0"
@ -1182,48 +1192,48 @@
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71"
integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg== integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg==
"@typescript-eslint/parser@5.0.0": "@typescript-eslint/parser@5.1.0":
version "5.0.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.0.0.tgz#50d1be2e0def82d73e863cceba74aeeac9973592" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.1.0.tgz#6c7f837d210d2bc0a811e7ea742af414f4e00908"
integrity sha512-B6D5rmmQ14I1fdzs71eL3DAuvnPHTY/t7rQABrL9BLnx/H51Un8ox1xqYAchs0/V2trcoyxB1lMJLlrwrJCDgw== integrity sha512-vx1P+mhCtYw3+bRHmbalq/VKP2Y3gnzNgxGxfEWc6OFpuEL7iQdAeq11Ke3Rhy8NjgB+AHsIWEwni3e+Y7djKA==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.0.0" "@typescript-eslint/scope-manager" "5.1.0"
"@typescript-eslint/types" "5.0.0" "@typescript-eslint/types" "5.1.0"
"@typescript-eslint/typescript-estree" "5.0.0" "@typescript-eslint/typescript-estree" "5.1.0"
debug "^4.3.1" debug "^4.3.2"
"@typescript-eslint/scope-manager@5.0.0": "@typescript-eslint/scope-manager@5.1.0":
version "5.0.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.0.0.tgz#aea0fb0e2480c1169a02e89d9005ac3f2835713f" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.1.0.tgz#6f1f26ad66a8f71bbb33b635e74fec43f76b44df"
integrity sha512-5RFjdA/ain/MDUHYXdF173btOKncIrLuBmA9s6FJhzDrRAyVSA+70BHg0/MW6TE+UiKVyRtX91XpVS0gVNwVDQ== integrity sha512-yYlyVjvn5lvwCL37i4hPsa1s0ORsjkauhTqbb8MnpvUs7xykmcjGqwlNZ2Q5QpoqkJ1odlM2bqHqJwa28qV6Tw==
dependencies: dependencies:
"@typescript-eslint/types" "5.0.0" "@typescript-eslint/types" "5.1.0"
"@typescript-eslint/visitor-keys" "5.0.0" "@typescript-eslint/visitor-keys" "5.1.0"
"@typescript-eslint/types@5.0.0": "@typescript-eslint/types@5.1.0":
version "5.0.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.0.0.tgz#25d93f6d269b2d25fdc51a0407eb81ccba60eb0f" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.1.0.tgz#a8a75ddfc611660de6be17d3ad950302385607a9"
integrity sha512-dU/pKBUpehdEqYuvkojmlv0FtHuZnLXFBn16zsDmlFF3LXkOpkAQ2vrKc3BidIIve9EMH2zfTlxqw9XM0fFN5w== integrity sha512-sEwNINVxcB4ZgC6Fe6rUyMlvsB2jvVdgxjZEjQUQVlaSPMNamDOwO6/TB98kFt4sYYfNhdhTPBEQqNQZjMMswA==
"@typescript-eslint/typescript-estree@5.0.0": "@typescript-eslint/typescript-estree@5.1.0":
version "5.0.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.0.0.tgz#bc20f413c6e572c7309dbe5fa3be027984952af3" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.1.0.tgz#132aea34372df09decda961cb42457433aa6e83d"
integrity sha512-V/6w+PPQMhinWKSn+fCiX5jwvd1vRBm7AX7SJQXEGQtwtBvjMPjaU3YTQ1ik2UF1u96X7tsB96HMnulG3eLi9Q== integrity sha512-SSz+l9YrIIsW4s0ZqaEfnjl156XQ4VRmJsbA0ZE1XkXrD3cRpzuZSVCyqeCMR3EBjF27IisWakbBDGhGNIOvfQ==
dependencies: dependencies:
"@typescript-eslint/types" "5.0.0" "@typescript-eslint/types" "5.1.0"
"@typescript-eslint/visitor-keys" "5.0.0" "@typescript-eslint/visitor-keys" "5.1.0"
debug "^4.3.1" debug "^4.3.2"
globby "^11.0.3" globby "^11.0.4"
is-glob "^4.0.1" is-glob "^4.0.3"
semver "^7.3.5" semver "^7.3.5"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@5.0.0": "@typescript-eslint/visitor-keys@5.1.0":
version "5.0.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.0.0.tgz#b789f7cd105e59bee5c0983a353942a5a48f56df" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.1.0.tgz#e01a01b27eb173092705ae983aa1451bd1842630"
integrity sha512-yRyd2++o/IrJdyHuYMxyFyBhU762MRHQ/bAGQeTnN3pGikfh+nEmM61XTqaDH1XDp53afZ+waXrk0ZvenoZ6xw== integrity sha512-uqNXepKBg81JVwjuqAxYrXa1Ql/YDzM+8g/pS+TCPxba0wZttl8m5DkrasbfnmJGHs4lQ2jTbcZ5azGhI7kK+w==
dependencies: dependencies:
"@typescript-eslint/types" "5.0.0" "@typescript-eslint/types" "5.1.0"
eslint-visitor-keys "^3.0.0" eslint-visitor-keys "^3.0.0"
"@ungap/promise-all-settled@1.1.2": "@ungap/promise-all-settled@1.1.2":
@ -1809,18 +1819,6 @@ anymatch@~3.1.1:
normalize-path "^3.0.0" normalize-path "^3.0.0"
picomatch "^2.0.4" picomatch "^2.0.4"
apexcharts@3.28.3:
version "3.28.3"
resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.28.3.tgz#22a6d9b234c82f6c2e1dd4aebba05b7603e2b1d2"
integrity sha512-EhghB2P27/Gjhwct8sSS0V63mdpRMx/ikH34dwUTqZQnkAEyOS/RKDmYjXBNA7zsAKBE/pThOdoTya6ADyk6zQ==
dependencies:
svg.draggable.js "^2.2.2"
svg.easing.js "^2.0.0"
svg.filter.js "^2.0.2"
svg.pathmorphing.js "^0.1.3"
svg.resize.js "^1.4.3"
svg.select.js "^3.0.1"
app-root-path@^3.0.0: app-root-path@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad"
@ -2076,10 +2074,10 @@ autwh@0.1.0:
dependencies: dependencies:
oauth "0.9.15" oauth "0.9.15"
aws-sdk@2.1003.0: aws-sdk@2.1013.0:
version "2.1003.0" version "2.1013.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1003.0.tgz#f4ca218f466c524a90370b5604a3ad4cda4c0e08" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1013.0.tgz#85babc473b0bc90cc1160eb48baf616ddb86e346"
integrity sha512-UEZveI1m7+/YsomU2tVxLMmlo5g3sr3ue+QMJ2UwbrvHZ+O9hr9vVia1lD+L8fYTQenOff95NFc02h3pDE3iDA== integrity sha512-TXxkp/meAdofpC15goFpNuur7fvh/mcMRfHJoP1jYzTtD0wcoB4FK16GLcny0uDYgkQgZuiO9QYv3Rq5bhGCqQ==
dependencies: dependencies:
buffer "4.9.2" buffer "4.9.2"
events "1.1.1" events "1.1.1"
@ -2664,10 +2662,10 @@ character-parser@^2.2.0:
dependencies: dependencies:
is-regex "^1.0.3" is-regex "^1.0.3"
chart.js@3.5.1: chart.js@3.6.0:
version "3.5.1" version "3.6.0"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.5.1.tgz#73e24d23a4134a70ccdb5e79a917f156b6f3644a" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.6.0.tgz#a87fce8431d4e7c5523d721f487f53aada1e42fe"
integrity sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ== integrity sha512-iOzzDKePL+bj+ccIsVAgWQehCXv8xOKGbaU2fO/myivH736zcx535PGJzQGanvcSGVOqX6yuLZsN3ygcQ35UgQ==
chartjs-adapter-date-fns@2.0.0: chartjs-adapter-date-fns@2.0.0:
version "2.0.0" version "2.0.0"
@ -4249,10 +4247,10 @@ escodegen@^2.0.0:
optionalDependencies: optionalDependencies:
source-map "~0.6.1" source-map "~0.6.1"
eslint-plugin-vue@7.19.1: eslint-plugin-vue@7.20.0:
version "7.19.1" version "7.20.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.19.1.tgz#435fb2ce712842a9530b28eacb883680e8eaa4f3" resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.20.0.tgz#98c21885a6bfdf0713c3a92957a5afeaaeed9253"
integrity sha512-e2pD7nW2sTY04ThH+66BgToNwC4n6dqfNhKE+ypdJFtZgn3Zn+nP8ZEIFPG0PGqCKQ3qxy8dJk1bzUsuQd3ANA== integrity sha512-oVNDqzBC9h3GO+NTgWeLMhhGigy6/bQaQbHS+0z7C4YEu/qK/yxHvca/2PTZtGNPsCrHwOTgKMrwu02A9iPBmw==
dependencies: dependencies:
eslint-utils "^2.1.0" eslint-utils "^2.1.0"
natural-compare "^1.4.0" natural-compare "^1.4.0"
@ -4304,10 +4302,10 @@ eslint-visitor-keys@^3.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186"
integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q== integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==
eslint@8.0.1: eslint@8.1.0:
version "8.0.1" version "8.1.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.0.1.tgz#3610e7fe4a05c2154669515ca60835a76a19f700" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.1.0.tgz#00f1f7dbf4134f26588e6c9f2efe970760f64664"
integrity sha512-LsgcwZgQ72vZ+SMp4K6pAnk2yFDWL7Ti4pJaRvsZ0Hsw2h8ZjUIW38a9AFn2cZXdBMlScMFYYgsSp4ttFI/0bA== integrity sha512-JZvNneArGSUsluHWJ8g8MMs3CfIEzwaLx9KyH4tZ2i+R2/rPWzL8c0zg3rHdwYVpN/1sB9gqnjHwz9HoeJpGHw==
dependencies: dependencies:
"@eslint/eslintrc" "^1.0.3" "@eslint/eslintrc" "^1.0.3"
"@humanwhocodes/config-array" "^0.6.0" "@humanwhocodes/config-array" "^0.6.0"
@ -4916,6 +4914,15 @@ fs-constants@^1.0.0:
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^8.0.1:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@^9.1.0: fs-extra@^9.1.0:
version "9.1.0" version "9.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
@ -5153,7 +5160,7 @@ globals@^13.9.0:
dependencies: dependencies:
type-fest "^0.20.2" type-fest "^0.20.2"
globby@^11.0.2, globby@^11.0.3: globby@^11.0.2:
version "11.0.3" version "11.0.3"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb"
integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==
@ -5165,6 +5172,18 @@ globby@^11.0.2, globby@^11.0.3:
merge2 "^1.3.0" merge2 "^1.3.0"
slash "^3.0.0" slash "^3.0.0"
globby@^11.0.4:
version "11.0.4"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
dependencies:
array-union "^2.1.0"
dir-glob "^3.0.1"
fast-glob "^3.1.1"
ignore "^5.1.4"
merge2 "^1.3.0"
slash "^3.0.0"
glogg@^1.0.0: glogg@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f"
@ -6411,6 +6430,22 @@ json5@^2.1.2, json5@^2.1.3:
dependencies: dependencies:
minimist "^1.2.5" minimist "^1.2.5"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-5.0.0.tgz#e6b718f73da420d612823996fdf14a03f6ff6922"
integrity sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==
dependencies:
universalify "^0.1.2"
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^6.0.1: jsonfile@^6.0.1:
version "6.1.0" version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
@ -6653,10 +6688,10 @@ koa@2.13.1:
type-is "^1.6.16" type-is "^1.6.16"
vary "^1.1.2" vary "^1.1.2"
koa@2.13.3: koa@2.13.4:
version "2.13.3" version "2.13.4"
resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.3.tgz#a62641ba753ec54bee2c6da1a4f294c5fac35407" resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e"
integrity sha512-XhXIoR+ylAwqG3HhXwnMPQAM/4xfywz52OvxZNmxmTWGGHsvmBv4NSIhURha6yMuvEex1WdtplUTHnxnKpQiGw== integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==
dependencies: dependencies:
accepts "^1.3.5" accepts "^1.3.5"
cache-content-type "^1.0.0" cache-content-type "^1.0.0"
@ -7310,10 +7345,10 @@ minizlib@^2.0.0, minizlib@^2.1.1:
minipass "^3.0.0" minipass "^3.0.0"
yallist "^4.0.0" yallist "^4.0.0"
misskey-js@0.0.6: misskey-js@0.0.8:
version "0.0.6" version "0.0.8"
resolved "https://registry.yarnpkg.com/misskey-js/-/misskey-js-0.0.6.tgz#2470a833c29e67d263318d9287ba935c5182027b" resolved "https://registry.yarnpkg.com/misskey-js/-/misskey-js-0.0.8.tgz#b47a1ec54bff96b23cc2a6b307a3895f99a94424"
integrity sha512-fzKn/WPPvTNAiCyoXYrczaqAmFZE7+MjCHFeCs624G+QRi35kVW0HLCMbSsGruMWEwHHZ1PKYI0pH6h9wSo9iw== integrity sha512-Q1L6FaroVz8kpW7T4xQyJmJKSwjOYPbNY3TspOUWmbIBDf2JP0HVeKEFLI9dvdSL0kSkdQNz3MSVLjlHiyPqLQ==
dependencies: dependencies:
autobind-decorator "^2.4.0" autobind-decorator "^2.4.0"
eventemitter3 "^4.0.7" eventemitter3 "^4.0.7"
@ -7457,10 +7492,10 @@ nanoid@^3.1.23:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
nanoid@^3.1.28: nanoid@^3.1.30:
version "3.1.29" version "3.1.30"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.29.tgz#214fb2d7a33e1a5bef4757b779dfaeb6a4e5aeb4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
integrity sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg== integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
nanomatch@^1.2.9: nanomatch@^1.2.9:
version "1.2.13" version "1.2.13"
@ -7535,10 +7570,10 @@ node-abi@^2.21.0:
dependencies: dependencies:
semver "^5.4.1" semver "^5.4.1"
node-addon-api@^4.1.0: node-addon-api@^4.2.0:
version "4.1.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.1.0.tgz#f1722f1f60793584632ffffb79e12ca042c48bd0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.2.0.tgz#117cbb5a959dff0992e1c586ae0393573e4d2a87"
integrity sha512-Zz1o1BDX2VtduiAt6kgiUl8jX1Vm3NMboljFYKQJ6ee8AGfiTvM2mlZFI3xPbqjs80rCQgiVJI/DjQ/1QJ0HwA== integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q==
node-fetch@2.6.1, node-fetch@^2.6.1: node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1" version "2.6.1"
@ -8236,10 +8271,14 @@ pgpass@1.x:
dependencies: dependencies:
split "^1.0.0" split "^1.0.0"
picocolors@^0.2.1: "photoswipe@git://github.com/dimsemenov/photoswipe#v5-beta":
version "0.2.1" version "5.1.7"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" resolved "git://github.com/dimsemenov/photoswipe#60040164333bd257409669e715e4327afdb3aec7"
integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1:
version "2.2.2" version "2.2.2"
@ -8800,13 +8839,13 @@ postcss-zindex@^2.0.1:
postcss "^5.0.4" postcss "^5.0.4"
uniqs "^2.0.0" uniqs "^2.0.0"
postcss@8.3.9: postcss@8.3.11:
version "8.3.9" version "8.3.11"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858"
integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==
dependencies: dependencies:
nanoid "^3.1.28" nanoid "^3.1.30"
picocolors "^0.2.1" picocolors "^1.0.0"
source-map-js "^0.6.2" source-map-js "^0.6.2"
postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16:
@ -9768,10 +9807,10 @@ sass-loader@12.2.0:
klona "^2.0.4" klona "^2.0.4"
neo-async "^2.6.2" neo-async "^2.6.2"
sass@1.43.2: sass@1.43.3:
version "1.43.2" version "1.43.3"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.43.2.tgz#c02501520c624ad6622529a8b3724eb08da82d65" resolved "https://registry.yarnpkg.com/sass/-/sass-1.43.3.tgz#aa16a69131b84f0cd23189a242571e8905f1ce43"
integrity sha512-DncYhjl3wBaPMMJR0kIUaH3sF536rVrOcqqVGmTZHQRRzj7LQlyGV7Mb8aCKFyILMr5VsPHwRYtyKpnKYlmQSQ== integrity sha512-BJnLngqWpMeS65UvlYYEuCb3/fLxDxhHtOB/gWPxs6NKrslTxGt3ZxwIvOe/0Jm4tWwM/+tIpE3wj4dLEhPDeQ==
dependencies: dependencies:
chokidar ">=3.0.0 <4.0.0" chokidar ">=3.0.0 <4.0.0"
@ -9915,14 +9954,14 @@ shallow-clone@^3.0.0:
dependencies: dependencies:
kind-of "^6.0.2" kind-of "^6.0.2"
sharp@0.29.1: sharp@0.29.2:
version "0.29.1" version "0.29.2"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.1.tgz#f60b50f24f399464a24187c86bd2da41aae50b85" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.2.tgz#e8c003cd9cb321585b32dbda6eed3baa7d6f2308"
integrity sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ== integrity sha512-XWRdiYLIJ3tDUejRyG24KERnJzMfIoyiJBntd2S6/uj3NEeNgRFRLgiBlvPxMa8aml14dKKD98yHinSNKp1xzQ==
dependencies: dependencies:
color "^4.0.1" color "^4.0.1"
detect-libc "^1.0.3" detect-libc "^1.0.3"
node-addon-api "^4.1.0" node-addon-api "^4.2.0"
prebuild-install "^6.1.4" prebuild-install "^6.1.4"
semver "^7.3.5" semver "^7.3.5"
simple-get "^3.1.0" simple-get "^3.1.0"
@ -10460,10 +10499,10 @@ strtok3@^6.2.4:
"@tokenizer/token" "^0.3.0" "@tokenizer/token" "^0.3.0"
peek-readable "^4.0.1" peek-readable "^4.0.1"
style-loader@3.3.0: style-loader@3.3.1:
version "3.3.0" version "3.3.1"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.0.tgz#d66ea95fc50b22f8b79b69a9e414760fcf58d8d8" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575"
integrity sha512-szANub7ksJtQioJYtpbWwh1hUl99uK15n5HDlikeCRil/zYMZgSxucHddyF/4A3qJMUiAjPhFowrrQuNMA7jwQ== integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==
stylehacks@^5.0.1: stylehacks@^5.0.1:
version "5.0.1" version "5.0.1"
@ -10529,61 +10568,6 @@ sver-compat@^1.5.0:
es6-iterator "^2.0.1" es6-iterator "^2.0.1"
es6-symbol "^3.1.1" es6-symbol "^3.1.1"
svg.draggable.js@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz#c514a2f1405efb6f0263e7958f5b68fce50603ba"
integrity sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==
dependencies:
svg.js "^2.0.1"
svg.easing.js@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/svg.easing.js/-/svg.easing.js-2.0.0.tgz#8aa9946b0a8e27857a5c40a10eba4091e5691f12"
integrity sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI=
dependencies:
svg.js ">=2.3.x"
svg.filter.js@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/svg.filter.js/-/svg.filter.js-2.0.2.tgz#91008e151389dd9230779fcbe6e2c9a362d1c203"
integrity sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM=
dependencies:
svg.js "^2.2.5"
svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5:
version "2.7.1"
resolved "https://registry.yarnpkg.com/svg.js/-/svg.js-2.7.1.tgz#eb977ed4737001eab859949b4a398ee1bb79948d"
integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
svg.pathmorphing.js@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz#c25718a1cc7c36e852ecabc380e758ac09bb2b65"
integrity sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==
dependencies:
svg.js "^2.4.0"
svg.resize.js@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/svg.resize.js/-/svg.resize.js-1.4.3.tgz#885abd248e0cd205b36b973c4b578b9a36f23332"
integrity sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==
dependencies:
svg.js "^2.6.5"
svg.select.js "^2.1.2"
svg.select.js@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-2.1.2.tgz#e41ce13b1acff43a7441f9f8be87a2319c87be73"
integrity sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==
dependencies:
svg.js "^2.2.5"
svg.select.js@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-3.0.1.tgz#a4198e359f3825739226415f82176a90ea5cc917"
integrity sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==
dependencies:
svg.js "^2.6.5"
svgo@^0.7.0: svgo@^0.7.0:
version "0.7.2" version "0.7.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
@ -10641,10 +10625,10 @@ syslog-pro@1.0.0:
dependencies: dependencies:
moment "^2.22.2" moment "^2.22.2"
systeminformation@5.9.7: systeminformation@5.9.8:
version "5.9.7" version "5.9.8"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.9.7.tgz#8a5041d3aa1518e962b17740e20a3c75ff390e6d" resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.9.8.tgz#470d5781647418fd2f2ec945e507cd522a69d565"
integrity sha512-Vcmc8HaWPMFM4DoasuKN2lpvIwS2AqaoPuEGZc4HCT6tlRJH+IQ5GhA2BrUgjpBDJjFMj2Bti6qLOzP3T1arCw== integrity sha512-Dt54Vuu4Q5pGCsBtbVjIzD3Lahek7qIL+2vqAPqcPtPAlFRPf+ef4VKB4F5AL5UmdjYm7NFCTnwjoiu7qtxmQQ==
syuilo-password-strength@0.0.1: syuilo-password-strength@0.0.1:
version "0.0.1" version "0.0.1"
@ -10981,10 +10965,10 @@ ts-loader@9.2.6:
micromatch "^4.0.0" micromatch "^4.0.0"
semver "^7.3.4" semver "^7.3.4"
ts-node@10.3.0: ts-node@10.4.0:
version "10.3.0" version "10.4.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.3.0.tgz#a797f2ed3ff50c9a5d814ce400437cb0c1c048b4" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7"
integrity sha512-RYIy3i8IgpFH45AX4fQHExrT8BxDeKTdC83QFJkNzkvt8uFB6QJ8XMyhynYiKMLxt9a7yuXaDBZNOYS3XjDcYw== integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==
dependencies: dependencies:
"@cspotcode/source-map-support" "0.7.0" "@cspotcode/source-map-support" "0.7.0"
"@tsconfig/node10" "^1.0.7" "@tsconfig/node10" "^1.0.7"
@ -11278,7 +11262,7 @@ unique-stream@^2.0.2:
json-stable-stringify-without-jsonify "^1.0.1" json-stable-stringify-without-jsonify "^1.0.1"
through2-filter "^3.0.0" through2-filter "^3.0.0"
universalify@^0.1.2: universalify@^0.1.0, universalify@^0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
@ -11404,7 +11388,7 @@ v-debounce@0.1.2:
resolved "https://registry.yarnpkg.com/v-debounce/-/v-debounce-0.1.2.tgz#cab75df7def2783215bf449ef85c69c2decf0a55" resolved "https://registry.yarnpkg.com/v-debounce/-/v-debounce-0.1.2.tgz#cab75df7def2783215bf449ef85c69c2decf0a55"
integrity sha1-yrdd997yeDIVv0Se+Fxpwt7PClU= integrity sha1-yrdd997yeDIVv0Se+Fxpwt7PClU=
v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: v8-compile-cache@^2.0.3:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"
integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==
@ -11648,10 +11632,10 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-cli@4.9.0: webpack-cli@4.9.1:
version "4.9.0" version "4.9.1"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.0.tgz#dc43e6e0f80dd52e89cbf73d5294bcd7ad6eb343" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3"
integrity sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw== integrity sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==
dependencies: dependencies:
"@discoveryjs/json-ext" "^0.5.0" "@discoveryjs/json-ext" "^0.5.0"
"@webpack-cli/configtest" "^1.1.0" "@webpack-cli/configtest" "^1.1.0"
@ -11664,7 +11648,6 @@ webpack-cli@4.9.0:
import-local "^3.0.2" import-local "^3.0.2"
interpret "^2.2.0" interpret "^2.2.0"
rechoir "^0.7.0" rechoir "^0.7.0"
v8-compile-cache "^2.2.0"
webpack-merge "^5.7.3" webpack-merge "^5.7.3"
webpack-merge@^5.7.3: webpack-merge@^5.7.3:
@ -11688,10 +11671,10 @@ webpack-sources@^3.2.0:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw== integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==
webpack@5.58.2: webpack@5.59.1:
version "5.58.2" version "5.59.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.58.2.tgz#6b4af12fc9bd5cbedc00dc0a2fc2b9592db16b44" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.59.1.tgz#60c77e9aad796252153d4d7ab6b2d4c11f0e548c"
integrity sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw== integrity sha512-I01IQV9K96FlpXX3V0L4nvd7gb0r7thfuu1IfT2P4uOHOA77nKARAKDYGe/tScSHKnffNIyQhLC8kRXzY4KEHQ==
dependencies: dependencies:
"@types/eslint-scope" "^3.7.0" "@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50" "@types/estree" "^0.0.50"