mirror of
https://github.com/sim1222/misskey.git
synced 2025-04-29 02:37:22 +09:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
commit
235f12c1d8
@ -3,13 +3,15 @@
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "app",
|
||||
"workspaceFolder": "/workspace",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers-contrib/features/pnpm:2": {}
|
||||
},
|
||||
"forwardPorts": [3000],
|
||||
"postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"eg2.vscode-npm-script",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
|
@ -16,7 +16,7 @@ services:
|
||||
- external_network
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
restart: unless-stopped
|
||||
image: redis:7-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
|
@ -4,6 +4,7 @@ set -xe
|
||||
|
||||
sudo chown -R node /workspace
|
||||
git submodule update --init
|
||||
pnpm config set store-dir /home/node/.local/share/pnpm/store
|
||||
pnpm install --frozen-lockfile
|
||||
cp .devcontainer/devcontainer.yml .config/default.yml
|
||||
pnpm build
|
||||
|
59
.github/workflows/test-backend.yml
vendored
Normal file
59
.github/workflows/test-backend.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: Test (backend)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
jest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:6
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
run_install: false
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Test
|
||||
run: pnpm jest-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
@ -1,4 +1,4 @@
|
||||
name: Test
|
||||
name: Test (frontend)
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -8,57 +8,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
jest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:13
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:6
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
run_install: false
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Test
|
||||
run: pnpm jest-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
|
||||
e2e:
|
||||
cypress:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@ -1,7 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"editorconfig.editorconfig",
|
||||
"eg2.vscode-npm-script",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -5,5 +5,6 @@
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"files.associations": {
|
||||
"*.test.ts": "typescript"
|
||||
}
|
||||
},
|
||||
"jest.autoRun": "off"
|
||||
}
|
21
CHANGELOG.md
21
CHANGELOG.md
@ -13,13 +13,28 @@ You should also include the user name that made the change.
|
||||
## 13.x.x (unreleased)
|
||||
|
||||
### Improvements
|
||||
- クリップ、チャンネルページに共有ボタンを追加
|
||||
- ドライブの「URLからアップロード」で、content-dispositionのfilenameがあればそれをファイル名に
|
||||
- サーバーのパフォーマンスを改善
|
||||
- enhance(client): DM作成時にメンションも含むように
|
||||
|
||||
### Bugfixes
|
||||
-
|
||||
|
||||
## 13.9.2 (2023/03/06)
|
||||
|
||||
### Improvements
|
||||
- クリップ、チャンネルページに共有ボタンを追加
|
||||
- チャンネルでタイムライン上部に投稿フォームを表示するかどうかのオプションを追加
|
||||
- ブラウザでメディアプロキシ(/proxy)からファイルを保存した際に、なるべくオリジナルのファイル名を継承するように
|
||||
- ドライブの「URLからアップロード」で、content-dispositionのfilenameがあればそれをファイル名に
|
||||
- Identiconがローカルとリモートで同じになるように
|
||||
- これまでのIdenticonは異なる画像になります
|
||||
- サーバーのパフォーマンスを改善
|
||||
|
||||
### Bugfixes
|
||||
- ロールの権限で「一般ユーザー」のロールがいきなり設定できない問題を修正
|
||||
- ユーザーページのバッジ表示を適切に折り返すように @arrow2nd
|
||||
- fix(client): みつけるのロール一覧でコンディショナルロールが含まれるのを修正
|
||||
- macOSでDev Containerが動作しない問題を修正 @RyotaK
|
||||
|
||||
## 13.9.1 (2023/03/03)
|
||||
|
||||
### Bugfixes
|
||||
|
@ -15,7 +15,7 @@ Before creating an issue, please check the following:
|
||||
- To avoid duplication, please search for similar issues before creating a new issue.
|
||||
- Do not use Issues to ask questions or troubleshooting.
|
||||
- Issues should only be used to feature requests, suggestions, and bug tracking.
|
||||
- Please ask questions or troubleshooting in the [Misskey Forum](https://forum.misskey.io/) or [Discord](https://discord.gg/Wp8gVStHW3).
|
||||
- Please ask questions or troubleshooting in ~~the [Misskey Forum](https://forum.misskey.io/)~~ [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3).
|
||||
|
||||
> **Warning**
|
||||
> Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged.
|
||||
|
@ -65,8 +65,8 @@ RUN apt-get update \
|
||||
&& corepack enable \
|
||||
&& groupadd -g "${GID}" misskey \
|
||||
&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
|
||||
&& find / -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
|
||||
&& find / -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
|
||||
&& find / -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
|
||||
&& find / -type d -path /proc -prune -o -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists
|
||||
|
||||
|
@ -52,12 +52,25 @@ describe('After setup instance', () => {
|
||||
cy.intercept('POST', '/api/signup').as('signup');
|
||||
|
||||
cy.get('[data-cy-signup]').click();
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-username] input').type('alice');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-submit]').click();
|
||||
|
||||
cy.wait('@signup');
|
||||
|
||||
cy.visitHome();
|
||||
|
||||
// ユーザー名が重複している場合の挙動確認
|
||||
cy.get('[data-cy-signup]').click();
|
||||
cy.get('[data-cy-signup-username] input').type('alice');
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -345,7 +345,7 @@ basicInfo: "Grundlegende Informationen"
|
||||
pinnedUsers: "Angeheftete Benutzer"
|
||||
pinnedUsersDescription: "Gib durch Leerzeichen getrennte Benutzer an, die an die \"Erkunden\"-Seite angeheftet werden sollen."
|
||||
pinnedPages: "Angeheftete Seiten"
|
||||
pinnedPagesDescription: "Gib durch Leerzeilen getrennte Pfäde zu Seiten an, die an die Startseite dieser Instanz angeheftet werden sollen.\n"
|
||||
pinnedPagesDescription: "Gib durch Leerzeilen getrennte Pfade zu Seiten an, die an die Startseite dieser Instanz angeheftet werden sollen."
|
||||
pinnedClipId: "ID des anzuheftenden Clips"
|
||||
pinnedNotes: "Angeheftete Notizen"
|
||||
hcaptcha: "hCaptcha"
|
||||
@ -404,7 +404,7 @@ securityKey: "Sicherheitsschlüssel"
|
||||
lastUsed: "Zuletzt benutzt"
|
||||
lastUsedAt: "Zuletzt verwendet: {t}"
|
||||
unregister: "Deaktivieren"
|
||||
passwordLessLogin: "Passwortloses Anmelden einrichten"
|
||||
passwordLessLogin: "Passwortloses Anmelden"
|
||||
passwordLessLoginDescription: "Ermöglicht passwortfreies Einloggen, nur via Security-Token oder Passkey"
|
||||
resetPassword: "Passwort zurücksetzen"
|
||||
newPasswordIs: "Das neue Passwort ist „{password}“"
|
||||
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "Bei Upload auf \"public-read\" stellen"
|
||||
serverLogs: "Serverprotokolle"
|
||||
deleteAll: "Alle löschen"
|
||||
showFixedPostForm: "Bereich zum Schreiben neuer Notizen am Anfang der Chronik anzeigen"
|
||||
showFixedPostFormInChannel: "Bereich zum Schreiben neuer Notizen am Anfang der Chronik anzeigen (Kanäle)"
|
||||
newNoteRecived: "Es gibt neue Notizen"
|
||||
sounds: "Töne"
|
||||
sound: "Töne"
|
||||
@ -955,6 +956,9 @@ exploreOtherServers: "Eine andere Instanz finden"
|
||||
letsLookAtTimeline: "Die Chronik durchstöbern"
|
||||
disableFederationWarn: "Dies deaktiviert Föderation, aber alle Notizen bleiben, sofern nicht umgestellt, öffentlich. In den meisten Fällen wird diese Option nicht benötigt."
|
||||
invitationRequiredToRegister: "Diese Instanz ist einladungsbasiert. Du musst einen validen Einladungscode eingeben, um dich zu registrieren."
|
||||
emailNotSupported: "Diese Instanz unterstützt das Versenden von Emails nicht"
|
||||
postToTheChannel: "In Kanal senden"
|
||||
cannotBeChangedLater: "Kann später nicht mehr geändert werden."
|
||||
_achievements:
|
||||
earnedAt: "Freigeschaltet am"
|
||||
_types:
|
||||
@ -1163,7 +1167,7 @@ _achievements:
|
||||
description: "Du hast hier geklickt"
|
||||
_justPlainLucky:
|
||||
title: "Pures Glück"
|
||||
description: "Kann alle 10 Sekunden mit einer Warscheinlichkeit von 0.01% erhalten werden"
|
||||
description: "Kann alle 10 Sekunden mit einer Warscheinlichkeit von 0.005% erhalten werden"
|
||||
_setNameToSyuilo:
|
||||
title: "Gottkomplex"
|
||||
description: "Setze deinen Namen auf \"syuilo\""
|
||||
@ -1510,7 +1514,7 @@ _2fa:
|
||||
step2Url: "Nutzt du ein Desktopprogramm kannst du alternativ diese URL eingeben:"
|
||||
step3Title: "Authentifizierungsscode eingeben"
|
||||
step3: "Gib zum Abschluss den Token ein, der von deiner App angezeigt wird."
|
||||
step4: "Alle folgenden Anmeldungsversuche werden ab sofort die Eingabe eines solchen Tokens benötigen."
|
||||
step4: "Alle folgenden Anmeldeversuche werden ab sofort die Eingabe eines solchen Tokens benötigen."
|
||||
securityKeyNotSupported: "Dein Browser unterstützt keine Security-Tokens."
|
||||
registerTOTPBeforeKey: "Um einen Security-Token oder einen Passkey zu registrieren, musst du zuerst eine Authentifizierungs-App registrieren."
|
||||
securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Anmeldung mit Hilfe eines FIDO2-kompatiblen Hardware-Sicherheitsschlüssels einrichten."
|
||||
|
@ -197,7 +197,7 @@ clearQueueConfirmText: "Any undelivered notes remaining in the queue will not be
|
||||
clearCachedFiles: "Clear cache"
|
||||
clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?"
|
||||
blockedInstances: "Blocked Instances"
|
||||
blockedInstancesDescription: "List the hostnames of the instances that you want to block. Listed instances will no longer be able to communicate with this instance."
|
||||
blockedInstancesDescription: "List the hostnames of the instances that you want to block separated by linebreaks. Listed instances will no longer be able to communicate with this instance."
|
||||
muteAndBlock: "Mutes and Blocks"
|
||||
mutedUsers: "Muted users"
|
||||
blockedUsers: "Blocked users"
|
||||
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "Set \"public-read\" on upload"
|
||||
serverLogs: "Server logs"
|
||||
deleteAll: "Delete all"
|
||||
showFixedPostForm: "Display the posting form at the top of the timeline"
|
||||
showFixedPostFormInChannel: "Display the posting form at the top of the timeline (Channels)"
|
||||
newNoteRecived: "There are new notes"
|
||||
sounds: "Sounds"
|
||||
sound: "Sounds"
|
||||
@ -955,6 +956,9 @@ exploreOtherServers: "Look for another instance"
|
||||
letsLookAtTimeline: "Have a look at the timeline"
|
||||
disableFederationWarn: "This will disable federation, but posts will continue to be public unless set otherwise. You usually do not need to use this setting."
|
||||
invitationRequiredToRegister: "This instance is invite-only. You must enter a valid invite code sign up."
|
||||
emailNotSupported: "This instance does not support sending emails"
|
||||
postToTheChannel: "Post to channel"
|
||||
cannotBeChangedLater: "This cannot be changed later."
|
||||
_achievements:
|
||||
earnedAt: "Unlocked at"
|
||||
_types:
|
||||
@ -1182,7 +1186,7 @@ _achievements:
|
||||
_loggedInOnNewYearsDay:
|
||||
title: "Happy New Year!"
|
||||
description: "Logged in on the first day of the year"
|
||||
flavor: "To another great year!"
|
||||
flavor: "To another great year on this instance"
|
||||
_cookieClicked:
|
||||
title: "A game in which you click cookies"
|
||||
description: "Clicked the cookie"
|
||||
|
@ -54,8 +54,8 @@ copyUsername: "Copia nome utente"
|
||||
searchUser: "Cerca utente"
|
||||
reply: "Rispondi"
|
||||
loadMore: "Mostra di più"
|
||||
showMore: "Mostra di più"
|
||||
showLess: "Chiudi"
|
||||
showMore: "Espandi"
|
||||
showLess: "Comprimi"
|
||||
youGotNewFollower: "Ha iniziato a seguirti"
|
||||
receiveFollowRequest: "Hai ricevuto una richiesta di follow"
|
||||
followRequestAccepted: "Richiesta di follow accettata"
|
||||
@ -76,7 +76,7 @@ noLists: "Nessuna lista"
|
||||
note: "Nota"
|
||||
notes: "Note"
|
||||
following: "Follow"
|
||||
followers: "Followers"
|
||||
followers: "Follower"
|
||||
followsYou: "Ti segue"
|
||||
createList: "Aggiungi una nuova lista"
|
||||
manageLists: "Gestisci liste"
|
||||
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "Imposta \"visibilità pubblica\" al momento di cari
|
||||
serverLogs: "Log del server"
|
||||
deleteAll: "Cancella cronologia"
|
||||
showFixedPostForm: "Visualizzare la finestra di pubblicazione in cima alla timeline"
|
||||
showFixedPostFormInChannel: "Per i canali, mostra il modulo di pubblicazione in cima alla timeline"
|
||||
newNoteRecived: "Vedi le nuove note"
|
||||
sounds: "Impostazioni suoni"
|
||||
sound: "Impostazioni suoni"
|
||||
@ -558,7 +559,7 @@ visibility: "Visibilità"
|
||||
poll: "Sondaggio"
|
||||
useCw: "Nascondere media"
|
||||
enablePlayer: "Apri in lettore video"
|
||||
disablePlayer: "Chiudi lettore video"
|
||||
disablePlayer: "Chiudi il lettore"
|
||||
expandTweet: "Espandi tweet"
|
||||
themeEditor: "Editor di temi"
|
||||
description: "Descrizione"
|
||||
@ -955,6 +956,9 @@ exploreOtherServers: "Trova altre istanze"
|
||||
letsLookAtTimeline: "Sbircia la timeline"
|
||||
disableFederationWarn: "Disabilita la federazione. Questo cambiamento non rende le pubblicazioni private. Di solito non è necessario abilitare questa opzione."
|
||||
invitationRequiredToRegister: "L'accesso a questo nodo è solo ad invito. Devi inserire un codice d'invito valido. Puoi richiedere un codice all'amministratore."
|
||||
emailNotSupported: "L'istanza non supporta l'invio di email"
|
||||
postToTheChannel: "Pubblica sul canale"
|
||||
cannotBeChangedLater: "Non sarà più modificabile"
|
||||
_achievements:
|
||||
earnedAt: "Data di conseguimento"
|
||||
_types:
|
||||
@ -1613,7 +1617,7 @@ _widgets:
|
||||
clicker: "Cliccaggio"
|
||||
_cw:
|
||||
hide: "Nascondere"
|
||||
show: "Mostra di più"
|
||||
show: "Apri..."
|
||||
chars: "{count} caratteri"
|
||||
files: "{count} file"
|
||||
_poll:
|
||||
|
@ -960,6 +960,7 @@ disableFederationWarn: "連合が無効になっています。無効にして
|
||||
invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。"
|
||||
emailNotSupported: "このサーバーではメール配信はサポートされていません"
|
||||
postToTheChannel: "チャンネルに投稿"
|
||||
cannotBeChangedLater: "後から変更できません。"
|
||||
|
||||
_achievements:
|
||||
earnedAt: "獲得日時"
|
||||
|
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "アップロードした時に'public-read'を設
|
||||
serverLogs: "サーバーログ"
|
||||
deleteAll: "全て削除してや"
|
||||
showFixedPostForm: "タイムラインの上の方で投稿できるようにやってくれへん?"
|
||||
showFixedPostFormInChannel: "タイムラインの上の方で投稿できるようにするわ(チャンネル)"
|
||||
newNoteRecived: "新しいノートがあるで"
|
||||
sounds: "サウンド"
|
||||
sound: "サウンド"
|
||||
@ -909,7 +910,7 @@ subscribePushNotification: "プッシュ通知をオンにするで"
|
||||
unsubscribePushNotification: "プッシュ通知を止めるで"
|
||||
pushNotificationAlreadySubscribed: "プッシュ通知はオンになってるで"
|
||||
pushNotificationNotSupported: "ブラウザかインスタンスがプッシュ通知に対応してないみたいやで。"
|
||||
sendPushNotificationReadMessage: "通知やメッセージが既読担ったらプッシュ通知を消すで"
|
||||
sendPushNotificationReadMessage: "通知やメッセージが既読になったらプッシュ通知を消すで"
|
||||
sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」っていう表示が一瞬表示されるようになるで。端末の電池使用量が増える可能性があるで。"
|
||||
windowMaximize: "最大化"
|
||||
windowRestore: "元に戻す"
|
||||
@ -955,6 +956,9 @@ exploreOtherServers: "他のサーバー見てみる"
|
||||
letsLookAtTimeline: "タイムライン見てみーや"
|
||||
disableFederationWarn: "連合が無効になっとるで。無効にしても投稿は非公開ってわけちゃうねん。大体の場合はこのオプションを有効にする必要は別にないで。"
|
||||
invitationRequiredToRegister: "今このサーバー招待制になってもうてんねん。招待コードを持っとるんやったら登録できるで。"
|
||||
emailNotSupported: "このサーバーはメール配信がサポートされてへんみたいやわ"
|
||||
postToTheChannel: "チャンネルに投稿"
|
||||
cannotBeChangedLater: "後からは変えられへんで。"
|
||||
_achievements:
|
||||
earnedAt: "貰った日ぃ"
|
||||
_types:
|
||||
@ -1072,7 +1076,7 @@ _achievements:
|
||||
description: "プロフィールを設定した"
|
||||
_markedAsCat:
|
||||
title: "吾輩は猫やねん"
|
||||
description: "アカウントがCatになってもうた"
|
||||
description: "アカウントをCatにしたった"
|
||||
flavor: "名前はまだないねん。"
|
||||
_following1:
|
||||
title: "はじめてのフォロー"
|
||||
|
@ -168,7 +168,9 @@ done: "ສຳເລັດ"
|
||||
processing: "ກຳລັງປະມວນຜົນ"
|
||||
preview: "ສະແດງເປັນຕົວຢ່າງ"
|
||||
default: "ຄ່າເລີ່ມຕົ້ນ"
|
||||
federating: "ສະຫະພັນ"
|
||||
blocked: "ບລັອກແລ້ວ "
|
||||
suspended: "ໂຈະ"
|
||||
all: "ທັງໝົດ"
|
||||
subscribing: "ສະໝັກສະມາຊິກແລັວ"
|
||||
publishing: "ການພິມເຜີຍແຜ່"
|
||||
@ -177,15 +179,35 @@ instanceFollowing: "ກຳລັງຕິດຕາມສຸດຕົວຢ່າ
|
||||
instanceFollowers: "ຜູ້ຕິດຕາມຕົວຢ່າງ"
|
||||
instanceUsers: "ຜູ້ຊົມໃຊ້ຂອງຕົວຢ່າງນີ້"
|
||||
changePassword: "ປ່ຽນລະຫັດຜ່ານ"
|
||||
security: "ຄວາມປອດໄພ"
|
||||
retypedNotMatch: "ວັດສະດຸປ້ອນບໍ່ກົງກັນ"
|
||||
currentPassword: "ລະຫັດຜ່ານປະຈຸບັນ"
|
||||
more: "ເພີ່ມເຕີມ!"
|
||||
featured: "ໄຮໄລທ໌"
|
||||
usernameOrUserId: "ຊື່ຜູ້ໃຊ້ ຫຼື id ຜູ້ໃຊ້"
|
||||
noSuchUser: "ບໍ່ພົບຜູ້ໃຊ້"
|
||||
lookup: "ຄົ້ນຫາ"
|
||||
announcements: "ປະກາດ"
|
||||
imageUrl: "URL ຮູບພາບ"
|
||||
remove: "ລຶບ"
|
||||
removed: "ລຶບແລ້ວ"
|
||||
resetAreYouSure: "ຣີເຊັດບໍ?"
|
||||
saved: "ບັນທຶກແລ້ວ"
|
||||
messaging: "ແຊ໋ດ"
|
||||
upload: "ອັບໂຫຼດ"
|
||||
keepOriginalUploading: "ຮັກສາຮູບພາບຕົ້ນສະບັບ"
|
||||
fromUrl: "ຈາກ URL"
|
||||
uploadFromUrl: "ອັບໂຫຼດຈາກ URL"
|
||||
uploadFromUrlDescription: "URL ຂອງໄຟລ໌ທີ່ທ່ານຕ້ອງການອັບໂຫລດ"
|
||||
messageRead: "ອ່ານແລ້ວ"
|
||||
startMessaging: "ເລີ່ມການສົນທະນາໃໝ່"
|
||||
nUsersRead: "ອ່ານໂດຍ {n}"
|
||||
tos: "ເງື່ອນໄຂການໃຫ້ບໍລິການ"
|
||||
start: "ເລີ່ມຕົ້ນນຳໃຊ້ເລີຍ"
|
||||
home: "ໜ້າຫຼັກ"
|
||||
images: "ຮູບພາບ"
|
||||
birthday: "ວັນເກີດ"
|
||||
yearsOld: "{age} ປີ"
|
||||
registeredDate: "ວັນທີ່ເປັນສະມາຊິກ"
|
||||
location: "ທີ່ຕັ້ງ"
|
||||
theme: "ແທ໋ມ"
|
||||
@ -193,17 +215,96 @@ light: "ສະຫວ່າງ"
|
||||
dark: "ມືດ"
|
||||
lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ"
|
||||
darkThemes: "ຮູບແບບສີສັນມືດ"
|
||||
drive: "ຂັບ"
|
||||
fileName: "ຊື່ໄຟລ໌"
|
||||
selectFile: "ເລືອກໄຟລ໌"
|
||||
selectFiles: "ເລືອກໄຟລ໌"
|
||||
selectFolder: "ເລືອກໂຟລເດີ"
|
||||
selectFolders: "ເລືອກໂຟລເດີ"
|
||||
renameFile: "ປ່ຽນຊື່ໄຟລ໌"
|
||||
folderName: "ຊື່ໂຟນເດີ"
|
||||
createFolder: "ສ້າງໂຟລເດີ"
|
||||
renameFolder: "ປ່ຽນຊື່ໂຟນເດີນີ້"
|
||||
deleteFolder: "ລົບໂຟລເດີ"
|
||||
addFile: "ເພີ່ມໄຟລ໌"
|
||||
emptyDrive: "Drive ຂອງທ່ານຫວ່າງເປົ່າ"
|
||||
emptyFolder: "ໂຟນເດີນີ້ເປົ່າຫວ່າງ"
|
||||
unableToDelete: "ບໍ່ສາມາດລົບໄດ້"
|
||||
inputNewFileName: "ໃສ່ຊື່ໄຟລ໌ໃໝ່"
|
||||
inputNewDescription: "ໃສ່ຄຳບັນຍາຍໃໝ່"
|
||||
inputNewFolderName: "ໃສ່ຊື່ໂຟນເດີໃໝ່"
|
||||
circularReferenceFolder: "ໂຟນເດີປາຍທາງແມ່ນໂຟນເດີຍ່ອຍຂອງໂຟນເດີທີ່ທ່ານຕ້ອງການຍ້າຍ"
|
||||
rename: "ປ່ຽນຊື່"
|
||||
nsfw: "NSFW"
|
||||
watch: "ເບິ່ງ"
|
||||
unwatch: "ຢຸດເບິ່ງ"
|
||||
accept: "ອະນຸຍາດ"
|
||||
reject: "ປະຕິເສດ"
|
||||
normal: "ປົກກະຕິ"
|
||||
instanceName: "ຊື່ເຊີເວີ້"
|
||||
instanceDescription: "ຄໍາອະທິບາຍຕົວຢ່າງ"
|
||||
maintainerName: "ຜູ້ດູແລ"
|
||||
maintainerEmail: "ອີເມວ admin"
|
||||
tosUrl: "ເງື່ອນໄຂການໃຫ້ບໍລິການ URL"
|
||||
thisYear: "ປີນີ້"
|
||||
thisMonth: "ເດືອນນີ້"
|
||||
today: "ມື້ນີ້"
|
||||
dayX: "ວັນ {day}"
|
||||
monthX: "ເດືອນ {month}"
|
||||
yearX: "ປີ {year}"
|
||||
pages: "ໜ້າ"
|
||||
integration: "ຄວາມສຳພັນຂອງ"
|
||||
connectService: "ເຊື່ອມຕໍ່"
|
||||
disconnectService: "ຕັດການເຊື່ອມຕໍ່"
|
||||
enableLocalTimeline: "ເປີດໃຊ້ທາມລາຍທ້ອງຖິ່ນ"
|
||||
enableGlobalTimeline: "ເປີດໃຊ້ທາມລາຍທົ່ວໂລກ"
|
||||
disablingTimelinesInfo: "ຜູ້ເບິ່ງແຍງລະບົບ ແລະຜູ້ຄວບຄຸມຈະມີການເຂົ້າເຖິງທຸກກຳນົດເວລາ, ເຖິງແມ່ນວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍຕາມ"
|
||||
registration: "ລົງທະບຽນ"
|
||||
enableRegistration: "ເປີດໃຊ້ການລົງທະບຽນຜູ້ໃຊ້ໃໝ່"
|
||||
invite: "ເຊີນ"
|
||||
driveCapacityPerLocalAccount: "ຄວາມອາດສາມາດຂັບຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ"
|
||||
driveCapacityPerRemoteAccount: "ໄດຣຟ໌ຄວາມອາດສາມາດຕໍ່ຜູ້ໃຊ້ທາງໄກ"
|
||||
pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
|
||||
userList: "ລາຍການ"
|
||||
about: "ກ່ຽວກັບ"
|
||||
aboutMisskey: "ກ່ຽວກັບ Misskey"
|
||||
administrator: "ຜູ້ບໍລິຫານ"
|
||||
share: "ແບ່ງປັນ"
|
||||
notFound: "ບໍ່ພົບ"
|
||||
cacheClear: "ລຶບລ້າງແຄສ"
|
||||
invites: "ເຊີນ"
|
||||
title: "ຫົວຂໍ້"
|
||||
text: "ຂໍ້ຄວາມ"
|
||||
enable: "ເປີດໃຊ້"
|
||||
next: "ຕໍ່ໄປ"
|
||||
invitations: "ເຊີນ"
|
||||
language: "ພາສາ"
|
||||
native: "ພາສາແມ່"
|
||||
category: "ຫມວດຫມູ່"
|
||||
tags: "ແທ໋ກ"
|
||||
createAccount: "ສ້າງບັນຊີ"
|
||||
existingAccount: "ທີ່ມີຢູ່"
|
||||
dashboard: "ໜ້າປັດ"
|
||||
local: "ທ້ອງຖິ່ນ"
|
||||
objectStorageRegion: "ພາກພື້ນ"
|
||||
sounds: "ສຽງ"
|
||||
sound: "ສຽງ"
|
||||
none: "ບໍ່ມີ"
|
||||
volume: "ລະດັບສຽງ"
|
||||
details: "ລາຍລະອຽດ"
|
||||
install: "ຕິດຕັ້ງ"
|
||||
uninstall: "ຖອນການຕິດຕັ້ງ"
|
||||
state: "ສະຖານະ"
|
||||
sort: "ຈັດຮຽງໂດຍ"
|
||||
ascendingOrder: "ນ້ອຍໄປຫາໃຫຍ່"
|
||||
descendingOrder: "ໃຫຍ່ຫານ້ອຍ"
|
||||
output: "ຜົນຜະລິດ"
|
||||
script: "ບົດຄວາມ"
|
||||
smtpHost: "ໂຮດສ"
|
||||
smtpUser: "ຊື່ຜູ້ໃຊ້"
|
||||
smtpPass: "ລະຫັດຜ່ານ"
|
||||
clearCache: "ລຶບລ້າງແຄສ"
|
||||
info: "ກ່ຽວກັບ"
|
||||
user: "ຜູ້ໃຊ້ຕ່າງໆ"
|
||||
searchByGoogle: "ຄົ້ນຫາ"
|
||||
file: "ໄຟລ໌"
|
||||
@ -244,6 +345,8 @@ _charts:
|
||||
federation: "ສະຫະພັນ"
|
||||
_timelines:
|
||||
home: "ໜ້າຫຼັກ"
|
||||
_play:
|
||||
script: "ບົດຄວາມ"
|
||||
_pages:
|
||||
blocks:
|
||||
image: "ຮູບພາບ"
|
||||
|
@ -268,7 +268,7 @@ remoteUserCaution: "เนื่องจากผู้ใช้งานรา
|
||||
activity: "กิจกรรม"
|
||||
images: "รูปภาพ"
|
||||
birthday: "วันเกิด"
|
||||
yearsOld: "{อายุ} ปี"
|
||||
yearsOld: "{age} ปี"
|
||||
registeredDate: "วันที่สมัครสมาชิก"
|
||||
location: "ตำแหน่งที่ตั้ง"
|
||||
theme: "ธีม"
|
||||
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "ตั้งค่า \"public-read\" ในกา
|
||||
serverLogs: "บันทึกของเซิร์ฟเวอร์"
|
||||
deleteAll: "ลบทั้งหมด"
|
||||
showFixedPostForm: "แสดงแบบฟอร์มการโพสต์ที่ด้านบนสุดของไทม์ไลน์"
|
||||
showFixedPostFormInChannel: "แสดงแบบฟอร์มกำลังโพสต์ที่ด้านบนของไทม์ไลน์ (แชนแนล)"
|
||||
newNoteRecived: "มีโน้ตใหม่"
|
||||
sounds: "เสียง"
|
||||
sound: "เสียง"
|
||||
@ -955,6 +956,9 @@ exploreOtherServers: "มองหาอินสแตนซ์อื่น"
|
||||
letsLookAtTimeline: "ลองดูที่ไทม์ไลน์"
|
||||
disableFederationWarn: "การดำเนินการนี้ถ้าหากจะปิดใช้งานการรวมศูนย์ แต่โพสต์ดังกล่าวนั้นจะยังคงเป็นสาธารณะต่อไป ยกเว้นแต่ว่าจะตั้งค่าเป็นอย่างอื่น โดยปกติคุณไม่จำเป็นต้องใช้การตั้งค่านี้นะ"
|
||||
invitationRequiredToRegister: "อินสแตนซ์นี้เป็นแบบรับเชิญเท่านั้น คุณต้องป้อนรหัสเชิญที่ถูกต้องถึงจะลงทะเบียนได้นะค่ะ"
|
||||
emailNotSupported: "อินสแตนซ์นี้ไม่รองรับการส่งอีเมลนะค่ะ"
|
||||
postToTheChannel: "โพสต์ลงช่อง"
|
||||
cannotBeChangedLater: "สิ่งนี้ไม่สามารถเปลี่ยนแปลงได้ในภายหลังนะ"
|
||||
_achievements:
|
||||
earnedAt: "ได้รับเมื่อ"
|
||||
_types:
|
||||
|
@ -2,7 +2,7 @@
|
||||
_lang_: "中文(简体)"
|
||||
headlineMisskey: "通过帖子连接在一起的网络"
|
||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖文」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖文表达反馈👍\n来探索新的世界吧!🚀"
|
||||
poweredByMisskeyDescription: "{name} 由开源平台 <b>Misskey</b> 驱动(也被称为 Misskey 实例)"
|
||||
poweredByMisskeyDescription: "{name} 由开源平台 <b>Misskey</b> 驱动(也被称为 Misskey 服务器)"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜索"
|
||||
notifications: "通知"
|
||||
@ -18,7 +18,7 @@ enterUsername: "输入用户名"
|
||||
renotedBy: "由 {user} 转贴"
|
||||
noNotes: "没有帖子"
|
||||
noNotifications: "无通知"
|
||||
instance: "实例"
|
||||
instance: "服务器"
|
||||
settings: "设置"
|
||||
basicSettings: "基本设置"
|
||||
otherSettings: "其他设置"
|
||||
@ -144,7 +144,7 @@ emojiUrl: "表情符号地址"
|
||||
addEmoji: "添加表情符号"
|
||||
settingGuide: "推荐配置"
|
||||
cacheRemoteFiles: "远程文件缓存"
|
||||
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
||||
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程服务器载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
||||
flagAsBot: "这是一个机器人账号"
|
||||
flagAsBotDescription: "如果此帐户由程序控制,请启用此项。启用后,此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为,并让Misskey的内部系统将此帐户识别为机器人。"
|
||||
flagAsCat: "将这个账户设定为一只猫"
|
||||
@ -154,7 +154,7 @@ flagShowTimelineRepliesDescription: "启用时,时间线除了显示用户的
|
||||
autoAcceptFollowed: "自动允许关注者的关注"
|
||||
addAccount: "添加账户"
|
||||
loginFailed: "登录失败"
|
||||
showOnRemote: "转到所在实例显示"
|
||||
showOnRemote: "转到所在服务器显示"
|
||||
general: "常规设置"
|
||||
wallpaper: "壁纸"
|
||||
setWallpaper: "设置壁纸"
|
||||
@ -169,7 +169,7 @@ selectUser: "选择用户"
|
||||
recipient: "收件人"
|
||||
annotation: "注解"
|
||||
federation: "联合"
|
||||
instances: "实例"
|
||||
instances: "服务器"
|
||||
registeredAt: "初次观测"
|
||||
latestRequestReceivedAt: "上次收到的请求"
|
||||
latestStatus: "最后状态"
|
||||
@ -178,7 +178,7 @@ charts: "图表"
|
||||
perHour: "每小时"
|
||||
perDay: "每天"
|
||||
stopActivityDelivery: "停止发送活动"
|
||||
blockThisInstance: "阻止此实例向本实例推流"
|
||||
blockThisInstance: "阻止此服务器向本服务器推流"
|
||||
operations: "操作"
|
||||
software: "软件"
|
||||
version: "版本"
|
||||
@ -189,15 +189,15 @@ jobQueue: "作业队列"
|
||||
cpuAndMemory: "CPU和内存"
|
||||
network: "网络"
|
||||
disk: "存储"
|
||||
instanceInfo: "实例信息"
|
||||
instanceInfo: "服务器信息"
|
||||
statistics: "统计"
|
||||
clearQueue: "清除队列"
|
||||
clearQueueConfirmTitle: "确定清除队列?"
|
||||
clearQueueConfirmText: "未送达的帖子将不会送达。 通常,您不需要这样做。"
|
||||
clearCachedFiles: "清除缓存"
|
||||
clearCachedFilesConfirm: "确定要清除缓存文件?"
|
||||
blockedInstances: "被阻拦的实例"
|
||||
blockedInstancesDescription: "设定要阻拦的实例,以换行来进行分割。被阻拦的实例将无法与本实例进行交换通讯。"
|
||||
blockedInstances: "被阻拦的服务器"
|
||||
blockedInstancesDescription: "设定要阻拦的服务器,以换行来进行分割。被阻拦的服务器将无法与本服务器进行交换通讯。"
|
||||
muteAndBlock: "屏蔽/拉黑"
|
||||
mutedUsers: "已屏蔽用户"
|
||||
blockedUsers: "被拉黑的用户"
|
||||
@ -220,9 +220,9 @@ all: "全部"
|
||||
subscribing: "已订阅"
|
||||
publishing: "投递中"
|
||||
notResponding: "没有响应"
|
||||
instanceFollowing: "关注实例"
|
||||
instanceFollowers: "关注实例"
|
||||
instanceUsers: "实例用户"
|
||||
instanceFollowing: "关注服务器"
|
||||
instanceFollowers: "关注的服务器"
|
||||
instanceUsers: "服务器用户"
|
||||
changePassword: "修改密码"
|
||||
security: "安全"
|
||||
retypedNotMatch: "两次输入不一致!"
|
||||
@ -264,7 +264,7 @@ basicNotesBeforeCreateAccount: "基本注意事项"
|
||||
tos: "服务条款"
|
||||
start: "开始"
|
||||
home: "首页"
|
||||
remoteUserCaution: "由于此用户来自其它实例,显示的信息可能不完整。"
|
||||
remoteUserCaution: "由于此用户来自其它服务器,显示的信息可能不完整。"
|
||||
activity: "活动"
|
||||
images: "图片"
|
||||
birthday: "生日"
|
||||
@ -314,8 +314,8 @@ unwatch: "取消关注"
|
||||
accept: "允许"
|
||||
reject: "拒绝"
|
||||
normal: "正常"
|
||||
instanceName: "实例名称"
|
||||
instanceDescription: "实例介绍"
|
||||
instanceName: "服务器名称"
|
||||
instanceDescription: "服务器简介"
|
||||
maintainerName: "管理员名称"
|
||||
maintainerEmail: "管理员电子邮箱"
|
||||
tosUrl: "服务条款URL"
|
||||
@ -345,7 +345,7 @@ basicInfo: "基本信息"
|
||||
pinnedUsers: "置顶用户"
|
||||
pinnedUsersDescription: "在「发现」页面中使用换行标记想要置顶的用户。"
|
||||
pinnedPages: "固定页面"
|
||||
pinnedPagesDescription: "输入您要固定到实例首页的页面路径,以换行符分隔。"
|
||||
pinnedPagesDescription: "输入您要固定到服务器首页的页面路径,以换行符分隔。"
|
||||
pinnedClipId: "置顶的便签ID"
|
||||
pinnedNotes: "已置顶的帖子"
|
||||
hcaptcha: "hCaptcha"
|
||||
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "上传时设置为public-read"
|
||||
serverLogs: "服务器日志"
|
||||
deleteAll: "全部删除"
|
||||
showFixedPostForm: "在时间线顶部显示发帖框"
|
||||
showFixedPostFormInChannel: "在时间线顶部显示发帖对话框(频道)"
|
||||
newNoteRecived: "有新的帖子"
|
||||
sounds: "提示音"
|
||||
sound: "提示音"
|
||||
@ -538,7 +539,7 @@ updateRemoteUser: "更新远程用户信息"
|
||||
deleteAllFiles: "删除所有文件"
|
||||
deleteAllFilesConfirm: "要删除所有文件吗?"
|
||||
removeAllFollowing: "取消所有关注"
|
||||
removeAllFollowingDescription: "取消{host}的所有关注者。当实例不存在时执行。"
|
||||
removeAllFollowingDescription: "取消{host}的所有关注者。当服务器不再存在时执行。"
|
||||
userSuspended: "该用户已被冻结。"
|
||||
userSilenced: "该用户已被禁言。"
|
||||
yourAccountSuspendedTitle: "账户已被冻结"
|
||||
@ -635,15 +636,15 @@ abuseReported: "内容已发送。感谢您提交信息。"
|
||||
reporter: "举报者"
|
||||
reporteeOrigin: "举报来源"
|
||||
reporterOrigin: "举报者来源"
|
||||
forwardReport: "将该举报信息转发给远程实例"
|
||||
forwardReportIsAnonymous: "勾选则在远程实例上显示的举报者是匿名的系统账号,而不是您的账号。"
|
||||
forwardReport: "将该举报信息转发给远程服务器"
|
||||
forwardReportIsAnonymous: "勾选则在远程服务器上显示的举报者是匿名的系统账号,而不是您的账号。"
|
||||
send: "发送"
|
||||
abuseMarkAsResolved: "处理完毕"
|
||||
openInNewTab: "在新标签页中打开"
|
||||
openInSideView: "在侧边栏中打开"
|
||||
defaultNavigationBehaviour: "默认导航"
|
||||
editTheseSettingsMayBreakAccount: "编辑这些设置可以会损坏您的账号"
|
||||
instanceTicker: "帖子的实例信息"
|
||||
instanceTicker: "帖子的服务器来源"
|
||||
waitingFor: "等待{x}"
|
||||
random: "随机"
|
||||
system: "系统"
|
||||
@ -732,7 +733,7 @@ capacity: "容量"
|
||||
inUse: "已使用"
|
||||
editCode: "编辑代码"
|
||||
apply: "应用"
|
||||
receiveAnnouncementFromInstance: "从实例接收通知"
|
||||
receiveAnnouncementFromInstance: "从服务器接收通知"
|
||||
emailNotification: "邮件通知"
|
||||
publish: "发布"
|
||||
inChannelSearch: "频道内搜索"
|
||||
@ -760,7 +761,7 @@ active: "活动"
|
||||
offline: "离线"
|
||||
notRecommended: "不推荐"
|
||||
botProtection: "Bot防御"
|
||||
instanceBlocking: "被阻拦的实例"
|
||||
instanceBlocking: "被阻拦的服务器"
|
||||
selectAccount: "选择账户"
|
||||
switchAccount: "切换账户"
|
||||
enabled: "已启用"
|
||||
@ -844,8 +845,8 @@ themeColor: "主题颜色"
|
||||
size: "大小"
|
||||
numberOfColumn: "列数"
|
||||
searchByGoogle: "Google"
|
||||
instanceDefaultLightTheme: "实例默认浅色主题"
|
||||
instanceDefaultDarkTheme: "实例默认深色主题"
|
||||
instanceDefaultLightTheme: "服务器默认浅色主题"
|
||||
instanceDefaultDarkTheme: "服务器默认深色主题"
|
||||
instanceDefaultThemeDescription: "以对象格式键入主题代码"
|
||||
mutePeriod: "屏蔽期限"
|
||||
period: "截止时间"
|
||||
@ -898,7 +899,7 @@ cannotUploadBecauseInappropriate: "因为可能含有不适宜的内容,无法
|
||||
cannotUploadBecauseNoFreeSpace: "因为已无可用空间,无法上传。"
|
||||
beta: "测试"
|
||||
enableAutoSensitive: "自动 NSFW 识别"
|
||||
enableAutoSensitiveDescription: "如果可用,请使用机器学习在媒体上自动设置 NSFW 标志。即使关闭此功能,也可能会根据实例自动设置。"
|
||||
enableAutoSensitiveDescription: "如果可用,请使用机器学习在媒体上自动设置 NSFW 标志。即使关闭此功能,也可能会根据服务器自动设置。"
|
||||
activeEmailValidationDescription: "开启用户的电子邮件地址验证,判断它是一次性的电子邮件地址,还是可以实际通信的地址。关闭时,则只检查字符串是否正确。"
|
||||
navbar: "导航栏"
|
||||
shuffle: "随机"
|
||||
@ -908,7 +909,7 @@ pushNotification: "推送通知"
|
||||
subscribePushNotification: "启用推送通知消息"
|
||||
unsubscribePushNotification: "停用推送通知消息"
|
||||
pushNotificationAlreadySubscribed: "推送通知消息已启用"
|
||||
pushNotificationNotSupported: "浏览器或实例不支持推送通知消息"
|
||||
pushNotificationNotSupported: "浏览器或服务器不支持推送通知消息"
|
||||
sendPushNotificationReadMessage: "删除已读推送通知消息"
|
||||
sendPushNotificationReadMessageCaption: "“{emptyPushNotificationMessage}”的通知消息将会显示。您终端设备的电池消耗可能会增加。"
|
||||
windowMaximize: "最大化"
|
||||
@ -950,11 +951,14 @@ collapseRenotes: "省略显示已经看过的转发内容"
|
||||
internalServerError: "内部服务器错误"
|
||||
internalServerErrorDescription: "内部服务器发生了预期外的错误"
|
||||
copyErrorInfo: "复制错误信息"
|
||||
joinThisServer: "在本实例上注册"
|
||||
exploreOtherServers: "探索其他实例"
|
||||
joinThisServer: "在本服务器上注册"
|
||||
exploreOtherServers: "探索其他服务器"
|
||||
letsLookAtTimeline: "时间线"
|
||||
disableFederationWarn: "联合被禁用。 禁用它并不能使帖子变成私人的。 在大多数情况下,这个选项不需要被启用。"
|
||||
invitationRequiredToRegister: "此实例目前只允许拥有邀请码的人注册。"
|
||||
invitationRequiredToRegister: "此服务器目前只允许拥有邀请码的人注册。"
|
||||
emailNotSupported: "此服务器不支持发送邮件"
|
||||
postToTheChannel: "发布到频道"
|
||||
cannotBeChangedLater: "之后不能再更改。"
|
||||
_achievements:
|
||||
earnedAt: "达成时间"
|
||||
_types:
|
||||
@ -1145,7 +1149,7 @@ _achievements:
|
||||
description: "在首页时间线的流速超过20npm"
|
||||
_viewInstanceChart:
|
||||
title: "分析师"
|
||||
description: "查看了实例信息中的图表"
|
||||
description: "查看了服务器信息中的图表"
|
||||
_outputHelloWorldOnScratchpad:
|
||||
title: "Hello, world!"
|
||||
description: "在AiScript控制台中输出 hello world"
|
||||
@ -1182,7 +1186,7 @@ _achievements:
|
||||
_loggedInOnNewYearsDay:
|
||||
title: "恭贺新禧"
|
||||
description: "在元旦登入"
|
||||
flavor: "今年也请对本实例多多指教!"
|
||||
flavor: "今年也请对本服务器多多指教!"
|
||||
_cookieClicked:
|
||||
title: "点击饼干小游戏"
|
||||
description: "点击了可疑的饼干"
|
||||
@ -1197,7 +1201,7 @@ _role:
|
||||
name: "角色名称"
|
||||
description: "角色描述"
|
||||
permission: "角色权限"
|
||||
descriptionOfPermission: "<b>监察员</b>可以执行基本的审核操作。\n<b>管理员</b>可以更改实例的所有设置。"
|
||||
descriptionOfPermission: "<b>监察员</b>可以执行基本地审核操作。\n<b>管理员</b>可以更改服务器的所有设置。"
|
||||
assignTarget: "授权对象"
|
||||
descriptionOfAssignTarget: "<b>手动</b>指手动选择谁被包括在这个角色中。\n<b>符合条件</b>指设置条件以自动包括符合条件的用户。"
|
||||
manual: "手动"
|
||||
@ -1287,7 +1291,7 @@ _ad:
|
||||
_forgotPassword:
|
||||
enterEmail: "请输入您验证账号时用的电子邮箱地址,密码重置链接将发送至该邮箱上。"
|
||||
ifNoEmail: "如果您没有使用电子邮件地址进行验证,请联系管理员。"
|
||||
contactAdmin: "该实例不支持发送电子邮件。如果您想重设密码,请联系管理员。"
|
||||
contactAdmin: "该服务器不支持发送电子邮件。如果您想重设密码,请联系管理员。"
|
||||
_gallery:
|
||||
my: "我的图库"
|
||||
liked: "喜欢的图片"
|
||||
@ -1372,10 +1376,10 @@ _wordMute:
|
||||
hard: "硬屏蔽"
|
||||
mutedNotes: "被屏蔽的帖子"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "屏蔽配置实例中的所有帖子和转帖,包括实例的用户回复。"
|
||||
instanceMuteDescription: "屏蔽配置服务器中的所有帖子和转帖,包括这些服务器上的用户回复。"
|
||||
instanceMuteDescription2: "设置时用换行符来分隔"
|
||||
title: "隐藏实例已设置的帖子。"
|
||||
heading: "屏蔽实例"
|
||||
title: "隐藏服务器已设置的帖子。"
|
||||
heading: "屏蔽服务器"
|
||||
_theme:
|
||||
explore: "寻找主题"
|
||||
install: "安装主题"
|
||||
@ -1583,7 +1587,7 @@ _weekday:
|
||||
saturday: "星期六"
|
||||
_widgets:
|
||||
profile: "个人资料"
|
||||
instanceInfo: "实例信息"
|
||||
instanceInfo: "服务器信息"
|
||||
memo: "便签"
|
||||
notifications: "通知"
|
||||
timeline: "时间线"
|
||||
@ -1597,7 +1601,7 @@ _widgets:
|
||||
digitalClock: "数字时钟"
|
||||
unixClock: "UNIX时钟"
|
||||
federation: "联邦宇宙"
|
||||
instanceCloud: "实例云"
|
||||
instanceCloud: "服务器云"
|
||||
postForm: "投稿窗口"
|
||||
slideshow: "幻灯片展示"
|
||||
button: "按钮"
|
||||
@ -1648,7 +1652,7 @@ _visibility:
|
||||
specified: "指定用户"
|
||||
specifiedDescription: "仅发送至指定用户"
|
||||
disableFederation: "不参与联合"
|
||||
disableFederationDescription: "不发送到其他实例"
|
||||
disableFederationDescription: "不发送到其他服务器"
|
||||
_postForm:
|
||||
replyPlaceholder: "回复这个帖子..."
|
||||
quotePlaceholder: "引用这个帖子..."
|
||||
|
@ -506,6 +506,7 @@ objectStorageSetPublicRead: "上傳時設定為\"public-read\""
|
||||
serverLogs: "伺服器日誌"
|
||||
deleteAll: "刪除所有記錄"
|
||||
showFixedPostForm: "於時間軸頁頂顯示「發送貼文」方框"
|
||||
showFixedPostFormInChannel: "於時間軸頁頂顯示「發送貼文」方框(頻道)"
|
||||
newNoteRecived: "發現新的貼文"
|
||||
sounds: "音效"
|
||||
sound: "音效"
|
||||
@ -955,6 +956,8 @@ exploreOtherServers: "探索其他伺服器"
|
||||
letsLookAtTimeline: "看看時間軸"
|
||||
disableFederationWarn: "聯邦被停用了。即使停用也不會讓您的貼文不公開,在大多數情況下,不需要啟用這個選項。"
|
||||
invitationRequiredToRegister: "目前這個伺服器為邀請制,必須擁有邀請碼才能註冊。"
|
||||
emailNotSupported: "這個伺服器不支援寄送郵件"
|
||||
postToTheChannel: "發布到頻道"
|
||||
_achievements:
|
||||
earnedAt: "獲得日期"
|
||||
_types:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"version": "13.9.1-simkey",
|
||||
"version": "13.9.2-simkey",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -278,27 +278,27 @@ export class UserEntityService implements OnModuleInit {
|
||||
@bindThis
|
||||
public async getAvatarUrl(user: User): Promise<string> {
|
||||
if (user.avatar) {
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user.id);
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else if (user.avatarId) {
|
||||
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
|
||||
return this.driveFileEntityService.getPublicUrl(avatar, 'avatar') ?? this.getIdenticonUrl(user.id);
|
||||
return this.driveFileEntityService.getPublicUrl(avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else {
|
||||
return this.getIdenticonUrl(user.id);
|
||||
return this.getIdenticonUrl(user);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getAvatarUrlSync(user: User): string {
|
||||
if (user.avatar) {
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user.id);
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else {
|
||||
return this.getIdenticonUrl(user.id);
|
||||
return this.getIdenticonUrl(user);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getIdenticonUrl(userId: User['id']): string {
|
||||
return `${this.config.url}/identicon/${userId}`;
|
||||
public getIdenticonUrl(user: User): string {
|
||||
return `${this.config.url}/identicon/${user.username.toLowerCase()}@${user.host ?? this.config.host}`;
|
||||
}
|
||||
|
||||
public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>(
|
||||
|
@ -1,7 +1,7 @@
|
||||
// 与えられた拡張子とファイル名が一致しているかどうかを確認し、
|
||||
// 一致していない場合は拡張子を付与して返す
|
||||
export function correctFilename(filename: string, ext: string | null) {
|
||||
const dotExt = ext ? `.${ext}` : '.unknown';
|
||||
const dotExt = ext ? ext.startsWith('.') ? ext : `.${ext}` : '.unknown';
|
||||
if (filename.endsWith(dotExt)) {
|
||||
return filename;
|
||||
}
|
||||
|
@ -76,9 +76,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
if (typeof ps.blocked === 'boolean') {
|
||||
const meta = await this.metaService.fetch(true);
|
||||
if (ps.blocked) {
|
||||
query.andWhere('instance.host IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
query.andWhere(meta.blockedHosts.length === 0 ? '1=0' : 'instance.host IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
} else {
|
||||
query.andWhere('instance.host NOT IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
query.andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
|
||||
let notes = await query
|
||||
.orderBy('note.score', 'DESC')
|
||||
.take(50)
|
||||
.take(100)
|
||||
.getMany();
|
||||
|
||||
notes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
||||
|
@ -64,6 +64,13 @@
|
||||
renderError('META_FETCH_V');
|
||||
return;
|
||||
}
|
||||
|
||||
// for https://github.com/misskey-dev/misskey/issues/10202
|
||||
if (lang == null || lang.toString == null || lang.toString() === 'null') {
|
||||
console.error('invalid lang value detected!!!', typeof lang, lang);
|
||||
lang = 'en-US';
|
||||
}
|
||||
|
||||
const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`);
|
||||
if (localRes.status === 200) {
|
||||
localStorage.setItem('lang', lang);
|
||||
|
@ -21,6 +21,9 @@ describe('misc:correct-filename', () => {
|
||||
test('with same ext', () => {
|
||||
expect(correctFilename('filename.jpg', 'jpg')).toBe('filename.jpg');
|
||||
});
|
||||
test('.ext', () => {
|
||||
expect(correctFilename('filename.jpg', '.jpg')).toBe('filename.jpg');
|
||||
});
|
||||
test('with different ext', () => {
|
||||
expect(correctFilename('filename.webp', 'jpg')).toBe('filename.webp.jpg');
|
||||
});
|
||||
|
@ -1,41 +1,46 @@
|
||||
<template>
|
||||
<div ref="rootEl" :class="[$style.root, { [$style.opened]: opened }]">
|
||||
<div :class="$style.header" class="_button" @click="toggle">
|
||||
<div :class="$style.headerIcon"><slot name="icon"></slot></div>
|
||||
<div :class="$style.headerText">
|
||||
<div :class="$style.headerTextMain">
|
||||
<slot name="label"></slot>
|
||||
</div>
|
||||
<div :class="$style.headerTextSub">
|
||||
<slot name="caption"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.headerRight">
|
||||
<span :class="$style.headerRightText"><slot name="suffix"></slot></span>
|
||||
<i v-if="opened" class="ti ti-chevron-up icon"></i>
|
||||
<i v-else class="ti ti-chevron-down icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="openedAtLeastOnce" :class="[$style.body, { [$style.bgSame]: bgSame }]" :style="{ maxHeight: maxHeight ? `${maxHeight}px` : null }">
|
||||
<Transition
|
||||
:enter-active-class="$store.state.animation ? $style.transition_toggle_enterActive : ''"
|
||||
:leave-active-class="$store.state.animation ? $style.transition_toggle_leaveActive : ''"
|
||||
:enter-from-class="$store.state.animation ? $style.transition_toggle_enterFrom : ''"
|
||||
:leave-to-class="$store.state.animation ? $style.transition_toggle_leaveTo : ''"
|
||||
@enter="enter"
|
||||
@after-enter="afterEnter"
|
||||
@leave="leave"
|
||||
@after-leave="afterLeave"
|
||||
>
|
||||
<KeepAlive>
|
||||
<div v-show="opened">
|
||||
<MkSpacer :margin-min="14" :margin-max="22">
|
||||
<slot></slot>
|
||||
</MkSpacer>
|
||||
<div ref="rootEl" :class="$style.root">
|
||||
<MkStickyContainer>
|
||||
<template #header>
|
||||
<div :class="[$style.header, { [$style.opened]: opened }]" class="_button" @click="toggle">
|
||||
<div :class="$style.headerIcon"><slot name="icon"></slot></div>
|
||||
<div :class="$style.headerText">
|
||||
<div :class="$style.headerTextMain">
|
||||
<slot name="label"></slot>
|
||||
</div>
|
||||
<div :class="$style.headerTextSub">
|
||||
<slot name="caption"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</KeepAlive>
|
||||
</Transition>
|
||||
</div>
|
||||
<div :class="$style.headerRight">
|
||||
<span :class="$style.headerRightText"><slot name="suffix"></slot></span>
|
||||
<i v-if="opened" class="ti ti-chevron-up icon"></i>
|
||||
<i v-else class="ti ti-chevron-down icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="openedAtLeastOnce" :class="[$style.body, { [$style.bgSame]: bgSame }]" :style="{ maxHeight: maxHeight ? `${maxHeight}px` : null, overflow: maxHeight ? `auto` : null }">
|
||||
<Transition
|
||||
:enter-active-class="$store.state.animation ? $style.transition_toggle_enterActive : ''"
|
||||
:leave-active-class="$store.state.animation ? $style.transition_toggle_leaveActive : ''"
|
||||
:enter-from-class="$store.state.animation ? $style.transition_toggle_enterFrom : ''"
|
||||
:leave-to-class="$store.state.animation ? $style.transition_toggle_leaveTo : ''"
|
||||
@enter="enter"
|
||||
@after-enter="afterEnter"
|
||||
@leave="leave"
|
||||
@after-leave="afterLeave"
|
||||
>
|
||||
<KeepAlive>
|
||||
<div v-show="opened">
|
||||
<MkSpacer :margin-min="14" :margin-max="22">
|
||||
<slot></slot>
|
||||
</MkSpacer>
|
||||
</div>
|
||||
</KeepAlive>
|
||||
</Transition>
|
||||
</div>
|
||||
</MkStickyContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -117,12 +122,6 @@ onMounted(() => {
|
||||
|
||||
.root {
|
||||
display: block;
|
||||
|
||||
&.opened {
|
||||
> .header {
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -132,6 +131,8 @@ onMounted(() => {
|
||||
box-sizing: border-box;
|
||||
padding: 9px 12px 9px 12px;
|
||||
background: var(--buttonBg);
|
||||
-webkit-backdrop-filter: var(--blur, blur(15px));
|
||||
backdrop-filter: var(--blur, blur(15px));
|
||||
border-radius: 6px;
|
||||
transition: border-radius 0.3s;
|
||||
|
||||
@ -144,6 +145,10 @@ onMounted(() => {
|
||||
color: var(--accent);
|
||||
background: var(--buttonHoverBg);
|
||||
}
|
||||
|
||||
&.opened {
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.headerUpper {
|
||||
@ -153,7 +158,7 @@ onMounted(() => {
|
||||
|
||||
.headerLower {
|
||||
color: var(--fgTransparentWeak);
|
||||
font-size: .85em;
|
||||
font-size: .85em;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
@ -202,7 +207,6 @@ onMounted(() => {
|
||||
background: var(--panel);
|
||||
border-radius: 0 0 6px 6px;
|
||||
container-type: inline-size;
|
||||
overflow: auto;
|
||||
|
||||
&.bgSame {
|
||||
background: var(--bg);
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
<div v-else ref="rootEl">
|
||||
<div v-show="pagination.reversed && more" key="_more_" class="_margin">
|
||||
<MkButton v-if="!moreFetching" v-appear="(enableInfiniteScroll && !props.disableAutoLoad) ? fetchMoreAhead : null" :class="$style.more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMoreAhead">
|
||||
<MkButton v-if="!moreFetching" v-appear="(enableInfiniteScroll && !props.disableAutoLoad) ? fetchMoreAhead : null" :class="$style.more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary rounded @click="fetchMoreAhead">
|
||||
{{ i18n.ts.loadMore }}
|
||||
</MkButton>
|
||||
<MkLoading v-else class="loading"/>
|
||||
</div>
|
||||
<slot :items="items" :fetching="fetching || moreFetching"></slot>
|
||||
<div v-show="!pagination.reversed && more" key="_more_" class="_margin">
|
||||
<MkButton v-if="!moreFetching" v-appear="(enableInfiniteScroll && !props.disableAutoLoad) ? fetchMore : null" :class="$style.more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMore">
|
||||
<MkButton v-if="!moreFetching" v-appear="(enableInfiniteScroll && !props.disableAutoLoad) ? fetchMore : null" :class="$style.more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary rounded @click="fetchMore">
|
||||
{{ i18n.ts.loadMore }}
|
||||
</MkButton>
|
||||
<MkLoading v-else class="loading"/>
|
||||
|
@ -431,6 +431,10 @@ function pushVisibleUser(user) {
|
||||
function addVisibleUser() {
|
||||
os.selectUser().then(user => {
|
||||
pushVisibleUser(user);
|
||||
|
||||
if (!text.toLowerCase().includes(`@${user.username.toLowerCase()}`)) {
|
||||
text = `@${Acct.toString(user)} ${text}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -667,7 +671,14 @@ async function post(ev?: MouseEvent) {
|
||||
if ((text.includes('love') || text.includes('❤')) && text.includes('misskey')) {
|
||||
claimAchievement('iLoveMisskey');
|
||||
}
|
||||
if (text.includes('Efrlqw8ytg4'.toLowerCase()) || text.includes('XVCwzwxdHuA'.toLowerCase())) {
|
||||
if (
|
||||
text.includes('https://youtu.be/Efrlqw8ytg4'.toLowerCase()) ||
|
||||
text.includes('https://www.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
|
||||
text.includes('https://m.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
|
||||
text.includes('https://youtu.be/XVCwzwxdHuA'.toLowerCase()) ||
|
||||
text.includes('https://www.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase()) ||
|
||||
text.includes('https://m.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase())
|
||||
) {
|
||||
claimAchievement('brainDiver');
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
<template #prefix>@</template>
|
||||
<template #suffix>@{{ host }}</template>
|
||||
<template #caption>
|
||||
<div><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.cannotBeChangedLater }}</div>
|
||||
<span v-if="usernameState === 'wait'" style="color:#999"><MkLoading :em="true"/> {{ i18n.ts.checking }}</span>
|
||||
<span v-else-if="usernameState === 'ok'" style="color: var(--success)"><i class="ti ti-check ti-fw"></i> {{ i18n.ts.available }}</span>
|
||||
<span v-else-if="usernameState === 'unavailable'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.unavailable }}</span>
|
||||
@ -117,7 +118,9 @@ const shouldDisableSubmitting = $computed((): boolean => {
|
||||
instance.enableHcaptcha && !hCaptchaResponse ||
|
||||
instance.enableRecaptcha && !reCaptchaResponse ||
|
||||
instance.enableTurnstile && !turnstileResponse ||
|
||||
passwordRetypeState === 'not-match';
|
||||
instance.emailRequiredForSignup && emailState !== 'ok' ||
|
||||
usernameState !== 'ok' ||
|
||||
passwordRetypeState !== 'match';
|
||||
});
|
||||
|
||||
function onChangeUsername(): void {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="vrtktovh" :class="{ first }">
|
||||
<div class="label"><slot name="label"></slot></div>
|
||||
<div class="main">
|
||||
<div :class="[$style.root, { [$style.rootFirst]: first }]">
|
||||
<div :class="[$style.label, { [$style.labelFirst]: first }]"><slot name="label"></slot></div>
|
||||
<div :class="$style.main">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
@ -13,31 +13,31 @@ defineProps<{
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vrtktovh {
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
border-top: solid 0.5px var(--divider);
|
||||
//border-bottom: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
> .label {
|
||||
font-weight: bold;
|
||||
padding: 1.5em 0 0 0;
|
||||
margin: 0 0 16px 0;
|
||||
.rootFirst {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.label {
|
||||
font-weight: bold;
|
||||
padding: 1.5em 0 0 0;
|
||||
margin: 0 0 16px 0;
|
||||
|
||||
> .main {
|
||||
margin: 1.5em 0 0 0;
|
||||
}
|
||||
|
||||
&.first {
|
||||
border-top: none;
|
||||
|
||||
> .label {
|
||||
padding-top: 0;
|
||||
}
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.labelFirst {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.main {
|
||||
margin: 1.5em 0 0 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -84,6 +84,12 @@
|
||||
</div>
|
||||
<p>{{ i18n.ts._aboutMisskey.morePatrons }}</p>
|
||||
</FormSection>
|
||||
<FormSection>
|
||||
<template #label>Special thanks</template>
|
||||
<div style="text-align: center;">
|
||||
<a style="display: inline-block;" class="dcadvirth" title="DC Advirth" href="https://www.dotchain.ltd/advirth" target="_blank"><img width="200" src="https://misskey-hub.net/sponsors/dcadvirth.png" alt="DC Advirth"></a>
|
||||
</div>
|
||||
</FormSection>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</div>
|
||||
@ -120,6 +126,9 @@ const patronsWithIcon = [{
|
||||
}, {
|
||||
name: 'ぱーこ',
|
||||
icon: 'https://misskey-hub.net/patrons/79c6602ffade489e8df2fcf2c2bc5d9d.jpg',
|
||||
}, {
|
||||
name: 'わっほー☆',
|
||||
icon: 'https://misskey-hub.net/patrons/d31d5d13924443a082f3da7966318a0a.jpg',
|
||||
}];
|
||||
|
||||
const patrons = [
|
||||
@ -203,6 +212,8 @@ const patrons = [
|
||||
'pixeldesu',
|
||||
'あめ玉',
|
||||
'氷月氷華里',
|
||||
'Ebise Lutica',
|
||||
'巣黒るい@リスケモ男の娘VTuber!',
|
||||
];
|
||||
|
||||
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
|
||||
|
@ -46,7 +46,8 @@ if (props.id) {
|
||||
data = {
|
||||
name: 'New Role',
|
||||
description: '',
|
||||
rolePermission: 'normal',
|
||||
isAdministrator: false,
|
||||
isModerator: false,
|
||||
color: null,
|
||||
iconUrl: null,
|
||||
target: 'manual',
|
||||
|
@ -85,7 +85,7 @@ function edit() {
|
||||
function openPostForm() {
|
||||
os.post({
|
||||
channel: {
|
||||
id: channel.channelId,
|
||||
id: channel.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ let roles = $ref();
|
||||
os.api('roles/list', {
|
||||
limit: 30,
|
||||
}).then(res => {
|
||||
roles = res;
|
||||
roles = res.filter(x => x.target === 'manual');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -193,6 +193,7 @@ watch([
|
||||
enableInfiniteScroll,
|
||||
squareAvatars,
|
||||
aiChanMode,
|
||||
showNoteActionsOnlyHover,
|
||||
showGapBetweenNotesInTimeline,
|
||||
instanceTicker,
|
||||
overridedDeviceKind,
|
||||
|
@ -5,22 +5,60 @@
|
||||
<option value="block">{{ i18n.ts.blockedUsers }}</option>
|
||||
</MkTab>
|
||||
<div v-if="tab === 'mute'">
|
||||
<MkPagination :pagination="mutingPagination" class="muting">
|
||||
<template #empty><FormInfo>{{ i18n.ts.noUsers }}</FormInfo></template>
|
||||
<template #default="{items}">
|
||||
<FormLink v-for="mute in items" :key="mute.id" :to="userPage(mute.mutee)">
|
||||
<MkAcct :user="mute.mutee"/>
|
||||
</FormLink>
|
||||
<MkPagination :pagination="mutingPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items }">
|
||||
<div class="_gaps_s">
|
||||
<div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedMuteItems.includes(item.id) }]">
|
||||
<div :class="$style.userItemMain">
|
||||
<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.mutee.id}`">
|
||||
<MkUserCardMini :user="item.mutee"/>
|
||||
</MkA>
|
||||
<button class="_button" :class="$style.userToggle" @click="toggleMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
|
||||
<button class="_button" :class="$style.remove" @click="unmute(item.mutee, $event)"><i class="ti ti-x"></i></button>
|
||||
</div>
|
||||
<div v-if="expandedMuteItems.includes(item.id)" :class="$style.userItemSub">
|
||||
<div>Muted at: <MkTime :time="item.createdAt" mode="detail"/></div>
|
||||
<div v-if="item.expiresAt">Period: {{ item.expiresAt.toLocaleString() }}</div>
|
||||
<div v-else>Period: {{ i18n.ts.indefinitely }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</MkPagination>
|
||||
</div>
|
||||
<div v-if="tab === 'block'">
|
||||
<MkPagination :pagination="blockingPagination" class="blocking">
|
||||
<template #empty><FormInfo>{{ i18n.ts.noUsers }}</FormInfo></template>
|
||||
<template #default="{items}">
|
||||
<FormLink v-for="block in items" :key="block.id" :to="userPage(block.blockee)">
|
||||
<MkAcct :user="block.blockee"/>
|
||||
</FormLink>
|
||||
<MkPagination :pagination="blockingPagination">
|
||||
<template #empty>
|
||||
<div class="_fullinfo">
|
||||
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||
<div>{{ i18n.ts.noUsers }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items }">
|
||||
<div class="_gaps_s">
|
||||
<div v-for="item in items" :key="item.blockee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedBlockItems.includes(item.id) }]">
|
||||
<div :class="$style.userItemMain">
|
||||
<MkA :class="$style.userItemMainBody" :to="`/user-info/${item.blockee.id}`">
|
||||
<MkUserCardMini :user="item.blockee"/>
|
||||
</MkA>
|
||||
<button class="_button" :class="$style.userToggle" @click="toggleBlockItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
|
||||
<button class="_button" :class="$style.remove" @click="unblock(item.blockee, $event)"><i class="ti ti-x"></i></button>
|
||||
</div>
|
||||
<div v-if="expandedBlockItems.includes(item.id)" :class="$style.userItemSub">
|
||||
<div>Blocked at: <MkTime :time="item.createdAt" mode="detail"/></div>
|
||||
<div v-if="item.expiresAt">Period: {{ item.expiresAt.toLocaleString() }}</div>
|
||||
<div v-else>Period: {{ i18n.ts.indefinitely }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</MkPagination>
|
||||
</div>
|
||||
@ -36,6 +74,8 @@ import FormLink from '@/components/form/link.vue';
|
||||
import { userPage } from '@/filters/user';
|
||||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
let tab = $ref('mute');
|
||||
|
||||
@ -49,6 +89,47 @@ const blockingPagination = {
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
let expandedMuteItems = $ref([]);
|
||||
let expandedBlockItems = $ref([]);
|
||||
|
||||
async function unmute(user, ev) {
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.unmute,
|
||||
icon: 'ti ti-x',
|
||||
action: async () => {
|
||||
await os.apiWithDialog('mute/delete', { userId: user.id });
|
||||
//role.users = role.users.filter(u => u.id !== user.id);
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
async function unblock(user, ev) {
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.unblock,
|
||||
icon: 'ti ti-x',
|
||||
action: async () => {
|
||||
await os.apiWithDialog('blocking/delete', { userId: user.id });
|
||||
//role.users = role.users.filter(u => u.id !== user.id);
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
async function toggleMuteItem(item) {
|
||||
if (expandedMuteItems.includes(item.id)) {
|
||||
expandedMuteItems = expandedMuteItems.filter(x => x !== item.id);
|
||||
} else {
|
||||
expandedMuteItems.push(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleBlockItem(item) {
|
||||
if (expandedBlockItems.includes(item.id)) {
|
||||
expandedBlockItems = expandedBlockItems.filter(x => x !== item.id);
|
||||
} else {
|
||||
expandedBlockItems.push(item.id);
|
||||
}
|
||||
}
|
||||
|
||||
const headerActions = $computed(() => []);
|
||||
|
||||
const headerTabs = $computed(() => []);
|
||||
@ -58,3 +139,43 @@ definePageMetadata({
|
||||
icon: 'ti ti-ban',
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.userItemMain {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.userItemSub {
|
||||
padding: 6px 12px;
|
||||
font-size: 85%;
|
||||
color: var(--fgTransparentWeak);
|
||||
}
|
||||
|
||||
.userItemMainBody {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-right: 8px;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.userToggle,
|
||||
.remove {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
display: block;
|
||||
transition: transform 0.1s ease-out;
|
||||
}
|
||||
|
||||
.userItem.userItemOpend {
|
||||
.chevron {
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -355,6 +355,9 @@ onUnmounted(() => {
|
||||
> .roles {
|
||||
padding: 24px 24px 0 154px;
|
||||
font-size: 0.95em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
> .role {
|
||||
border: solid 1px var(--color, var(--divider));
|
||||
@ -496,7 +499,7 @@ onUnmounted(() => {
|
||||
|
||||
> .roles {
|
||||
padding: 16px 16px 0 16px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
> .description {
|
||||
|
@ -111,7 +111,7 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
|
||||
icon: 'ti ti-mail',
|
||||
text: i18n.ts.sendMessage,
|
||||
action: () => {
|
||||
os.post({ specified: user });
|
||||
os.post({ specified: user, initialText: `@${user.username} ` });
|
||||
},
|
||||
}, null, {
|
||||
type: 'parent',
|
||||
|
@ -332,8 +332,8 @@ export class ColdDeviceStorage {
|
||||
plugins: [] as Plugin[],
|
||||
mediaVolume: 0.5,
|
||||
sound_masterVolume: 0.5,
|
||||
sound_note: { type: 'syuilo/n-aec', volume: 0.5 },
|
||||
sound_noteMy: { type: 'syuilo/n-cea', volume: 0.5 },
|
||||
sound_note: { type: 'syuilo/n-eca', volume: 0.5 },
|
||||
sound_noteMy: { type: 'syuilo/n-cea-4va', volume: 0.5 },
|
||||
sound_notification: { type: 'syuilo/n-ea', volume: 0.5 },
|
||||
sound_chat: { type: 'syuilo/pope1', volume: 0.5 },
|
||||
sound_chatBg: { type: 'syuilo/waon', volume: 0.5 },
|
||||
|
@ -40,8 +40,9 @@ const fs = require('fs');
|
||||
|
||||
const start = async () => {
|
||||
try {
|
||||
const exist = fs.existsSync(__dirname + '/../packages/backend/built/boot/index.js')
|
||||
if (!exist) throw new Error('not exist yet');
|
||||
const stat = fs.statSync(__dirname + '/../packages/backend/built/boot/index.js');
|
||||
if (!stat) throw new Error('not exist yet');
|
||||
if (stat.size === 0) throw new Error('not built yet');
|
||||
|
||||
await execa('pnpm', ['start'], {
|
||||
cwd: __dirname + '/../',
|
||||
|
Loading…
x
Reference in New Issue
Block a user