Merge branch 'develop' of https://codeberg.org/calckey/calckey into feat/module-player
This commit is contained in:
commit
c788adb3e5
67 changed files with 2101 additions and 1231 deletions
13
.config/LICENSE
Normal file
13
.config/LICENSE
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright 2023 Calckey
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -25,6 +25,7 @@ coverage
|
||||||
!/.config/devenv.yml
|
!/.config/devenv.yml
|
||||||
!/.config/docker_example.env
|
!/.config/docker_example.env
|
||||||
!/.config/helm_values_example.yml
|
!/.config/helm_values_example.yml
|
||||||
|
!/.config/LICENSE
|
||||||
|
|
||||||
#docker dev config
|
#docker dev config
|
||||||
/dev/docker-compose.yml
|
/dev/docker-compose.yml
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
- 👍 also triggers generic like/favorite
|
- 👍 also triggers generic like/favorite
|
||||||
- [Add additional background for acrylic popups if backdrop-filter is unsupported](https://github.com/misskey-dev/misskey/pull/8671)
|
- [Add additional background for acrylic popups if backdrop-filter is unsupported](https://github.com/misskey-dev/misskey/pull/8671)
|
||||||
- [Add parameters to MFM rotate](https://github.com/misskey-dev/misskey/pull/8549)
|
- [Add parameters to MFM rotate](https://github.com/misskey-dev/misskey/pull/8549)
|
||||||
- Many changes from [Foundkey](https://akkoma.dev/FoundKeyGang/Foundkey)
|
- Many changes from [FoundKey](https://akkoma.dev/FoundKeyGang/FoundKey)
|
||||||
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/0ece67b04c3f0365057624c1068808276ccab981: refactor pages/auth.form.vue to composition API
|
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/0ece67b04c3f0365057624c1068808276ccab981: refactor pages/auth.form.vue to composition API
|
||||||
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/4bc9610d8bf5af736b5e89e4782395705de45d7d: remove unnecessary joins
|
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/4bc9610d8bf5af736b5e89e4782395705de45d7d: remove unnecessary joins
|
||||||
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/9ee609d70082f7a6dc119a5d83c0e7c5e1208676: enhance privacy of notes
|
- https://akkoma.dev/FoundKeyGang/FoundKey/commit/9ee609d70082f7a6dc119a5d83c0e7c5e1208676: enhance privacy of notes
|
||||||
|
|
|
@ -2704,7 +2704,7 @@ Co-committed-by: naskya <naskya@noreply.codeberg.org>
|
||||||
|
|
||||||
Passwords will be automatically re-hashed on sign-in. All new password hashes will be argon2 by default. This uses argon2id and is not configurable. In the very unlikely case someone has more specific needs, a fork is recommended. ChangeLog: Added Co-authored-by: Chloe Kudryavtsev <code@toast.bunkerlabs.net>
|
Passwords will be automatically re-hashed on sign-in. All new password hashes will be argon2 by default. This uses argon2id and is not configurable. In the very unlikely case someone has more specific needs, a fork is recommended. ChangeLog: Added Co-authored-by: Chloe Kudryavtsev <code@toast.bunkerlabs.net>
|
||||||
|
|
||||||
Breaks Calckey -> Misskey migration, but fixes Foundkey -> Calckey migration
|
Breaks Calckey -> Misskey migration, but fixes FoundKey -> Calckey migration
|
||||||
|
|
||||||
- Add argon
|
- Add argon
|
||||||
|
|
||||||
|
|
29
COPYING
29
COPYING
|
@ -1,15 +1,24 @@
|
||||||
Unless otherwise stated this repository is
|
Unless specified otherwise, the entirety of this repository is subject to the following:
|
||||||
Copyright © 2014-2022 syuilo and contributers
|
Copyright © 2014-2023 syuilo and contributors
|
||||||
Copyright © 2022 thatonecalculator and contributers
|
Copyright © 2022-2023 Kainoa Kanter and contributors
|
||||||
|
|
||||||
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Calckey includes several third-party Open-Source softwares.
|
These specific configuration directories:
|
||||||
|
|
||||||
Emoji keywords for Unicode 11 and below by Mu-An Chiou
|
- .config/
|
||||||
License: MIT
|
- custom/assets/
|
||||||
https://github.com/muan/emojilib/blob/master/LICENSE
|
|
||||||
|
and their contents are
|
||||||
|
Copyright © 2022-2023 Kainoa Kanter and contributors
|
||||||
|
|
||||||
|
And are distributed under The Apache License, Version 2.0, you should have received a copy of the license file as LICENSE in each specified directory.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Calckey includes several third-party open-source softwares and software libraries.
|
||||||
|
|
||||||
RsaSignature2017 implementation by Transmute Industries Inc
|
RsaSignature2017 implementation by Transmute Industries Inc
|
||||||
License: MIT
|
License: MIT
|
||||||
|
@ -23,6 +32,6 @@ Chiptune2.js by Simon Gündling
|
||||||
License: MIT
|
License: MIT
|
||||||
https://github.com/deskjet/chiptune2.js#license
|
https://github.com/deskjet/chiptune2.js#license
|
||||||
|
|
||||||
libopenmpt (as part of openmpt) by OpenMPT
|
Licenses for all softwares and software libraries installed via the Node Package Manager ("npm") can be found by running the following shell command in the root directory of this repository:
|
||||||
License: BSD 3-Clause
|
|
||||||
https://github.com/OpenMPT/openmpt/blob/master/LICENSE
|
pnpm licenses list
|
||||||
|
|
12
README.md
12
README.md
|
@ -72,6 +72,14 @@
|
||||||
|
|
||||||
# 🌠 Getting started
|
# 🌠 Getting started
|
||||||
|
|
||||||
|
Want to just join a Calckey server? View the list here, pick one, and join:
|
||||||
|
|
||||||
|
### https://calckey.org/join
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Want to make your own? Keep reading!
|
||||||
|
|
||||||
This guide will work for both **starting from scratch** and **migrating from Misskey**.
|
This guide will work for both **starting from scratch** and **migrating from Misskey**.
|
||||||
|
|
||||||
## 🔰 Easy installers
|
## 🔰 Easy installers
|
||||||
|
@ -208,9 +216,9 @@ Please don't use ElasticSearch unless you already have an ElasticSearch setup an
|
||||||
- Edit `.config/default.yml`, making sure to fill out required fields.
|
- Edit `.config/default.yml`, making sure to fill out required fields.
|
||||||
- Also copy and edit `.config/docker_example.env` to `.config/docker.env` if you're using Docker.
|
- Also copy and edit `.config/docker_example.env` to `.config/docker.env` if you're using Docker.
|
||||||
|
|
||||||
## 🚚 Migrating from Misskey to Calckey
|
## 🚚 Migrating from Misskey/FoundKey to Calckey
|
||||||
|
|
||||||
For migrating from Misskey v13, Misskey v12, and Foundkey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md).
|
For migrating from Misskey v13, Misskey v12, and FoundKey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md).
|
||||||
|
|
||||||
## 🌐 Web proxy
|
## 🌐 Web proxy
|
||||||
|
|
||||||
|
|
13
custom/assets/LICENSE
Normal file
13
custom/assets/LICENSE
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright 2023 Calckey
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
|
@ -1,10 +1,11 @@
|
||||||
# 🚚 Migrating from Misskey to Calckey
|
# 🚚 Migrating from Misskey/FoundKey to Calckey
|
||||||
|
|
||||||
The following procedure may not work depending on your environment and version of Misskey.
|
All the guides below assume you're starting in the root of the repo directory.
|
||||||
|
|
||||||
**Make sure you**
|
### Before proceeding
|
||||||
- **stopped all master and worker processes of Misskey.**
|
|
||||||
- **have backups of the database before performing any commands.**
|
- **Ensure you have stopped all master and worker processes of Misskey.**
|
||||||
|
- **Ensure you have backups of the database before performing any commands.**
|
||||||
|
|
||||||
## Misskey v13 and above
|
## Misskey v13 and above
|
||||||
|
|
||||||
|
@ -77,15 +78,16 @@ NODE_ENV=production pnpm run migrate
|
||||||
# build using prefered method
|
# build using prefered method
|
||||||
```
|
```
|
||||||
|
|
||||||
## Foundkey
|
## FoundKey
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd packages/backend
|
cd packages/backend
|
||||||
|
sed -i '12s/^/\/\//' ./migration/1663399074403-resize-comments-drive-file.js
|
||||||
|
|
||||||
LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)"
|
LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)"
|
||||||
NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | nl)"
|
NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)"
|
||||||
|
|
||||||
for i in $(seq 1 $NUM_MIGRAIONS); do
|
for i in $(seq 1 $NUM_MIGRATIONS); do
|
||||||
npx typeorm migration:revert -d ormconfig.js
|
npx typeorm migration:revert -d ormconfig.js
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -100,4 +102,4 @@ NODE_ENV=production pnpm run migrate
|
||||||
|
|
||||||
## Reverse
|
## Reverse
|
||||||
|
|
||||||
You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to Foundkey, though.
|
You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to FoundKey, although this is not recommended due to FoundKey being end-of-life.
|
||||||
|
|
|
@ -2144,3 +2144,6 @@ _skinTones:
|
||||||
swipeOnMobile: Permet lliscar entre pàgines
|
swipeOnMobile: Permet lliscar entre pàgines
|
||||||
enableIdenticonGeneration: Habilitar la generació d'Identicon
|
enableIdenticonGeneration: Habilitar la generació d'Identicon
|
||||||
enableServerMachineStats: Habilitar les estadístiques del maquinari del servidor
|
enableServerMachineStats: Habilitar les estadístiques del maquinari del servidor
|
||||||
|
showPopup: Notificar els usuaris amb una finestra emergent
|
||||||
|
showWithSparkles: Mostra amb espurnes
|
||||||
|
youHaveUnreadAnnouncements: Tens anuncis sense llegir
|
||||||
|
|
|
@ -645,6 +645,7 @@ useBlurEffectForModal: "Use blur effect for modals"
|
||||||
useFullReactionPicker: "Use full-size reaction picker"
|
useFullReactionPicker: "Use full-size reaction picker"
|
||||||
width: "Width"
|
width: "Width"
|
||||||
height: "Height"
|
height: "Height"
|
||||||
|
xl: "XL"
|
||||||
large: "Big"
|
large: "Big"
|
||||||
medium: "Medium"
|
medium: "Medium"
|
||||||
small: "Small"
|
small: "Small"
|
||||||
|
@ -1118,6 +1119,9 @@ enableIdenticonGeneration: "Enable Identicon generation"
|
||||||
showPopup: "Notify users with popup"
|
showPopup: "Notify users with popup"
|
||||||
showWithSparkles: "Show with sparkles"
|
showWithSparkles: "Show with sparkles"
|
||||||
youHaveUnreadAnnouncements: "You have unread announcements"
|
youHaveUnreadAnnouncements: "You have unread announcements"
|
||||||
|
donationLink: "Link to donation page"
|
||||||
|
neverShow: "Don't show again"
|
||||||
|
remindMeLater: "Maybe later"
|
||||||
|
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "Reduces the effort of server moderation through automatically recognizing
|
description: "Reduces the effort of server moderation through automatically recognizing
|
||||||
|
@ -1216,6 +1220,10 @@ _aboutMisskey:
|
||||||
source: "Source code"
|
source: "Source code"
|
||||||
translation: "Translate Calckey"
|
translation: "Translate Calckey"
|
||||||
donate: "Donate to Calckey"
|
donate: "Donate to Calckey"
|
||||||
|
donateTitle: "Enjoying Calckey?"
|
||||||
|
pleaseDonateToCalckey: "Please consider donating to Calckey to support its development."
|
||||||
|
pleaseDonateToHost: "Please also consider donating to your home server, {host}, to help support its operation costs."
|
||||||
|
donateHost: "Donate to {host}"
|
||||||
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
||||||
Thank you! 🥰"
|
Thank you! 🥰"
|
||||||
patrons: "Calckey patrons"
|
patrons: "Calckey patrons"
|
||||||
|
|
|
@ -983,6 +983,8 @@ enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にす
|
||||||
showPopup: "ポップアップを表示してユーザーに知らせる"
|
showPopup: "ポップアップを表示してユーザーに知らせる"
|
||||||
showWithSparkles: "タイトルをキラキラさせる"
|
showWithSparkles: "タイトルをキラキラさせる"
|
||||||
youHaveUnreadAnnouncements: "未読のお知らせがあります"
|
youHaveUnreadAnnouncements: "未読のお知らせがあります"
|
||||||
|
neverShow: "今後表示しない"
|
||||||
|
remindMeLater: "また後で"
|
||||||
|
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。"
|
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。"
|
||||||
|
|
24
package.json
24
package.json
|
@ -1,16 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "calckey",
|
"name": "calckey",
|
||||||
"version": "14.0.0-rc3",
|
"version": "14.0.0-dev71",
|
||||||
"codename": "aqua",
|
"codename": "aqua",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://codeberg.org/calckey/calckey.git"
|
"url": "https://codeberg.org/calckey/calckey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.6.6",
|
"packageManager": "pnpm@8.6.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp",
|
"rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp",
|
||||||
"build": "pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp",
|
"build": "pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp",
|
||||||
"start": "pnpm --filter backend run start",
|
"start": "pnpm --filter backend run start",
|
||||||
"start:test": "pnpm --filter backend run start:test",
|
"start:test": "pnpm --filter backend run start:test",
|
||||||
"init": "pnpm run migrate",
|
"init": "pnpm run migrate",
|
||||||
|
@ -21,13 +21,13 @@
|
||||||
"watch": "pnpm run dev",
|
"watch": "pnpm run dev",
|
||||||
"dev": "pnpm node ./scripts/dev.js",
|
"dev": "pnpm node ./scripts/dev.js",
|
||||||
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
|
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
|
||||||
"lint": "pnpm -r run lint",
|
"lint": "pnpm -r --parallel run lint",
|
||||||
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"e2e": "start-server-and-test start:test http://localhost:61812 cy:run",
|
"e2e": "start-server-and-test start:test http://localhost:61812 cy:run",
|
||||||
"mocha": "pnpm --filter backend run mocha",
|
"mocha": "pnpm --filter backend run mocha",
|
||||||
"test": "pnpm run mocha",
|
"test": "pnpm run mocha",
|
||||||
"format": "pnpm -r run format",
|
"format": "pnpm -r --parallel run format",
|
||||||
"clean": "pnpm node ./scripts/clean.js",
|
"clean": "pnpm node ./scripts/clean.js",
|
||||||
"clean-all": "pnpm node ./scripts/clean-all.js",
|
"clean-all": "pnpm node ./scripts/clean-all.js",
|
||||||
"cleanall": "pnpm run clean-all"
|
"cleanall": "pnpm run clean-all"
|
||||||
|
@ -36,17 +36,17 @@
|
||||||
"chokidar": "^3.3.1"
|
"chokidar": "^3.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "5.2.0",
|
"@bull-board/api": "5.6.0",
|
||||||
"@bull-board/ui": "5.2.0",
|
"@bull-board/ui": "5.6.0",
|
||||||
"@napi-rs/cli": "^2.16.1",
|
"@napi-rs/cli": "^2.16.1",
|
||||||
"@tensorflow/tfjs": "^3.21.0",
|
"@tensorflow/tfjs": "^3.21.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"seedrandom": "^3.0.5"
|
"seedrandom": "^3.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "18.11.18",
|
"@types/gulp": "4.0.13",
|
||||||
"@types/gulp": "4.0.10",
|
"@types/gulp-rename": "2.0.2",
|
||||||
"@types/gulp-rename": "2.0.1",
|
"@types/node": "20.4.1",
|
||||||
"chalk": "4.1.2",
|
"chalk": "4.1.2",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "10.11.0",
|
"cypress": "10.11.0",
|
||||||
|
@ -59,6 +59,6 @@
|
||||||
"install-peers": "^1.0.4",
|
"install-peers": "^1.0.4",
|
||||||
"rome": "^12.1.3",
|
"rome": "^12.1.3",
|
||||||
"start-server-and-test": "1.15.2",
|
"start-server-and-test": "1.15.2",
|
||||||
"typescript": "4.9.4"
|
"typescript": "5.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
packages/backend/migration/1689136347561-donation-link.js
Normal file
15
packages/backend/migration/1689136347561-donation-link.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
export class DonationLink1689136347561 {
|
||||||
|
name = "DonationLink1689136347561";
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "meta" ADD "donationLink" character varying(256)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,16 +25,16 @@
|
||||||
"@tensorflow/tfjs-node": "3.21.1"
|
"@tensorflow/tfjs-node": "3.21.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "5.2.0",
|
"@bull-board/api": "5.6.0",
|
||||||
"@bull-board/koa": "5.2.0",
|
"@bull-board/koa": "5.6.0",
|
||||||
"@bull-board/ui": "5.2.0",
|
"@bull-board/ui": "5.6.0",
|
||||||
"@discordapp/twemoji": "14.1.2",
|
"@discordapp/twemoji": "14.1.2",
|
||||||
"@elastic/elasticsearch": "7.17.0",
|
"@elastic/elasticsearch": "7.17.0",
|
||||||
"@koa/cors": "3.4.3",
|
"@koa/cors": "3.4.3",
|
||||||
"@koa/multer": "3.0.2",
|
"@koa/multer": "3.0.2",
|
||||||
"@koa/router": "9.0.1",
|
"@koa/router": "9.0.1",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@redocly/openapi-core": "1.0.0-beta.120",
|
"@redocly/openapi-core": "1.0.0-beta.131",
|
||||||
"@sinonjs/fake-timers": "9.1.2",
|
"@sinonjs/fake-timers": "9.1.2",
|
||||||
"@syuilo/aiscript": "0.11.1",
|
"@syuilo/aiscript": "0.11.1",
|
||||||
"@tensorflow/tfjs": "^4.2.0",
|
"@tensorflow/tfjs": "^4.2.0",
|
||||||
|
@ -45,17 +45,17 @@
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"autolinker": "4.0.0",
|
"autolinker": "4.0.0",
|
||||||
"autwh": "0.1.0",
|
"autwh": "0.1.0",
|
||||||
"aws-sdk": "2.1277.0",
|
"aws-sdk": "2.1413.0",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"blurhash": "1.1.5",
|
"blurhash": "2.0.5",
|
||||||
"bull": "4.10.4",
|
"bull": "4.10.4",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
"calckey-js": "workspace:*",
|
"calckey-js": "workspace:*",
|
||||||
"cbor": "8.1.0",
|
"cbor": "8.1.0",
|
||||||
"chalk": "5.2.0",
|
"chalk": "5.3.0",
|
||||||
"chalk-template": "0.4.0",
|
"chalk-template": "0.4.0",
|
||||||
"chokidar": "3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"cli-highlight": "2.1.11",
|
"cli-highlight": "2.1.11",
|
||||||
"color-convert": "2.0.1",
|
"color-convert": "2.0.1",
|
||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
|
@ -68,15 +68,15 @@
|
||||||
"got": "12.5.3",
|
"got": "12.5.3",
|
||||||
"hpagent": "0.1.2",
|
"hpagent": "0.1.2",
|
||||||
"ioredis": "5.3.2",
|
"ioredis": "5.3.2",
|
||||||
"ip-cidr": "3.0.11",
|
"ip-cidr": "3.1.0",
|
||||||
"is-svg": "4.3.2",
|
"is-svg": "4.3.2",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"jsdom": "20.0.3",
|
"jsdom": "20.0.3",
|
||||||
"jsonld": "8.2.0",
|
"jsonld": "8.2.0",
|
||||||
"jsrsasign": "10.6.1",
|
"jsrsasign": "10.8.6",
|
||||||
"koa": "2.13.4",
|
"koa": "2.14.2",
|
||||||
"koa-body": "^6.0.1",
|
"koa-body": "^6.0.1",
|
||||||
"koa-bodyparser": "4.3.0",
|
"koa-bodyparser": "4.4.1",
|
||||||
"koa-favicon": "2.1.0",
|
"koa-favicon": "2.1.0",
|
||||||
"koa-json-body": "5.3.0",
|
"koa-json-body": "5.3.0",
|
||||||
"koa-logger": "3.2.1",
|
"koa-logger": "3.2.1",
|
||||||
|
@ -98,9 +98,9 @@
|
||||||
"nsfwjs": "2.4.2",
|
"nsfwjs": "2.4.2",
|
||||||
"oauth": "^0.10.0",
|
"oauth": "^0.10.0",
|
||||||
"os-utils": "0.0.14",
|
"os-utils": "0.0.14",
|
||||||
"otpauth": "^9.1.2",
|
"otpauth": "^9.1.3",
|
||||||
"parse5": "7.1.2",
|
"parse5": "7.1.2",
|
||||||
"pg": "8.11.0",
|
"pg": "8.11.1",
|
||||||
"private-ip": "2.3.4",
|
"private-ip": "2.3.4",
|
||||||
"probe-image-size": "7.2.3",
|
"probe-image-size": "7.2.3",
|
||||||
"promise-limit": "2.7.0",
|
"promise-limit": "2.7.0",
|
||||||
|
@ -110,7 +110,7 @@
|
||||||
"qs": "6.11.2",
|
"qs": "6.11.2",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"re2": "1.19.0",
|
"re2": "1.19.1",
|
||||||
"redis-lock": "0.1.4",
|
"redis-lock": "0.1.4",
|
||||||
"redis-semaphore": "5.3.1",
|
"redis-semaphore": "5.3.1",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
"rss-parser": "3.13.0",
|
"rss-parser": "3.13.0",
|
||||||
"sanitize-html": "2.10.0",
|
"sanitize-html": "2.10.0",
|
||||||
"seedrandom": "^3.0.5",
|
"seedrandom": "^3.0.5",
|
||||||
"semver": "7.5.1",
|
"semver": "7.5.4",
|
||||||
"sharp": "0.32.1",
|
"sharp": "0.32.1",
|
||||||
"sonic-channel": "^1.3.1",
|
"sonic-channel": "^1.3.1",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
|
@ -130,27 +130,26 @@
|
||||||
"tinycolor2": "1.5.2",
|
"tinycolor2": "1.5.2",
|
||||||
"tmp": "0.2.1",
|
"tmp": "0.2.1",
|
||||||
"twemoji-parser": "14.0.0",
|
"twemoji-parser": "14.0.0",
|
||||||
"typeorm": "0.3.11",
|
"typeorm": "0.3.17",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"web-push": "3.6.1",
|
"web-push": "3.6.3",
|
||||||
"websocket": "1.0.34",
|
"websocket": "1.0.34",
|
||||||
"xev": "3.0.2"
|
"xev": "3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@swc/cli": "^0.1.62",
|
"@swc/cli": "^0.1.62",
|
||||||
"@swc/core": "^1.3.62",
|
"@swc/core": "^1.3.68",
|
||||||
"@types/adm-zip": "^0.5.0",
|
"@types/adm-zip": "^0.5.0",
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
"@types/bull": "3.15.9",
|
|
||||||
"@types/cbor": "6.0.0",
|
"@types/cbor": "6.0.0",
|
||||||
"@types/escape-regexp": "0.0.1",
|
"@types/escape-regexp": "0.0.1",
|
||||||
"@types/fluent-ffmpeg": "2.1.20",
|
"@types/fluent-ffmpeg": "2.1.21",
|
||||||
"@types/js-yaml": "4.0.5",
|
"@types/js-yaml": "4.0.5",
|
||||||
"@types/jsdom": "20.0.1",
|
"@types/jsdom": "21.1.1",
|
||||||
"@types/jsonld": "1.5.8",
|
"@types/jsonld": "1.5.9",
|
||||||
"@types/jsrsasign": "10.5.4",
|
"@types/jsrsasign": "10.5.8",
|
||||||
"@types/koa": "2.13.5",
|
"@types/koa": "2.13.6",
|
||||||
"@types/koa-bodyparser": "4.3.10",
|
"@types/koa-bodyparser": "4.3.10",
|
||||||
"@types/koa-cors": "0.0.2",
|
"@types/koa-cors": "0.0.2",
|
||||||
"@types/koa-favicon": "2.0.21",
|
"@types/koa-favicon": "2.0.21",
|
||||||
|
@ -169,7 +168,7 @@
|
||||||
"@types/probe-image-size": "^7.2.0",
|
"@types/probe-image-size": "^7.2.0",
|
||||||
"@types/pug": "2.0.6",
|
"@types/pug": "2.0.6",
|
||||||
"@types/punycode": "2.1.0",
|
"@types/punycode": "2.1.0",
|
||||||
"@types/qrcode": "1.5.0",
|
"@types/qrcode": "1.5.1",
|
||||||
"@types/qs": "6.9.7",
|
"@types/qs": "6.9.7",
|
||||||
"@types/random-seed": "0.3.3",
|
"@types/random-seed": "0.3.3",
|
||||||
"@types/ratelimiter": "3.4.4",
|
"@types/ratelimiter": "3.4.4",
|
||||||
|
@ -177,17 +176,16 @@
|
||||||
"@types/rename": "1.0.4",
|
"@types/rename": "1.0.4",
|
||||||
"@types/sanitize-html": "2.9.0",
|
"@types/sanitize-html": "2.9.0",
|
||||||
"@types/semver": "7.5.0",
|
"@types/semver": "7.5.0",
|
||||||
"@types/sharp": "0.31.1",
|
|
||||||
"@types/sinonjs__fake-timers": "8.1.2",
|
"@types/sinonjs__fake-timers": "8.1.2",
|
||||||
"@types/tinycolor2": "1.4.3",
|
"@types/tinycolor2": "1.4.3",
|
||||||
"@types/tmp": "0.2.3",
|
"@types/tmp": "0.2.3",
|
||||||
"@types/uuid": "8.3.4",
|
"@types/uuid": "9.0.2",
|
||||||
"@types/web-push": "3.3.2",
|
"@types/web-push": "3.3.2",
|
||||||
"@types/websocket": "1.0.5",
|
"@types/websocket": "1.0.5",
|
||||||
"@types/ws": "8.5.4",
|
"@types/ws": "8.5.5",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "^8.42.0",
|
"eslint": "^8.44.0",
|
||||||
"execa": "6.1.0",
|
"execa": "6.1.0",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"json5-loader": "4.0.1",
|
"json5-loader": "4.0.1",
|
||||||
|
@ -195,11 +193,11 @@
|
||||||
"pug": "3.0.2",
|
"pug": "3.0.2",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"swc-loader": "^0.2.3",
|
"swc-loader": "^0.2.3",
|
||||||
"ts-loader": "9.4.3",
|
"ts-loader": "9.4.4",
|
||||||
"ts-node": "10.9.1",
|
"ts-node": "10.9.1",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "5.1.3",
|
"typescript": "5.1.6",
|
||||||
"webpack": "^5.85.1",
|
"webpack": "^5.88.1",
|
||||||
"ws": "8.13.0"
|
"ws": "8.13.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ export function nyaize(text: string): string {
|
||||||
)
|
)
|
||||||
.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥")
|
.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥")
|
||||||
.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥")
|
.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥")
|
||||||
// zh-CN, zh-TW
|
|
||||||
.replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵")
|
|
||||||
// el-GR
|
// el-GR
|
||||||
.replaceAll("να", "νια")
|
.replaceAll("να", "νια")
|
||||||
.replaceAll("ΝΑ", "ΝΙΑ")
|
.replaceAll("ΝΑ", "ΝΙΑ")
|
||||||
|
|
|
@ -556,4 +556,10 @@ export class Meta {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public enableIdenticonGeneration: boolean;
|
public enableIdenticonGeneration: boolean;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
length: 256,
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public donationLink: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
|
import type { DoneCallback } from "bull";
|
||||||
|
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
|
@ -11,7 +12,7 @@ const logger = queueLogger.createSubLogger("index-all-notes");
|
||||||
|
|
||||||
export default async function indexAllNotes(
|
export default async function indexAllNotes(
|
||||||
job: Bull.Job<Record<string, unknown>>,
|
job: Bull.Job<Record<string, unknown>>,
|
||||||
done: () => void,
|
done: DoneCallback,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
logger.info("Indexing all notes...");
|
logger.info("Indexing all notes...");
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ export default async function indexAllNotes(
|
||||||
let total: number = (job.data.total as number) ?? 0;
|
let total: number = (job.data.total as number) ?? 0;
|
||||||
|
|
||||||
let running = true;
|
let running = true;
|
||||||
const take = 100000;
|
const take = 10000;
|
||||||
const batch = 100;
|
const batch = 100;
|
||||||
while (running) {
|
while (running) {
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -41,13 +42,14 @@ export default async function indexAllNotes(
|
||||||
},
|
},
|
||||||
relations: ["user"],
|
relations: ["user"],
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
logger.error(`Failed to query notes ${e}`);
|
logger.error(`Failed to query notes ${e}`);
|
||||||
continue;
|
done(e);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
job.progress(100);
|
await job.progress(100);
|
||||||
running = false;
|
running = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +57,7 @@ export default async function indexAllNotes(
|
||||||
try {
|
try {
|
||||||
const count = await Notes.count();
|
const count = await Notes.count();
|
||||||
total = count;
|
total = count;
|
||||||
job.update({ indexedCount, cursor, total });
|
await job.update({ indexedCount, cursor, total });
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
for (let i = 0; i < notes.length; i += batch) {
|
for (let i = 0; i < notes.length; i += batch) {
|
||||||
|
@ -69,12 +71,12 @@ export default async function indexAllNotes(
|
||||||
|
|
||||||
indexedCount += chunk.length;
|
indexedCount += chunk.length;
|
||||||
const pct = (indexedCount / total) * 100;
|
const pct = (indexedCount / total) * 100;
|
||||||
job.update({ indexedCount, cursor, total });
|
await job.update({ indexedCount, cursor, total });
|
||||||
job.progress(+pct.toFixed(1));
|
await job.progress(+pct.toFixed(1));
|
||||||
logger.info(`Indexed notes ${indexedCount}/${total ? total : "?"}`);
|
logger.info(`Indexed notes ${indexedCount}/${total ? total : "?"}`);
|
||||||
}
|
}
|
||||||
cursor = notes[notes.length - 1].id;
|
cursor = notes[notes.length - 1].id;
|
||||||
job.update({ indexedCount, cursor, total });
|
await job.update({ indexedCount, cursor, total });
|
||||||
|
|
||||||
if (notes.length < take) {
|
if (notes.length < take) {
|
||||||
running = false;
|
running = false;
|
||||||
|
|
|
@ -50,7 +50,7 @@ export async function importMastoPost(
|
||||||
text: text || undefined,
|
text: text || undefined,
|
||||||
reply,
|
reply,
|
||||||
renote: null,
|
renote: null,
|
||||||
cw: post.sensitive,
|
cw: post.object.sensitive ? post.object.summary : undefined,
|
||||||
localOnly: false,
|
localOnly: false,
|
||||||
visibility: "hidden",
|
visibility: "hidden",
|
||||||
visibleUsers: [],
|
visibleUsers: [],
|
||||||
|
|
|
@ -491,6 +491,11 @@ export const meta = {
|
||||||
optional: false,
|
optional: false,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
},
|
},
|
||||||
|
donationLink: {
|
||||||
|
type: "string",
|
||||||
|
optional: true,
|
||||||
|
nullable: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -604,5 +609,6 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
experimentalFeatures: instance.experimentalFeatures,
|
experimentalFeatures: instance.experimentalFeatures,
|
||||||
enableServerMachineStats: instance.enableServerMachineStats,
|
enableServerMachineStats: instance.enableServerMachineStats,
|
||||||
enableIdenticonGeneration: instance.enableIdenticonGeneration,
|
enableIdenticonGeneration: instance.enableIdenticonGeneration,
|
||||||
|
donationLink: instance.donationLink,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -177,6 +177,9 @@ export const paramDef = {
|
||||||
postImports: { type: "boolean" },
|
postImports: { type: "boolean" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
enableServerMachineStats: { type: "boolean" },
|
||||||
|
enableIdenticonGeneration: { type: "boolean" },
|
||||||
|
donationLink: { type: "string", nullable: true },
|
||||||
},
|
},
|
||||||
required: [],
|
required: [],
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -568,6 +571,21 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
set.experimentalFeatures = ps.experimentalFeatures || undefined;
|
set.experimentalFeatures = ps.experimentalFeatures || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ps.enableServerMachineStats !== undefined) {
|
||||||
|
set.enableServerMachineStats = ps.enableServerMachineStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ps.enableIdenticonGeneration !== undefined) {
|
||||||
|
set.enableIdenticonGeneration = ps.enableIdenticonGeneration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ps.donationLink !== undefined) {
|
||||||
|
set.donationLink = ps.donationLink;
|
||||||
|
if (set.donationLink && !/^https?:\/\//i.test(set.donationLink)) {
|
||||||
|
set.donationLink = `https://${set.donationLink}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await db.transaction(async (transactionalEntityManager) => {
|
await db.transaction(async (transactionalEntityManager) => {
|
||||||
const metas = await transactionalEntityManager.find(Meta, {
|
const metas = await transactionalEntityManager.find(Meta, {
|
||||||
order: {
|
order: {
|
||||||
|
|
|
@ -389,6 +389,11 @@ export const meta = {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
default: "⭐",
|
default: "⭐",
|
||||||
},
|
},
|
||||||
|
donationLink: {
|
||||||
|
type: "string",
|
||||||
|
optional: "true",
|
||||||
|
nullable: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -491,6 +496,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
translatorAvailable:
|
translatorAvailable:
|
||||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||||
defaultReaction: instance.defaultReaction,
|
defaultReaction: instance.defaultReaction,
|
||||||
|
donationLink: instance.donationLink,
|
||||||
|
|
||||||
...(ps.detail
|
...(ps.detail
|
||||||
? {
|
? {
|
||||||
|
|
|
@ -247,7 +247,7 @@ export default class Connection {
|
||||||
|
|
||||||
for (const obj of objs) {
|
for (const obj of objs) {
|
||||||
const { type, body } = obj;
|
const { type, body } = obj;
|
||||||
console.log(type, body);
|
// console.log(type, body);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "readNotification":
|
case "readNotification":
|
||||||
this.onReadNotification(body);
|
this.onReadNotification(body);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"@syuilo/aiscript": "0.11.1",
|
"@syuilo/aiscript": "0.11.1",
|
||||||
"@types/escape-regexp": "0.0.1",
|
"@types/escape-regexp": "0.0.1",
|
||||||
"@types/glob": "8.1.0",
|
"@types/glob": "8.1.0",
|
||||||
"@types/gulp": "4.0.11",
|
"@types/gulp": "4.0.13",
|
||||||
"@types/gulp-rename": "2.0.2",
|
"@types/gulp-rename": "2.0.2",
|
||||||
"@types/katex": "0.16.0",
|
"@types/katex": "0.16.0",
|
||||||
"@types/matter-js": "0.18.2",
|
"@types/matter-js": "0.18.2",
|
||||||
|
@ -29,8 +29,8 @@
|
||||||
"@vue/compiler-sfc": "3.3.4",
|
"@vue/compiler-sfc": "3.3.4",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"autosize": "5.0.2",
|
"autosize": "5.0.2",
|
||||||
"blurhash": "1.1.5",
|
"blurhash": "2.0.5",
|
||||||
"broadcast-channel": "4.19.1",
|
"broadcast-channel": "5.1.0",
|
||||||
"browser-image-resizer": "github:misskey-dev/browser-image-resizer",
|
"browser-image-resizer": "github:misskey-dev/browser-image-resizer",
|
||||||
"calckey-js": "workspace:*",
|
"calckey-js": "workspace:*",
|
||||||
"chart.js": "4.3.0",
|
"chart.js": "4.3.0",
|
||||||
|
@ -39,57 +39,58 @@
|
||||||
"chartjs-plugin-gradient": "0.6.1",
|
"chartjs-plugin-gradient": "0.6.1",
|
||||||
"chartjs-plugin-zoom": "2.0.1",
|
"chartjs-plugin-zoom": "2.0.1",
|
||||||
"city-timezones": "^1.2.1",
|
"city-timezones": "^1.2.1",
|
||||||
"compare-versions": "5.0.3",
|
"compare-versions": "6.0.0",
|
||||||
"cropperjs": "2.0.0-beta.2",
|
"cropperjs": "2.0.0-beta.2",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "10.11.0",
|
"cypress": "10.11.0",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
"emojilib": "github:thatonecalculator/emojilib",
|
"emojilib": "github:thatonecalculator/emojilib",
|
||||||
"escape-regexp": "0.0.1",
|
"escape-regexp": "0.0.1",
|
||||||
"eventemitter3": "4.0.7",
|
"eventemitter3": "5.0.1",
|
||||||
"focus-trap": "^7.4.3",
|
"fast-blurhash": "^1.1.2",
|
||||||
|
"focus-trap": "^7.5.2",
|
||||||
"focus-trap-vue": "^4.0.2",
|
"focus-trap-vue": "^4.0.2",
|
||||||
"gsap": "^3.11.5",
|
"gsap": "^3.12.2",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.1",
|
||||||
"insert-text-at-cursor": "0.3.0",
|
"insert-text-at-cursor": "0.3.0",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"katex": "0.16.7",
|
"katex": "0.16.8",
|
||||||
"libopenmpt-wasm": "github:TheEssem/libopenmpt-packaging#build",
|
"libopenmpt-wasm": "github:TheEssem/libopenmpt-packaging#build",
|
||||||
"matter-js": "0.18.0",
|
"matter-js": "0.18.0",
|
||||||
"mfm-js": "0.23.3",
|
"mfm-js": "0.23.3",
|
||||||
"photoswipe": "5.3.7",
|
"photoswipe": "5.3.8",
|
||||||
"prettier": "3.0.0",
|
"prettier": "3.0.0",
|
||||||
"prettier-plugin-vue": "1.1.6",
|
"prettier-plugin-vue": "1.1.6",
|
||||||
"prismjs": "1.29.0",
|
"prismjs": "1.29.0",
|
||||||
"punycode": "2.1.1",
|
"punycode": "2.3.0",
|
||||||
"querystring": "0.2.1",
|
"querystring": "0.2.1",
|
||||||
"rndstr": "1.0.0",
|
"rndstr": "1.0.0",
|
||||||
"rollup": "3.23.1",
|
"rollup": "3.26.2",
|
||||||
"s-age": "1.1.2",
|
"s-age": "1.1.2",
|
||||||
"sass": "1.62.1",
|
"sass": "1.63.6",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"start-server-and-test": "1.15.2",
|
"start-server-and-test": "1.15.2",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"swiper": "9.3.2",
|
"swiper": "10.0.4",
|
||||||
"syuilo-password-strength": "0.0.1",
|
"syuilo-password-strength": "0.0.1",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.146.0",
|
"three": "0.146.0",
|
||||||
"throttle-debounce": "5.0.0",
|
"throttle-debounce": "5.0.0",
|
||||||
"tinycolor2": "1.5.2",
|
"tinycolor2": "1.6.0",
|
||||||
"tsc-alias": "1.8.6",
|
"tsc-alias": "1.8.7",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"twemoji-parser": "14.0.0",
|
"twemoji-parser": "14.0.0",
|
||||||
"typescript": "5.1.3",
|
"typescript": "5.1.6",
|
||||||
"unicode-emoji-json": "^0.4.0",
|
"unicode-emoji-json": "^0.4.0",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"vanilla-tilt": "1.8.0",
|
"vanilla-tilt": "1.8.0",
|
||||||
"vite": "4.3.9",
|
"vite": "4.4.2",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
|
"vue-draggable-plus": "^0.2.2",
|
||||||
"vue-isyourpasswordsafe": "^2.0.0",
|
"vue-isyourpasswordsafe": "^2.0.0",
|
||||||
"vue-plyr": "^7.0.0",
|
"vue-plyr": "^7.0.0",
|
||||||
"vue-prism-editor": "2.0.0-alpha.2",
|
"vue-prism-editor": "2.0.0-alpha.2"
|
||||||
"vuedraggable": "4.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,13 @@
|
||||||
<MkSparkle v-if="isGoodNews">{{ title }}</MkSparkle>
|
<MkSparkle v-if="isGoodNews">{{ title }}</MkSparkle>
|
||||||
<p v-else>{{ title }}</p>
|
<p v-else>{{ title }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div :class="$style.time">
|
||||||
|
<MkTime :time="announcement.createdAt" />
|
||||||
|
<div v-if="announcement.updatedAt">
|
||||||
|
{{ i18n.ts.updatedAt }}:
|
||||||
|
<MkTime :time="announcement.createdAt" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<Mfm :text="text" />
|
<Mfm :text="text" />
|
||||||
<img
|
<img
|
||||||
v-if="imageUrl != null"
|
v-if="imageUrl != null"
|
||||||
|
@ -68,6 +75,10 @@ const gotIt = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
.gotIt {
|
.gotIt {
|
||||||
margin: 8px 0 0 0;
|
margin: 8px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
<template #default="{ width, height }">
|
<template #default="{ width, height }">
|
||||||
<div
|
<div
|
||||||
class="mk-cropper-dialog"
|
class="mk-cropper-dialog"
|
||||||
:style="`--vw: ${width}px; --vh: ${height}px;`"
|
:style="`--vw: ${width ? `${width}px` : '100%'}; --vh: ${
|
||||||
|
height ? `${height}px` : '100%'
|
||||||
|
};`"
|
||||||
>
|
>
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div v-if="loading" class="loading">
|
<div v-if="loading" class="loading">
|
||||||
|
|
180
packages/client/src/components/MkDonation.vue
Normal file
180
packages/client/src/components/MkDonation.vue
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
<template>
|
||||||
|
<transition name="slide-fade">
|
||||||
|
<div v-if="show" class="_panel _shadow _acrylic" :class="$style.root">
|
||||||
|
<div :class="$style.icon">
|
||||||
|
<i class="ph-hand-heart ph-bold ph-5x" />
|
||||||
|
</div>
|
||||||
|
<div :class="$style.main">
|
||||||
|
<div :class="$style.title">
|
||||||
|
{{ i18n.ts._aboutMisskey.donateTitle }}
|
||||||
|
</div>
|
||||||
|
<div :class="$style.text">
|
||||||
|
{{ i18n.ts._aboutMisskey.pleaseDonateToCalckey }}
|
||||||
|
<p v-if="$instance.donationLink">
|
||||||
|
{{
|
||||||
|
i18n.t("_aboutMisskey.pleaseDonateToHost", {
|
||||||
|
host: hostname,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="_flexList" style="gap: 0.6rem;">
|
||||||
|
<MkButton
|
||||||
|
primary
|
||||||
|
@click="
|
||||||
|
openExternal('https://opencollective.com/calckey')
|
||||||
|
"
|
||||||
|
>{{ i18n.ts._aboutMisskey.donate }}</MkButton
|
||||||
|
>
|
||||||
|
<MkButton
|
||||||
|
v-if="$instance.donationLink"
|
||||||
|
gradate
|
||||||
|
@click="openExternal($instance.donationLink)"
|
||||||
|
>{{
|
||||||
|
i18n.t("_aboutMisskey.donateHost", {
|
||||||
|
host: hostname,
|
||||||
|
})
|
||||||
|
}}</MkButton
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="_flexList" style="margin-top: 0.6rem">
|
||||||
|
<MkButton @click="close">{{
|
||||||
|
i18n.ts.remindMeLater
|
||||||
|
}}</MkButton>
|
||||||
|
<MkButton @click="neverShow">{{
|
||||||
|
i18n.ts.neverShow
|
||||||
|
}}</MkButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="_button" :class="$style.close" @click="close">
|
||||||
|
<i class="ph-x ph-bold ph-lg"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, nextTick } from "vue";
|
||||||
|
import MkButton from "@/components/MkButton.vue";
|
||||||
|
import { host } from "@/config";
|
||||||
|
import { i18n } from "@/i18n";
|
||||||
|
import * as os from "@/os";
|
||||||
|
import { instance } from "@/instance";
|
||||||
|
|
||||||
|
let show = ref(false);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: "closed"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const hostname = instance.name?.length < 38 ? instance.name : host;
|
||||||
|
|
||||||
|
const zIndex = os.claimZIndex("low");
|
||||||
|
|
||||||
|
function slideIn() {
|
||||||
|
show.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
show.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
slideIn();
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
localStorage.setItem("latestDonationInfoShownAt", Date.now().toString());
|
||||||
|
emit("closed");
|
||||||
|
show.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function neverShow() {
|
||||||
|
localStorage.setItem("neverShowDonationInfo", "true");
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openExternal(link) {
|
||||||
|
window.open(link, "_blank");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.slide-fade-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter-active {
|
||||||
|
transition: opacity 0.5s, transform 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter-to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-leave-from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-leave-active {
|
||||||
|
transition: opacity 0.5s, transform 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.root {
|
||||||
|
position: fixed;
|
||||||
|
z-index: v-bind(zIndex);
|
||||||
|
bottom: var(--margin);
|
||||||
|
left: 2%;
|
||||||
|
bottom: 2%;
|
||||||
|
margin: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: calc(100% - (var(--margin) * 2));
|
||||||
|
max-width: 500px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 25px;
|
||||||
|
width: 100px;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
.icon {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
.icon {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding: 25px 25px 25px 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
margin: 0.7em 0 1em 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,7 +12,7 @@
|
||||||
:transparent-bg="true"
|
:transparent-bg="true"
|
||||||
:manual-showing="manualShowing"
|
:manual-showing="manualShowing"
|
||||||
:src="src"
|
:src="src"
|
||||||
@click="modal?.close()"
|
@click="checkForShift"
|
||||||
@opening="opening"
|
@opening="opening"
|
||||||
@close="emit('close')"
|
@close="emit('close')"
|
||||||
@closed="emit('closed')"
|
@closed="emit('closed')"
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||||
import MkModal from "@/components/MkModal.vue";
|
import MkModal from "@/components/MkModal.vue";
|
||||||
import MkEmojiPicker from "@/components/MkEmojiPicker.vue";
|
import MkEmojiPicker from "@/components/MkEmojiPicker.vue";
|
||||||
import { defaultStore } from "@/store";
|
import { defaultStore } from "@/store";
|
||||||
|
@ -58,20 +58,49 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const modal = ref<InstanceType<typeof MkModal>>();
|
const modal = ref<InstanceType<typeof MkModal>>();
|
||||||
const picker = ref<InstanceType<typeof MkEmojiPicker>>();
|
const picker = ref<InstanceType<typeof MkEmojiPicker>>();
|
||||||
|
const isShiftKeyPressed = ref(false);
|
||||||
|
|
||||||
|
const keydownHandler = (e) => {
|
||||||
|
if (e.key === "Shift") {
|
||||||
|
isShiftKeyPressed.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const keyupHandler = (e) => {
|
||||||
|
if (e.key === "Shift") {
|
||||||
|
isShiftKeyPressed.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkForShift(ev?: MouseEvent) {
|
||||||
|
if (!isShiftKeyPressed.value) {
|
||||||
|
modal.value?.close(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function chosen(emoji: any) {
|
function chosen(emoji: any) {
|
||||||
emit("done", emoji);
|
emit("done", emoji);
|
||||||
modal.value?.close();
|
checkForShift();
|
||||||
}
|
}
|
||||||
|
|
||||||
function opening() {
|
function opening() {
|
||||||
try {
|
try {
|
||||||
picker.value?.reset();
|
picker.value?.reset();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Something's wrong with restting the emoji picker: ${e}`);
|
console.error("Something's wrong with resetting the emoji picker", e);
|
||||||
}
|
}
|
||||||
picker.value?.focus();
|
picker.value?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener("keydown", keydownHandler);
|
||||||
|
window.addEventListener("keyup", keyupHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener("keydown", keydownHandler);
|
||||||
|
window.removeEventListener("keyup", keyupHandler);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import { decode } from "blurhash";
|
import { decodeBlurHash } from "fast-blurhash";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -47,8 +47,8 @@ const canvas = $ref<HTMLCanvasElement>();
|
||||||
let loaded = $ref(false);
|
let loaded = $ref(false);
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
if (props.hash == null) return;
|
if (props.hash == null || canvas == null) return;
|
||||||
const pixels = decode(props.hash, props.size, props.size);
|
const pixels = decodeBlurHash(props.hash, props.size, props.size);
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
const imageData = ctx!.createImageData(props.size, props.size);
|
const imageData = ctx!.createImageData(props.size, props.size);
|
||||||
imageData.data.set(pixels);
|
imageData.data.set(pixels);
|
||||||
|
|
|
@ -226,11 +226,13 @@ watch(
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: max-content;
|
min-width: max-content;
|
||||||
width: 110px;
|
width: 110px;
|
||||||
transition: width 0.2s cubic-bezier(0,0,0,1);
|
transition: width 0.2s cubic-bezier(0, 0, 0, 1);
|
||||||
[data-plyr="volume"] {
|
[data-plyr="volume"] {
|
||||||
width: 0;
|
width: 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
transition: margin 0.3s, opacity .2s 0.2s;
|
transition:
|
||||||
|
margin 0.3s,
|
||||||
|
opacity 0.2s 0.2s;
|
||||||
}
|
}
|
||||||
&:not(:hover):not(:focus-within) {
|
&:not(:hover):not(:focus-within) {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
|
@ -238,7 +240,9 @@ watch(
|
||||||
[data-plyr="volume"] {
|
[data-plyr="volume"] {
|
||||||
margin-inline: 0px;
|
margin-inline: 0px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: margin 0.3s, opacity 0.1s;
|
transition:
|
||||||
|
margin 0.3s,
|
||||||
|
opacity 0.1s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -869,6 +869,9 @@ defineExpose({
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5 !important;
|
||||||
|
}
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 3.5em;
|
max-width: 3.5em;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
|
|
|
@ -477,6 +477,9 @@ function noteClick(e) {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5 !important;
|
||||||
|
}
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 3.5em;
|
max-width: 3.5em;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="files.length != 0" class="skeikyzd">
|
<div v-show="files.length != 0" class="skeikyzd">
|
||||||
<XDraggable
|
<VueDraggable
|
||||||
v-model="_files"
|
v-model="_files"
|
||||||
class="files"
|
class="files"
|
||||||
item-key="id"
|
|
||||||
animation="150"
|
animation="150"
|
||||||
delay="100"
|
delay="100"
|
||||||
delay-on-touch-only="true"
|
delay-on-touch-only="true"
|
||||||
>
|
>
|
||||||
<template #item="{ element }">
|
|
||||||
<div
|
<div
|
||||||
class="file"
|
class="file"
|
||||||
|
v-for="element in _files"
|
||||||
|
:key="element.id"
|
||||||
@click="showFileMenu(element, $event)"
|
@click="showFileMenu(element, $event)"
|
||||||
@contextmenu.prevent="showFileMenu(element, $event)"
|
@contextmenu.prevent="showFileMenu(element, $event)"
|
||||||
>
|
>
|
||||||
|
@ -24,27 +24,19 @@
|
||||||
<i class="ph-warning ph-bold ph-lg icon"></i>
|
<i class="ph-warning ph-bold ph-lg icon"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</VueDraggable>
|
||||||
</XDraggable>
|
|
||||||
<p class="remain">{{ 16 - files.length }}/16</p>
|
<p class="remain">{{ 16 - files.length }}/16</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, defineAsyncComponent } from "vue";
|
import { defineAsyncComponent, ref, computed } from "vue";
|
||||||
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import MkDriveFileThumbnail from "@/components/MkDriveFileThumbnail.vue";
|
import MkDriveFileThumbnail from "@/components/MkDriveFileThumbnail.vue";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps({
|
||||||
components: {
|
|
||||||
XDraggable: defineAsyncComponent(() =>
|
|
||||||
import("vuedraggable").then((x) => x.default),
|
|
||||||
),
|
|
||||||
MkDriveFileThumbnail,
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
files: {
|
files: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -53,65 +45,55 @@ export default defineComponent({
|
||||||
type: Function,
|
type: Function,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
|
|
||||||
emits: ["updated", "detach", "changeSensitive", "changeName"],
|
const emits = defineEmits([
|
||||||
|
"updated",
|
||||||
|
"detach",
|
||||||
|
"changeSensitive",
|
||||||
|
"changeName",
|
||||||
|
]);
|
||||||
|
|
||||||
data() {
|
const _files = computed({
|
||||||
return {
|
get: () => props.files,
|
||||||
menu: null as Promise<null> | null,
|
set: (value) => emits("updated", value),
|
||||||
i18n,
|
});
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
const detachMedia = (id) => {
|
||||||
_files: {
|
if (props.detachMediaFn) {
|
||||||
get() {
|
props.detachMediaFn(id);
|
||||||
return this.files;
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.$emit("updated", value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
detachMedia(id) {
|
|
||||||
if (this.detachMediaFn) {
|
|
||||||
this.detachMediaFn(id);
|
|
||||||
} else {
|
} else {
|
||||||
this.$emit("detach", id);
|
emits("detach", id);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
toggleSensitive(file) {
|
|
||||||
|
function toggleSensitive(file) {
|
||||||
os.api("drive/files/update", {
|
os.api("drive/files/update", {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
isSensitive: !file.isSensitive,
|
isSensitive: !file.isSensitive,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$emit("changeSensitive", file, !file.isSensitive);
|
emits("changeSensitive", file, !file.isSensitive);
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
async rename(file) {
|
|
||||||
|
async function rename(file) {
|
||||||
const { canceled, result } = await os.inputText({
|
const { canceled, result } = await os.inputText({
|
||||||
title: i18n.ts.enterFileName,
|
title: i18n.ts.enterFileName,
|
||||||
default: file.name,
|
default: file.name,
|
||||||
allowEmpty: false,
|
|
||||||
});
|
});
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
os.api("drive/files/update", {
|
os.api("drive/files/update", {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
name: result,
|
name: result,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$emit("changeName", file, result);
|
emits("changeName", file, result);
|
||||||
file.name = result;
|
file.name = result;
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
async describe(file) {
|
async function describe(file) {
|
||||||
os.popup(
|
os.popup(
|
||||||
defineAsyncComponent(
|
defineAsyncComponent(() => import("@/components/MkMediaCaption.vue")),
|
||||||
() => import("@/components/MkMediaCaption.vue"),
|
|
||||||
),
|
|
||||||
{
|
{
|
||||||
title: i18n.ts.describeFile,
|
title: i18n.ts.describeFile,
|
||||||
input: {
|
input: {
|
||||||
|
@ -123,8 +105,7 @@ export default defineComponent({
|
||||||
{
|
{
|
||||||
done: (result) => {
|
done: (result) => {
|
||||||
if (!result || result.canceled) return;
|
if (!result || result.canceled) return;
|
||||||
let comment =
|
let comment = result.result.length === 0 ? null : result.result;
|
||||||
result.result.length === 0 ? null : result.result;
|
|
||||||
os.api("drive/files/update", {
|
os.api("drive/files/update", {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
comment: comment,
|
comment: comment,
|
||||||
|
@ -135,18 +116,16 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
"closed",
|
"closed",
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
showFileMenu(file, ev: MouseEvent) {
|
function showFileMenu(file, ev: MouseEvent) {
|
||||||
if (this.menu) return;
|
os.popupMenu(
|
||||||
this.menu = os
|
|
||||||
.popupMenu(
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: i18n.ts.renameFile,
|
text: i18n.ts.renameFile,
|
||||||
icon: "ph-cursor-text ph-bold ph-lg",
|
icon: "ph-cursor-text ph-bold ph-lg",
|
||||||
action: () => {
|
action: () => {
|
||||||
this.rename(file);
|
rename(file);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -157,30 +136,27 @@ export default defineComponent({
|
||||||
? "ph-eye ph-bold ph-lg"
|
? "ph-eye ph-bold ph-lg"
|
||||||
: "ph-eye-slash ph-bold ph-lg",
|
: "ph-eye-slash ph-bold ph-lg",
|
||||||
action: () => {
|
action: () => {
|
||||||
this.toggleSensitive(file);
|
toggleSensitive(file);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: i18n.ts.describeFile,
|
text: i18n.ts.describeFile,
|
||||||
icon: "ph-subtitles ph-bold ph-lg",
|
icon: "ph-subtitles ph-bold ph-lg",
|
||||||
action: () => {
|
action: () => {
|
||||||
this.describe(file);
|
describe(file);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: i18n.ts.attachCancel,
|
text: i18n.ts.attachCancel,
|
||||||
icon: "ph-x ph-bold ph-lg",
|
icon: "ph-x ph-bold ph-lg",
|
||||||
action: () => {
|
action: () => {
|
||||||
this.detachMedia(file.id);
|
detachMedia(file.id);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
ev.currentTarget ?? ev.target,
|
(ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined,
|
||||||
)
|
);
|
||||||
.then(() => (this.menu = null));
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -219,8 +195,8 @@ export default defineComponent({
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background: rgba(17, 17, 17, 0.7);
|
background: var(--header);
|
||||||
color: #fff;
|
color: var(--fg);
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
|
@ -10,8 +10,13 @@
|
||||||
<i class="ph-repeat ph-bold ph-lg"></i>
|
<i class="ph-repeat ph-bold ph-lg"></i>
|
||||||
<p v-if="count > 0 && !detailedView" class="count">{{ count }}</p>
|
<p v-if="count > 0 && !detailedView" class="count">{{ count }}</p>
|
||||||
</button>
|
</button>
|
||||||
<button v-else class="eddddedb _button">
|
<button
|
||||||
<i class="ph-prohibit ph-bold ph-lg"></i>
|
v-else
|
||||||
|
class="eddddedb _button"
|
||||||
|
disabled="true"
|
||||||
|
v-tooltip.noDelay.bottom="i18n.ts.disabled"
|
||||||
|
>
|
||||||
|
<i class="ph-repeat ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,9 @@ onUnmounted(() => {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 0.2em;
|
margin-bottom: 0.2em;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: transparent;
|
||||||
|
transition: text-decoration-color 0.2s;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin-bottom: -0.5em;
|
margin-bottom: -0.5em;
|
||||||
|
@ -279,7 +282,7 @@ onUnmounted(() => {
|
||||||
&:focus-within {
|
&:focus-within {
|
||||||
background: var(--panelHighlight);
|
background: var(--panelHighlight);
|
||||||
h3 {
|
h3 {
|
||||||
text-decoration: underline;
|
text-decoration-color: currentColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,8 @@
|
||||||
i18n.ts.close
|
i18n.ts.close
|
||||||
}}</MkButton>
|
}}</MkButton>
|
||||||
</header>
|
</header>
|
||||||
<XDraggable
|
<VueDraggable v-model="widgets_" handle=".handle" animation="150">
|
||||||
v-model="widgets_"
|
<div v-for="element in widgets_" :key="element.id">
|
||||||
item-key="id"
|
|
||||||
handle=".handle"
|
|
||||||
animation="150"
|
|
||||||
>
|
|
||||||
<template #item="{ element }">
|
|
||||||
<div class="customize-container">
|
<div class="customize-container">
|
||||||
<button
|
<button
|
||||||
class="config _button"
|
class="config _button"
|
||||||
|
@ -58,8 +53,8 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</XDraggable>
|
</VueDraggable>
|
||||||
</template>
|
</template>
|
||||||
<component
|
<component
|
||||||
:is="`mkw-${widget.name}`"
|
:is="`mkw-${widget.name}`"
|
||||||
|
@ -78,14 +73,13 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineAsyncComponent, reactive, ref, computed } from "vue";
|
import { defineAsyncComponent, reactive, ref, computed } from "vue";
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import MkSelect from "@/components/form/select.vue";
|
import MkSelect from "@/components/form/select.vue";
|
||||||
import MkButton from "@/components/MkButton.vue";
|
import MkButton from "@/components/MkButton.vue";
|
||||||
import { widgets as widgetDefs } from "@/widgets";
|
import { widgets as widgetDefs } from "@/widgets";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
|
||||||
const XDraggable = defineAsyncComponent(() => import("vuedraggable"));
|
|
||||||
|
|
||||||
type Widget = {
|
type Widget = {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -69,7 +69,7 @@ const alt = computed(() =>
|
||||||
vertical-align: -0.25em;
|
vertical-align: -0.25em;
|
||||||
|
|
||||||
&.custom {
|
&.custom {
|
||||||
height: 2.5em;
|
height: 2em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
|
|
||||||
|
|
|
@ -75,13 +75,12 @@ const target = self ? null : "_blank";
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.url {
|
.url {
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 80%;
|
|
||||||
display: inline-block;
|
|
||||||
overflow: clip;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
line-height: 1.05;
|
> span {
|
||||||
|
text-decoration: underline var(--fgTransparent);
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
transition: text-decoration-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
|
@ -111,5 +110,9 @@ const target = self ? null : "_blank";
|
||||||
> .hash {
|
> .hash {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover span {
|
||||||
|
text-decoration-color: var(--link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -409,7 +409,6 @@ export default defineComponent({
|
||||||
key: Math.random(),
|
key: Math.random(),
|
||||||
to: `/tags/${encodeURIComponent(token.props.hashtag)}`,
|
to: `/tags/${encodeURIComponent(token.props.hashtag)}`,
|
||||||
style: "color:var(--hashtag);",
|
style: "color:var(--hashtag);",
|
||||||
class: "_link",
|
|
||||||
},
|
},
|
||||||
`#${token.props.hashtag}`,
|
`#${token.props.hashtag}`,
|
||||||
),
|
),
|
||||||
|
|
|
@ -450,6 +450,29 @@ function checkForSplash() {
|
||||||
}
|
}
|
||||||
localStorage.setItem("lastUsed", Date.now().toString());
|
localStorage.setItem("lastUsed", Date.now().toString());
|
||||||
|
|
||||||
|
const latestDonationInfoShownAt = localStorage.getItem(
|
||||||
|
"latestDonationInfoShownAt",
|
||||||
|
);
|
||||||
|
const neverShowDonationInfo = localStorage.getItem("neverShowDonationInfo");
|
||||||
|
if (
|
||||||
|
neverShowDonationInfo !== "true" &&
|
||||||
|
new Date($i.createdAt).getTime() < Date.now() - 1000 * 60 * 60 * 24 * 3 &&
|
||||||
|
!location.pathname.startsWith("/miauth")
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
latestDonationInfoShownAt == null ||
|
||||||
|
new Date(latestDonationInfoShownAt).getTime() <
|
||||||
|
Date.now() - 1000 * 60 * 60 * 24 * 30
|
||||||
|
) {
|
||||||
|
popup(
|
||||||
|
defineAsyncComponent(() => import("@/components/MkDonation.vue")),
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
"closed",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ("Notification" in window) {
|
if ("Notification" in window) {
|
||||||
// 許可を得ていなかったらリクエスト
|
// 許可を得ていなかったらリクエスト
|
||||||
if (Notification.permission === "default") {
|
if (Notification.permission === "default") {
|
||||||
|
|
|
@ -101,8 +101,9 @@
|
||||||
><Mfm
|
><Mfm
|
||||||
:text="'@freeplay@calckey.social (UI/UX)'"
|
:text="'@freeplay@calckey.social (UI/UX)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink to="/@nmkj@calckey.jp"
|
<FormLink to="/@namekuji@calckey.social"
|
||||||
><Mfm :text="'@nmkj@calckey.jp (Backend)'"
|
><Mfm
|
||||||
|
:text="'@namekuji@calckey.social (Backend)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink to="/@dev@post.naskya.net"
|
<FormLink to="/@dev@post.naskya.net"
|
||||||
><Mfm :text="'@dev@post.naskya.net (Backend)'"
|
><Mfm :text="'@dev@post.naskya.net (Backend)'"
|
||||||
|
|
|
@ -93,6 +93,21 @@
|
||||||
external
|
external
|
||||||
>{{ i18n.ts.tos }}</FormLink
|
>{{ i18n.ts.tos }}</FormLink
|
||||||
>
|
>
|
||||||
|
<FormLink
|
||||||
|
v-if="$instance.donationLink"
|
||||||
|
:to="$instance.donationLink"
|
||||||
|
external
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><i class="ph-money ph-bold ph-lg"></i
|
||||||
|
></template>
|
||||||
|
{{
|
||||||
|
i18n.t("_aboutMisskey.donateHost", {
|
||||||
|
host: $instance.name || host,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
<template #suffix>Donate</template>
|
||||||
|
</FormLink>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
|
||||||
<FormSuspense :p="initStats">
|
<FormSuspense :p="initStats">
|
||||||
|
@ -163,7 +178,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted, watch } from "vue";
|
import { ref, computed, onMounted, watch } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import XEmojis from "./about.emojis.vue";
|
import XEmojis from "./about.emojis.vue";
|
||||||
import XFederation from "./about.federation.vue";
|
import XFederation from "./about.federation.vue";
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch } from "vue";
|
import { computed, watch } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import MkButton from "@/components/MkButton.vue";
|
import MkButton from "@/components/MkButton.vue";
|
||||||
import MkSwitch from "@/components/form/switch.vue";
|
import MkSwitch from "@/components/form/switch.vue";
|
||||||
|
|
|
@ -53,6 +53,20 @@
|
||||||
i18n.ts.maintainerEmail
|
i18n.ts.maintainerEmail
|
||||||
}}</template>
|
}}</template>
|
||||||
</FormInput>
|
</FormInput>
|
||||||
|
|
||||||
|
<FormInput
|
||||||
|
v-model="donationLink"
|
||||||
|
class="_formBlock"
|
||||||
|
>
|
||||||
|
<template #prefix
|
||||||
|
><i
|
||||||
|
class="ph-hand-heart ph-bold ph-lg"
|
||||||
|
></i
|
||||||
|
></template>
|
||||||
|
<template #label>{{
|
||||||
|
i18n.ts.donationLink
|
||||||
|
}}</template>
|
||||||
|
</FormInput>
|
||||||
</FormSplit>
|
</FormSplit>
|
||||||
|
|
||||||
<FormTextarea v-model="pinnedUsers" class="_formBlock">
|
<FormTextarea v-model="pinnedUsers" class="_formBlock">
|
||||||
|
@ -435,6 +449,7 @@ let description: string | null = $ref(null);
|
||||||
let tosUrl: string | null = $ref(null);
|
let tosUrl: string | null = $ref(null);
|
||||||
let maintainerName: string | null = $ref(null);
|
let maintainerName: string | null = $ref(null);
|
||||||
let maintainerEmail: string | null = $ref(null);
|
let maintainerEmail: string | null = $ref(null);
|
||||||
|
let donationLink: string | null = $ref(null);
|
||||||
let iconUrl: string | null = $ref(null);
|
let iconUrl: string | null = $ref(null);
|
||||||
let bannerUrl: string | null = $ref(null);
|
let bannerUrl: string | null = $ref(null);
|
||||||
let logoImageUrl: string | null = $ref(null);
|
let logoImageUrl: string | null = $ref(null);
|
||||||
|
@ -481,6 +496,7 @@ async function init() {
|
||||||
defaultDarkTheme = meta.defaultDarkTheme;
|
defaultDarkTheme = meta.defaultDarkTheme;
|
||||||
maintainerName = meta.maintainerName;
|
maintainerName = meta.maintainerName;
|
||||||
maintainerEmail = meta.maintainerEmail;
|
maintainerEmail = meta.maintainerEmail;
|
||||||
|
donationLink = meta.donationLink;
|
||||||
enableLocalTimeline = !meta.disableLocalTimeline;
|
enableLocalTimeline = !meta.disableLocalTimeline;
|
||||||
enableGlobalTimeline = !meta.disableGlobalTimeline;
|
enableGlobalTimeline = !meta.disableGlobalTimeline;
|
||||||
enableRecommendedTimeline = !meta.disableRecommendedTimeline;
|
enableRecommendedTimeline = !meta.disableRecommendedTimeline;
|
||||||
|
@ -527,6 +543,7 @@ function save() {
|
||||||
defaultDarkTheme: defaultDarkTheme === "" ? null : defaultDarkTheme,
|
defaultDarkTheme: defaultDarkTheme === "" ? null : defaultDarkTheme,
|
||||||
maintainerName,
|
maintainerName,
|
||||||
maintainerEmail,
|
maintainerEmail,
|
||||||
|
donationLink,
|
||||||
disableLocalTimeline: !enableLocalTimeline,
|
disableLocalTimeline: !enableLocalTimeline,
|
||||||
disableGlobalTimeline: !enableGlobalTimeline,
|
disableGlobalTimeline: !enableGlobalTimeline,
|
||||||
disableRecommendedTimeline: !enableRecommendedTimeline,
|
disableRecommendedTimeline: !enableRecommendedTimeline,
|
||||||
|
|
|
@ -15,8 +15,13 @@
|
||||||
class="_card announcement"
|
class="_card announcement"
|
||||||
>
|
>
|
||||||
<div class="_title">
|
<div class="_title">
|
||||||
<span v-if="$i && !announcement.isRead">🆕 </span
|
<span v-if="$i && !announcement.isRead">🆕 </span>
|
||||||
>{{ announcement.title }}
|
<h3>{{ announcement.title }}</h3>
|
||||||
|
<MkTime :time="announcement.createdAt" />
|
||||||
|
<div v-if="announcement.updatedAt">
|
||||||
|
{{ i18n.ts.updatedAt }}:
|
||||||
|
<MkTime :time="announcement.createdAt" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
<Mfm :text="announcement.text" />
|
<Mfm :text="announcement.text" />
|
||||||
|
@ -76,6 +81,10 @@ definePageMetadata({
|
||||||
margin-bottom: var(--margin);
|
margin-bottom: var(--margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> ._title {
|
||||||
|
padding: 14px 32px !important;
|
||||||
|
}
|
||||||
|
|
||||||
> ._content {
|
> ._content {
|
||||||
> img {
|
> img {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, defineComponent, inject, watch } from "vue";
|
import { computed, onMounted, defineComponent, inject, watch } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import MkChannelPreview from "@/components/MkChannelPreview.vue";
|
import MkChannelPreview from "@/components/MkChannelPreview.vue";
|
||||||
import MkChannelList from "@/components/MkChannelList.vue";
|
import MkChannelList from "@/components/MkChannelList.vue";
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch, onMounted } from "vue";
|
import { computed, watch, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import XFeatured from "./explore.featured.vue";
|
import XFeatured from "./explore.featured.vue";
|
||||||
import XUsers from "./explore.users.vue";
|
import XUsers from "./explore.users.vue";
|
||||||
|
|
|
@ -107,7 +107,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, defineComponent, watch, onMounted } from "vue";
|
import { computed, defineComponent, watch, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import MkFolder from "@/components/MkFolder.vue";
|
import MkFolder from "@/components/MkFolder.vue";
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
import MkPagination from "@/components/MkPagination.vue";
|
||||||
|
|
|
@ -338,7 +338,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watch } from "vue";
|
import { watch } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import type * as calckey from "calckey-js";
|
import type * as calckey from "calckey-js";
|
||||||
import MkChart from "@/components/MkChart.vue";
|
import MkChart from "@/components/MkChart.vue";
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, markRaw, onMounted, onUnmounted, watch } from "vue";
|
import { ref, markRaw, onMounted, onUnmounted, watch } from "vue";
|
||||||
import * as Acct from "calckey-js/built/acct";
|
import * as Acct from "calckey-js/built/acct";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import MkButton from "@/components/MkButton.vue";
|
import MkButton from "@/components/MkButton.vue";
|
||||||
import MkChatPreview from "@/components/MkChatPreview.vue";
|
import MkChatPreview from "@/components/MkChatPreview.vue";
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import { notificationTypes } from "calckey-js";
|
import { notificationTypes } from "calckey-js";
|
||||||
import XNotifications from "@/components/MkNotifications.vue";
|
import XNotifications from "@/components/MkNotifications.vue";
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<XDraggable
|
<VueDraggable
|
||||||
v-model="blocks"
|
v-model="blocks"
|
||||||
tag="div"
|
tag="div"
|
||||||
item-key="id"
|
|
||||||
handle=".drag-handle"
|
handle=".drag-handle"
|
||||||
:group="{ name: 'blocks' }"
|
:group="{ name: 'blocks' }"
|
||||||
animation="150"
|
animation="150"
|
||||||
swap-threshold="0.5"
|
swap-threshold="0.5"
|
||||||
>
|
>
|
||||||
<template #item="{ element }">
|
|
||||||
<component
|
<component
|
||||||
|
v-for="element in blocks"
|
||||||
|
:key="element"
|
||||||
:is="'x-' + element.type"
|
:is="'x-' + element.type"
|
||||||
:value="element"
|
:value="element"
|
||||||
:hpml="hpml"
|
:hpml="hpml"
|
||||||
@update:value="updateItem"
|
@update:value="updateItem"
|
||||||
@remove="() => removeItem(element)"
|
@remove="() => removeItem(element)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</VueDraggable>
|
||||||
</XDraggable>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, defineAsyncComponent } from "vue";
|
import { defineComponent, defineAsyncComponent } from "vue";
|
||||||
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import XSection from "./els/page-editor.el.section.vue";
|
import XSection from "./els/page-editor.el.section.vue";
|
||||||
import XText from "./els/page-editor.el.text.vue";
|
import XText from "./els/page-editor.el.text.vue";
|
||||||
import XTextarea from "./els/page-editor.el.textarea.vue";
|
import XTextarea from "./els/page-editor.el.textarea.vue";
|
||||||
|
@ -41,9 +41,7 @@ import * as os from "@/os";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XDraggable: defineAsyncComponent(() =>
|
VueDraggable,
|
||||||
import("vuedraggable").then((x) => x.default),
|
|
||||||
),
|
|
||||||
XSection,
|
XSection,
|
||||||
XText,
|
XText,
|
||||||
XImage,
|
XImage,
|
||||||
|
|
|
@ -118,19 +118,19 @@
|
||||||
|
|
||||||
<div v-else-if="tab === 'variables'">
|
<div v-else-if="tab === 'variables'">
|
||||||
<div class="qmuvgica">
|
<div class="qmuvgica">
|
||||||
<XDraggable
|
<VueDraggable
|
||||||
v-show="variables.length > 0"
|
v-show="variables.length > 0"
|
||||||
v-model="variables"
|
v-model="variables"
|
||||||
tag="div"
|
tag="div"
|
||||||
class="variables"
|
class="variables"
|
||||||
item-key="name"
|
|
||||||
handle=".drag-handle"
|
handle=".drag-handle"
|
||||||
:group="{ name: 'variables' }"
|
:group="{ name: 'variables' }"
|
||||||
animation="150"
|
animation="150"
|
||||||
swap-threshold="0.5"
|
swap-threshold="0.5"
|
||||||
>
|
>
|
||||||
<template #item="{ element }">
|
|
||||||
<XVariable
|
<XVariable
|
||||||
|
v-for="element in variables"
|
||||||
|
:key="element.name"
|
||||||
:model-value="element"
|
:model-value="element"
|
||||||
:removable="true"
|
:removable="true"
|
||||||
:hpml="hpml"
|
:hpml="hpml"
|
||||||
|
@ -139,8 +139,7 @@
|
||||||
:draggable="true"
|
:draggable="true"
|
||||||
@remove="() => removeVariable(element)"
|
@remove="() => removeVariable(element)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</VueDraggable>
|
||||||
</XDraggable>
|
|
||||||
|
|
||||||
<MkButton
|
<MkButton
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
|
@ -174,6 +173,7 @@ import { blockDefs } from "@/scripts/hpml/index";
|
||||||
import { HpmlTypeChecker } from "@/scripts/hpml/type-checker";
|
import { HpmlTypeChecker } from "@/scripts/hpml/type-checker";
|
||||||
import { url } from "@/config";
|
import { url } from "@/config";
|
||||||
import { collectPageVars } from "@/scripts/collect-page-vars";
|
import { collectPageVars } from "@/scripts/collect-page-vars";
|
||||||
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { selectFile } from "@/scripts/select-file";
|
import { selectFile } from "@/scripts/select-file";
|
||||||
import { mainRouter } from "@/router";
|
import { mainRouter } from "@/router";
|
||||||
|
@ -181,10 +181,6 @@ import { i18n } from "@/i18n";
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||||
import { $i } from "@/account";
|
import { $i } from "@/account";
|
||||||
|
|
||||||
const XDraggable = defineAsyncComponent(() =>
|
|
||||||
import("vuedraggable").then((x) => x.default),
|
|
||||||
);
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
initPageId?: string;
|
initPageId?: string;
|
||||||
initPageName?: string;
|
initPageName?: string;
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch, onMounted } from "vue";
|
import { computed, watch, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import MkPagePreview from "@/components/MkPagePreview.vue";
|
import MkPagePreview from "@/components/MkPagePreview.vue";
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
import MkPagination from "@/components/MkPagination.vue";
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch, onMounted } from "vue";
|
import { computed, watch, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import XNotes from "@/components/MkNotes.vue";
|
import XNotes from "@/components/MkNotes.vue";
|
||||||
import XUserList from "@/components/MkUserList.vue";
|
import XUserList from "@/components/MkUserList.vue";
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
<p>
|
<p>
|
||||||
{{ `${i18n.ts.lastUsedDate}: ${key.lastUsed}` }}
|
{{ `${i18n.ts.lastUsedDate}: ${key.lastUsed}` }}
|
||||||
</p>
|
</p>
|
||||||
<div class="_buttons _flexList">
|
<div class="_flexList">
|
||||||
<MkButton @click="renameKey(key)"
|
<MkButton @click="renameKey(key)"
|
||||||
><i
|
><i
|
||||||
class="ph-pencil-line ph-bold ph-lg"
|
class="ph-pencil-line ph-bold ph-lg"
|
||||||
|
|
|
@ -10,32 +10,30 @@
|
||||||
i18n.ts.reactionSettingDescription
|
i18n.ts.reactionSettingDescription
|
||||||
}}</template>
|
}}</template>
|
||||||
<div v-panel style="border-radius: 6px">
|
<div v-panel style="border-radius: 6px">
|
||||||
<XDraggable
|
<VueDraggable
|
||||||
v-model="reactions"
|
v-model="reactions"
|
||||||
class="zoaiodol"
|
:class="$style.root"
|
||||||
:item-key="(item) => item"
|
|
||||||
animation="150"
|
animation="150"
|
||||||
delay="100"
|
delay="100"
|
||||||
|
@end="save"
|
||||||
delay-on-touch-only="true"
|
delay-on-touch-only="true"
|
||||||
>
|
>
|
||||||
<template #item="{ element }">
|
<div
|
||||||
<button
|
v-for="item in reactions"
|
||||||
|
:key="item"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
@click="remove(element, $event)"
|
@click="remove(item, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji
|
<MkEmoji
|
||||||
:emoji="element"
|
:emoji="item"
|
||||||
style="height: 1.7em"
|
style="height: 1.7em"
|
||||||
class="emoji"
|
class="emoji"
|
||||||
/>
|
/>
|
||||||
</button>
|
</div>
|
||||||
</template>
|
</VueDraggable>
|
||||||
<template #footer>
|
|
||||||
<button class="_button add" @click="chooseEmoji">
|
<button class="_button add" @click="chooseEmoji">
|
||||||
<i class="ph-plus ph-bold ph-lg"></i>
|
<i class="ph-plus ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
|
||||||
</XDraggable>
|
|
||||||
</div>
|
</div>
|
||||||
<template #caption
|
<template #caption
|
||||||
>{{ i18n.ts.reactionSettingDescription2 }}
|
>{{ i18n.ts.reactionSettingDescription2 }}
|
||||||
|
@ -85,7 +83,7 @@
|
||||||
<option :value="1">{{ i18n.ts.small }}</option>
|
<option :value="1">{{ i18n.ts.small }}</option>
|
||||||
<option :value="2">{{ i18n.ts.medium }}</option>
|
<option :value="2">{{ i18n.ts.medium }}</option>
|
||||||
<option :value="3">{{ i18n.ts.large }}</option>
|
<option :value="3">{{ i18n.ts.large }}</option>
|
||||||
<option :value="4">{{ i18n.ts.large }}+</option>
|
<option :value="4">{{ i18n.ts.xl }}</option>
|
||||||
</FormRadios>
|
</FormRadios>
|
||||||
|
|
||||||
<FormSwitch
|
<FormSwitch
|
||||||
|
@ -124,8 +122,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineAsyncComponent, watch } from "vue";
|
import { defineAsyncComponent, watch } from "vue";
|
||||||
import XDraggable from "vuedraggable";
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import FormInput from "@/components/form/input.vue";
|
|
||||||
import FormRadios from "@/components/form/radios.vue";
|
import FormRadios from "@/components/form/radios.vue";
|
||||||
import FromSlot from "@/components/form/slot.vue";
|
import FromSlot from "@/components/form/slot.vue";
|
||||||
import FormButton from "@/components/MkButton.vue";
|
import FormButton from "@/components/MkButton.vue";
|
||||||
|
@ -184,6 +181,7 @@ function remove(reaction, ev: MouseEvent) {
|
||||||
text: i18n.ts.remove,
|
text: i18n.ts.remove,
|
||||||
action: () => {
|
action: () => {
|
||||||
reactions = reactions.filter((x) => x !== reaction);
|
reactions = reactions.filter((x) => x !== reaction);
|
||||||
|
save();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -221,20 +219,11 @@ function chooseEmoji(ev: MouseEvent) {
|
||||||
}).then((emoji) => {
|
}).then((emoji) => {
|
||||||
if (!reactions.includes(emoji)) {
|
if (!reactions.includes(emoji)) {
|
||||||
reactions.push(emoji);
|
reactions.push(emoji);
|
||||||
|
save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
|
||||||
$$(reactions),
|
|
||||||
() => {
|
|
||||||
save();
|
|
||||||
},
|
|
||||||
{
|
|
||||||
deep: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(enableEmojiReactions, async () => {
|
watch(enableEmojiReactions, async () => {
|
||||||
await reloadAsk();
|
await reloadAsk();
|
||||||
});
|
});
|
||||||
|
@ -253,15 +242,11 @@ const headerTabs = $computed(() => []);
|
||||||
definePageMetadata({
|
definePageMetadata({
|
||||||
title: i18n.ts.reaction,
|
title: i18n.ts.reaction,
|
||||||
icon: "ph-smiley ph-bold ph-lg",
|
icon: "ph-smiley ph-bold ph-lg",
|
||||||
action: {
|
|
||||||
icon: "ph-eye ph-bold ph-lg",
|
|
||||||
handler: preview,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" module>
|
||||||
.zoaiodol {
|
.root {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
|
|
||||||
|
@ -270,10 +255,12 @@ definePageMetadata({
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> .add {
|
.add {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
margin-left: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch, onMounted } from "vue";
|
import { computed, watch, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import XNotes from "@/components/MkNotes.vue";
|
import XNotes from "@/components/MkNotes.vue";
|
||||||
import XUserList from "@/components/MkUserList.vue";
|
import XUserList from "@/components/MkUserList.vue";
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, onMounted } from "vue";
|
import { computed, ref, onMounted } from "vue";
|
||||||
import { Virtual } from "swiper";
|
import { Virtual } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||||
import XTutorial from "@/components/MkTutorialDialog.vue";
|
import XTutorial from "@/components/MkTutorialDialog.vue";
|
||||||
import XTimeline from "@/components/MkTimeline.vue";
|
import XTimeline from "@/components/MkTimeline.vue";
|
||||||
|
|
|
@ -26,8 +26,9 @@
|
||||||
class="banner"
|
class="banner"
|
||||||
:style="{
|
:style="{
|
||||||
backgroundImage: `url('${user.bannerUrl}')`,
|
backgroundImage: `url('${user.bannerUrl}')`,
|
||||||
'--backgroundImageStatic': defaultStore
|
'--backgroundImageStatic':
|
||||||
.state.useBlurEffect && user.bannerUrl
|
defaultStore.state.useBlurEffect &&
|
||||||
|
user.bannerUrl
|
||||||
? `url('${getStaticImageUrl(
|
? `url('${getStaticImageUrl(
|
||||||
user.bannerUrl,
|
user.bannerUrl,
|
||||||
)}')`
|
)}')`
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
import { getBlurHashAverageColor } from "fast-blurhash";
|
||||||
|
|
||||||
|
function rgbToHex(rgb: number[]): string {
|
||||||
|
return `#${rgb
|
||||||
|
.map((x) => {
|
||||||
|
const hex = x.toString(16);
|
||||||
|
return hex.length === 1 ? `0${hex}` : hex;
|
||||||
|
})
|
||||||
|
.join("")}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function extractAvgColorFromBlurhash(hash: string) {
|
export function extractAvgColorFromBlurhash(hash: string) {
|
||||||
return typeof hash === "string"
|
return typeof hash === "string"
|
||||||
? `#${[...hash.slice(2, 6)]
|
? rgbToHex(getBlurHashAverageColor(hash))
|
||||||
.map((x) =>
|
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".indexOf(
|
|
||||||
x,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.reduce((a, c) => a * 83 + c, 0)
|
|
||||||
.toString(16)
|
|
||||||
.padStart(6, "0")}`
|
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,11 @@ a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
text-decoration-color: transparent;
|
||||||
|
transition: text-decoration-color 0.2s;
|
||||||
|
&:hover {
|
||||||
|
text-decoration-color: currentColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,24 +635,26 @@ hr {
|
||||||
._link {
|
._link {
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
text-decoration: none !important;
|
text-underline-offset: 0.2em;
|
||||||
|
|
||||||
&::before, &::after {
|
// &::before,
|
||||||
content: "";
|
// &::after {
|
||||||
position: absolute;
|
// content: "";
|
||||||
bottom: 0;
|
// position: absolute;
|
||||||
left: 0;
|
// bottom: 0;
|
||||||
width: 0%;
|
// left: 0;
|
||||||
border-bottom: 1px solid var(--link);
|
// width: 0%;
|
||||||
transition: 0.3s ease-in-out;
|
// border-bottom: 1px solid currentColor;
|
||||||
}
|
// transition: 0.3s ease-in-out;
|
||||||
&::before {
|
// }
|
||||||
width: 100%;
|
// &::before {
|
||||||
opacity: .4;
|
// width: 100%;
|
||||||
}
|
// opacity: 0.4;
|
||||||
&:hover:after, &:focus:after {
|
// }
|
||||||
width: 100%;
|
// &:hover:after,
|
||||||
}
|
// &:focus:after {
|
||||||
|
// width: 100%;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
._caption {
|
._caption {
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<MkA
|
<MkA
|
||||||
v-click-anime
|
v-click-anime
|
||||||
v-tooltip.noDelay.right="i18n.ts.timeline"
|
v-tooltip.noDelay.right="i18n.ts.timeline"
|
||||||
class="nav-item index"
|
class="item index"
|
||||||
active-class="active"
|
active-class="active"
|
||||||
to="/"
|
to="/"
|
||||||
exact
|
exact
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
v-tooltip.noDelay.right="
|
v-tooltip.noDelay.right="
|
||||||
i18n.ts[navbarItemDef[item].title]
|
i18n.ts[navbarItemDef[item].title]
|
||||||
"
|
"
|
||||||
class="nav-item _button"
|
class="item _button"
|
||||||
:class="[item, { active: navbarItemDef[item].active }]"
|
:class="[item, { active: navbarItemDef[item].active }]"
|
||||||
active-class="active"
|
active-class="active"
|
||||||
:to="navbarItemDef[item].to"
|
:to="navbarItemDef[item].to"
|
||||||
|
@ -66,9 +66,6 @@
|
||||||
<span
|
<span
|
||||||
v-if="navbarItemDef[item].indicated"
|
v-if="navbarItemDef[item].indicated"
|
||||||
class="indicator"
|
class="indicator"
|
||||||
:class="{
|
|
||||||
animateIndicator: $store.state.animation,
|
|
||||||
}"
|
|
||||||
><i class="icon ph-circle ph-fill"></i
|
><i class="icon ph-circle ph-fill"></i
|
||||||
></span>
|
></span>
|
||||||
</component>
|
</component>
|
||||||
|
@ -78,7 +75,7 @@
|
||||||
v-if="$i.isAdmin || $i.isModerator"
|
v-if="$i.isAdmin || $i.isModerator"
|
||||||
v-click-anime
|
v-click-anime
|
||||||
v-tooltip.noDelay.right="i18n.ts.controlPanel"
|
v-tooltip.noDelay.right="i18n.ts.controlPanel"
|
||||||
class="nav-item _button"
|
class="item _button"
|
||||||
active-class="active"
|
active-class="active"
|
||||||
to="/admin"
|
to="/admin"
|
||||||
>
|
>
|
||||||
|
@ -91,7 +88,6 @@
|
||||||
updateAvailable
|
updateAvailable
|
||||||
"
|
"
|
||||||
class="indicator"
|
class="indicator"
|
||||||
:class="{ animateIndicator: $store.state.animation }"
|
|
||||||
></span
|
></span
|
||||||
><i class="icon ph-door ph-bold ph-fw ph-lg"></i
|
><i class="icon ph-door ph-bold ph-fw ph-lg"></i
|
||||||
><span class="text">{{ i18n.ts.controlPanel }}</span>
|
><span class="text">{{ i18n.ts.controlPanel }}</span>
|
||||||
|
@ -99,24 +95,21 @@
|
||||||
<button
|
<button
|
||||||
v-click-anime
|
v-click-anime
|
||||||
v-tooltip.noDelay.right="i18n.ts.more"
|
v-tooltip.noDelay.right="i18n.ts.more"
|
||||||
class="nav-item _button"
|
class="item _button"
|
||||||
@click="more"
|
@click="more"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="icon ph-dots-three-outline ph-bold ph-fw ph-lg"
|
class="icon ph-dots-three-outline ph-bold ph-fw ph-lg"
|
||||||
></i
|
></i
|
||||||
><span class="text">{{ i18n.ts.more }}</span>
|
><span class="text">{{ i18n.ts.more }}</span>
|
||||||
<span
|
<span v-if="otherMenuItemIndicated" class="indicator"
|
||||||
v-if="otherMenuItemIndicated"
|
|
||||||
class="indicator"
|
|
||||||
:class="{ animateIndicator: $store.state.animation }"
|
|
||||||
><i class="icon ph-circle ph-fill"></i
|
><i class="icon ph-circle ph-fill"></i
|
||||||
></span>
|
></span>
|
||||||
</button>
|
</button>
|
||||||
<MkA
|
<MkA
|
||||||
v-click-anime
|
v-click-anime
|
||||||
v-tooltip.noDelay.right="i18n.ts.settings"
|
v-tooltip.noDelay.right="i18n.ts.settings"
|
||||||
class="nav-item _button"
|
class="item _button"
|
||||||
active-class="active"
|
active-class="active"
|
||||||
to="/settings"
|
to="/settings"
|
||||||
>
|
>
|
||||||
|
@ -127,7 +120,7 @@
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<button
|
<button
|
||||||
v-tooltip.noDelay.right="i18n.ts.note"
|
v-tooltip.noDelay.right="i18n.ts.note"
|
||||||
class="nav-item _button post"
|
class="item _button post"
|
||||||
data-cy-open-post-form
|
data-cy-open-post-form
|
||||||
@click="os.post"
|
@click="os.post"
|
||||||
>
|
>
|
||||||
|
@ -272,125 +265,6 @@ function more(ev: MouseEvent) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-inline: 30px;
|
|
||||||
line-height: 2.85rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: var(--navFg);
|
|
||||||
|
|
||||||
&:before, &.post::after {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
width: calc(100% - 34px);
|
|
||||||
height: 100%;
|
|
||||||
margin: auto;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
border-radius: 999px;
|
|
||||||
background: var(--accentedBg);
|
|
||||||
opacity: 0;
|
|
||||||
z-index: -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .icon {
|
|
||||||
position: relative;
|
|
||||||
width: 32px;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .indicator {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 20px;
|
|
||||||
color: var(--navIndicator);
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .animateIndicator {
|
|
||||||
animation: blink 1s infinite;
|
|
||||||
}
|
|
||||||
> .text {
|
|
||||||
position: relative;
|
|
||||||
font-size: 0.9em;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus-within {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--navHoverFg);
|
|
||||||
transition: color 0.4s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: var(--navActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus-within,
|
|
||||||
&.active {
|
|
||||||
color: var(--accent);
|
|
||||||
opacity: 1;
|
|
||||||
transition: color 0.4s, opacity 0.4s;
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.post {
|
|
||||||
padding-inline: 0;
|
|
||||||
color: var(--fgOnAccent);
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--buttonGradateA),
|
|
||||||
var(--buttonGradateB)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
background: var(--accentLighten) !important;
|
|
||||||
opacity: 0;
|
|
||||||
z-index: -1;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus-within,
|
|
||||||
&.active {
|
|
||||||
&::after {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .icon,
|
|
||||||
> .text {
|
|
||||||
position: relative;
|
|
||||||
left: 3rem;
|
|
||||||
margin: 0;
|
|
||||||
width: auto;
|
|
||||||
color: var(--fgOnAccent);
|
|
||||||
transform: translateY(0em);
|
|
||||||
}
|
|
||||||
|
|
||||||
> .text {
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.iconOnly) {
|
&:not(.iconOnly) {
|
||||||
> .body {
|
> .body {
|
||||||
margin-left: -200px;
|
margin-left: -200px;
|
||||||
|
@ -431,6 +305,57 @@ function more(ev: MouseEvent) {
|
||||||
> .bottom {
|
> .bottom {
|
||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
|
|
||||||
|
> .post {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
color: var(--fgOnAccent);
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: calc(100% - 38px);
|
||||||
|
height: 100%;
|
||||||
|
margin: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--buttonGradateA),
|
||||||
|
var(--buttonGradateB)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
|
&.active {
|
||||||
|
&:before {
|
||||||
|
background: var(--accentLighten);
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon,
|
||||||
|
> .text {
|
||||||
|
position: relative;
|
||||||
|
left: 3rem;
|
||||||
|
color: var(--fgOnAccent);
|
||||||
|
transform: translateY(0em);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> .instance {
|
> .instance {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -468,6 +393,75 @@ function more(ev: MouseEvent) {
|
||||||
margin: 16px 16px;
|
margin: 16px 16px;
|
||||||
border-top: solid 0.5px var(--divider);
|
border-top: solid 0.5px var(--divider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 30px;
|
||||||
|
line-height: 2.85rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--navFg);
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
position: relative;
|
||||||
|
width: 32px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 20px;
|
||||||
|
color: var(--navIndicator);
|
||||||
|
font-size: 8px;
|
||||||
|
animation: blink 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.9em;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--navHoverFg);
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--navActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
|
&.active {
|
||||||
|
color: var(--accent);
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: calc(100% - 34px);
|
||||||
|
height: 100%;
|
||||||
|
margin: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--accentedBg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,6 +493,52 @@ function more(ev: MouseEvent) {
|
||||||
> .bottom {
|
> .bottom {
|
||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
|
|
||||||
|
> .post {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 52px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 52px;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
border-radius: 100%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--buttonGradateA),
|
||||||
|
var(--buttonGradateB)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within,
|
||||||
|
&.active {
|
||||||
|
&:before {
|
||||||
|
background: var(--accentLighten);
|
||||||
|
transition: all 0.4s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
position: relative;
|
||||||
|
color: var(--fgOnAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
> .help {
|
> .help {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -537,11 +577,12 @@ function more(ev: MouseEvent) {
|
||||||
border-top: solid 0.5px var(--divider);
|
border-top: solid 0.5px var(--divider);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
> .item {
|
||||||
}
|
display: block;
|
||||||
.nav-item {
|
position: relative;
|
||||||
padding: 1.1rem 0;
|
padding: 1.1rem 0;
|
||||||
margin-bottom: 0.2rem;
|
margin-bottom: 0.2rem;
|
||||||
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
|
@ -561,32 +602,42 @@ function more(ev: MouseEvent) {
|
||||||
left: 24px;
|
left: 24px;
|
||||||
color: var(--navIndicator);
|
color: var(--navIndicator);
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
}
|
|
||||||
|
|
||||||
> .animateIndicator {
|
|
||||||
animation: blink 1s infinite;
|
animation: blink 1s infinite;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.post {
|
&:hover,
|
||||||
width: 100%;
|
&:focus-within,
|
||||||
height: 52px;
|
&.active {
|
||||||
margin-bottom: 16px;
|
text-decoration: none;
|
||||||
&:before, &::after {
|
color: var(--accent);
|
||||||
inset: 0;
|
transition: all 0.4s ease;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
aspect-ratio: 1;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
width: 52px;
|
position: absolute;
|
||||||
aspect-ratio: 1/1;
|
top: 0;
|
||||||
}
|
left: 0;
|
||||||
> .icon {
|
right: 0;
|
||||||
left: unset;
|
bottom: 0;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--accentedBg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .icon,
|
||||||
> .text {
|
> .text {
|
||||||
display: none;
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item {
|
.item {
|
||||||
outline: none;
|
outline: none;
|
||||||
&:focus-visible:before {
|
&:focus-visible:before {
|
||||||
outline: auto;
|
outline: auto;
|
||||||
|
|
|
@ -23,9 +23,9 @@ const extensions = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export default defineConfig(({ command, mode }) => {
|
export default defineConfig(({ command, mode }) => {
|
||||||
fs.mkdirSync(__dirname + "/../../built", { recursive: true });
|
fs.mkdirSync(`${__dirname}/../../built`, { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
__dirname + "/../../built/meta.json",
|
`${__dirname}/../../built/meta.json`,
|
||||||
JSON.stringify({ version: meta.version }),
|
JSON.stringify({ version: meta.version }),
|
||||||
"utf-8",
|
"utf-8",
|
||||||
);
|
);
|
||||||
|
@ -40,15 +40,16 @@ export default defineConfig(({ command, mode }) => {
|
||||||
pluginJson5(),
|
pluginJson5(),
|
||||||
viteCompression({
|
viteCompression({
|
||||||
algorithm: "brotliCompress",
|
algorithm: "brotliCompress",
|
||||||
|
verbose: false,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions,
|
extensions,
|
||||||
alias: {
|
alias: {
|
||||||
"@/": __dirname + "/src/",
|
"@/": `${__dirname}/src/`,
|
||||||
"/client-assets/": __dirname + "/assets/",
|
"/client-assets/": `${__dirname}/assets/`,
|
||||||
"/static-assets/": __dirname + "/../backend/assets/",
|
"/static-assets/": `${__dirname}/../backend/assets/`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ export default defineConfig(({ command, mode }) => {
|
||||||
},
|
},
|
||||||
cssCodeSplit: true,
|
cssCodeSplit: true,
|
||||||
assetsInlineLimit: 0,
|
assetsInlineLimit: 0,
|
||||||
outDir: __dirname + "/../../built/_client_dist_",
|
outDir: `${__dirname}/../../built/_client_dist_`,
|
||||||
assetsDir: ".",
|
assetsDir: ".",
|
||||||
emptyOutDir: false,
|
emptyOutDir: false,
|
||||||
sourcemap: process.env.NODE_ENV === "development",
|
sourcemap: process.env.NODE_ENV === "development",
|
||||||
|
@ -94,5 +95,7 @@ export default defineConfig(({ command, mode }) => {
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
auto: true,
|
auto: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logLevel: "warn",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1541,7 +1541,7 @@ export default class Misskey implements MegalodonInterface {
|
||||||
if (!res.data || (res.data != 'public' && res.data != 'home' && res.data != 'followers' && res.data != 'specified'))
|
if (!res.data || (res.data != 'public' && res.data != 'home' && res.data != 'followers' && res.data != 'specified'))
|
||||||
return 'public';
|
return 'public';
|
||||||
return this.converter.visibility(res.data);
|
return this.converter.visibility(res.data);
|
||||||
});
|
}).catch(_ => 'public')
|
||||||
}
|
}
|
||||||
|
|
||||||
public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> {
|
public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> {
|
||||||
|
|
|
@ -156,7 +156,7 @@ namespace MisskeyAPI {
|
||||||
id: u.id,
|
id: u.id,
|
||||||
username: u.username,
|
username: u.username,
|
||||||
acct: acct,
|
acct: acct,
|
||||||
display_name: u.name,
|
display_name: u.name || u.username,
|
||||||
locked: u.isLocked,
|
locked: u.isLocked,
|
||||||
created_at: u.createdAt,
|
created_at: u.createdAt,
|
||||||
followers_count: u.followersCount,
|
followers_count: u.followersCount,
|
||||||
|
|
|
@ -86,6 +86,13 @@
|
||||||
"@irfan@calckey.social",
|
"@irfan@calckey.social",
|
||||||
"@dvd@dvd.chat",
|
"@dvd@dvd.chat",
|
||||||
"@charlie2alpha@electricrequiem.com",
|
"@charlie2alpha@electricrequiem.com",
|
||||||
|
"@arndot@layer8.space",
|
||||||
|
"@ryan@c.ryanccn.dev",
|
||||||
|
"@lapastora_deprova@calckey.social",
|
||||||
|
"@rameez@calckey.social",
|
||||||
|
"@dracoling@firetribe.org",
|
||||||
|
"@Space6host@calckey.social",
|
||||||
|
"@zakalwe@plasmatrap.com",
|
||||||
"\nInterkosmos Link"
|
"\nInterkosmos Link"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
1679
pnpm-lock.yaml
1679
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue