Merge branch 'develop'
This commit is contained in:
commit
88cdbc2ad6
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
|
@ -17,5 +17,9 @@ jobs:
|
|||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- run: yarn install
|
||||
- run: yarn lint
|
||||
|
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -75,6 +75,10 @@ jobs:
|
|||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
- name: Check yarn.lock
|
||||
|
|
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
|
@ -3,7 +3,7 @@
|
|||
"editorconfig.editorconfig",
|
||||
"eg2.vscode-npm-script",
|
||||
"ms-vscode.typescript-javascript-grammar",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"johnsoncodehk.volar",
|
||||
"sysoev.language-stylus"
|
||||
]
|
||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -7,6 +7,18 @@
|
|||
|
||||
-->
|
||||
|
||||
## 12.97.0 (2021/11/19)
|
||||
|
||||
### Improvements
|
||||
- クライアント: 返信先やRenoteに対しても自動折りたたみされるように
|
||||
- クライアント: 長いスレッドの表示を改善
|
||||
- クライアント: 翻訳にもMFMを適用し、元の文章の改行などを保持するように
|
||||
- クライアント: アカウント削除に確認ダイアログを出すように
|
||||
|
||||
### Bugfixes
|
||||
- クライアント: ユーザー検索の「全て」が動作しない問題を修正
|
||||
- クライアント: リアクション一覧、Renote一覧ツールチップのスタイルを修正
|
||||
|
||||
## 12.96.1 (2021/11/13)
|
||||
### Improvements
|
||||
- npm scriptの互換性を向上
|
||||
|
|
|
@ -49,6 +49,11 @@ If your language is not listed in Crowdin, please open an issue.
|
|||
|
||||
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
|
||||
|
||||
## Development
|
||||
During development, it is useful to use the `npm run dev` command.
|
||||
This command monitors the server-side and client-side source files and automatically builds them if they are modified.
|
||||
In addition, it will also automatically start the Misskey server process.
|
||||
|
||||
## Testing
|
||||
- Test codes are located in [`/test`](/test).
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ COPY --from=builder /misskey/built ./built
|
|||
COPY --from=builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
|
||||
COPY --from=builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --from=builder /misskey/packages/client/node_modules ./packages/client/node_modules
|
||||
COPY --from=builder /misskey/packages/client/built ./packages/client/built
|
||||
COPY . ./
|
||||
|
||||
CMD ["npm", "run", "migrateandstart"]
|
||||
|
|
|
@ -57,6 +57,6 @@ gulp.task('default', gulp.task('build'));
|
|||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch([
|
||||
'./packages/**/*',
|
||||
'./packages/*/src/**/*',
|
||||
], { ignoreInitial: false }, gulp.task('build'));
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -52,6 +52,7 @@ searchUser: "Vyhledat uživatele"
|
|||
reply: "Odpovědět"
|
||||
loadMore: "Zobrazit více"
|
||||
showMore: "Zobrazit více"
|
||||
youGotNewFollower: "Máte nového následovníka"
|
||||
mention: "Zmínění"
|
||||
mentions: "Zmínění"
|
||||
importAndExport: "Import a export"
|
||||
|
@ -163,6 +164,7 @@ clearQueue: "Vyčistit frontu"
|
|||
clearQueueConfirmTitle: "Jste si jisti že zrušit všechny úlohy ve frontě?"
|
||||
clearCachedFiles: "Vyprázdnit mezipaměť"
|
||||
blockedInstances: "Blokované instance"
|
||||
noUsers: "Žádní uživatelé"
|
||||
editProfile: "Upravit můj profil"
|
||||
pinLimitExceeded: "Nemůžete připnout další poznámky."
|
||||
intro: "Instalace Misskey byla dokončena! Prosím vytvořte admina."
|
||||
|
@ -170,6 +172,7 @@ done: "Hotovo"
|
|||
processing: "Zpracovávám"
|
||||
preview: "Náhled"
|
||||
default: "Výchozí"
|
||||
noCustomEmojis: "Bez Emoji"
|
||||
blocked: "Blokováno"
|
||||
suspended: "Suspendováno"
|
||||
all: "Vše"
|
||||
|
@ -402,6 +405,9 @@ smtpPass: "Heslo"
|
|||
clearCache: "Vyprázdnit mezipaměť"
|
||||
info: "Informace"
|
||||
user: "Uživatelé"
|
||||
_email:
|
||||
_follow:
|
||||
title: "Máte nového následovníka"
|
||||
_mfm:
|
||||
mention: "Zmínění"
|
||||
quote: "Citovat"
|
||||
|
@ -464,6 +470,7 @@ _pages:
|
|||
types:
|
||||
array: "Seznamy"
|
||||
_notification:
|
||||
youWereFollowed: "Máte nového následovníka"
|
||||
youWereInvitedToGroup: "Pozvat do skupiny"
|
||||
_types:
|
||||
follow: "Sledovaní"
|
||||
|
|
|
@ -620,6 +620,8 @@ reportAbuse: "Melden"
|
|||
reportAbuseOf: "{name} melden"
|
||||
fillAbuseReportDescription: "Bitte gib zusätzliche Informationen zu dieser Meldung an. Falls es sich um eine spezielle Notiz handelt, bitte gib dessen URL an."
|
||||
abuseReported: "Die Meldung wurde versendet. Vielen Dank."
|
||||
reporteeOrigin: "Herkunft des Gemeldeten"
|
||||
reporterOrigin: "Herkunft des Meldenden"
|
||||
send: "Senden"
|
||||
abuseMarkAsResolved: "Meldung als gelöst markieren"
|
||||
openInNewTab: "In neuem Tab öffnen"
|
||||
|
@ -795,12 +797,27 @@ itsOff: "Ausgeschaltet"
|
|||
emailRequiredForSignup: "Angaben einer Email-Adresse als benötigt markieren"
|
||||
unread: "Ungelesen"
|
||||
filter: "Filter"
|
||||
controlPanel: "Systemsteuerung"
|
||||
manageAccounts: "Benutzerkonten verwalten"
|
||||
makeReactionsPublic: "Reaktionsverlauf veröffentlichen"
|
||||
makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktionen einsehen können."
|
||||
classic: "Classic"
|
||||
muteThread: "Thread stummschalten"
|
||||
unmuteThread: "Threadstummschaltung aufheben"
|
||||
ffVisibility: "Sichtbarkeit von Gefolgten/Followern"
|
||||
ffVisibilityDescription: "Konfiguriere wer sehen kann, wem du folgst sowie wer dir folgt."
|
||||
continueThread: "Weiteren Threadverlauf anzeigen"
|
||||
deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?"
|
||||
_emailUnavailable:
|
||||
used: "Diese Email-Adresse wird bereits verwendet"
|
||||
format: "Das Format dieser Email-Adresse ist ungültig"
|
||||
disposable: "Wegwerf-Email-Adressen können nicht verwendet werden"
|
||||
mx: "Dieser Email-Server ist ungültig"
|
||||
smtp: "Dieser Email-Server antwortet nicht"
|
||||
_ffVisibility:
|
||||
public: "Öffentlich"
|
||||
followers: "Nur für Follower sichtbar"
|
||||
private: "Privat"
|
||||
_signup:
|
||||
almostThere: "Fast geschafft"
|
||||
emailAddressInfo: "Bitte gib deine Email-Adresse ein."
|
||||
|
@ -812,13 +829,6 @@ _accountDelete:
|
|||
requestAccountDelete: "Löschung des Benutzerkontos anfordern"
|
||||
started: "Löschung wurde eingeleitet."
|
||||
inProgress: "Löschung in Bearbeitung"
|
||||
_docs:
|
||||
continueReading: "Mehr lesen"
|
||||
features: "Funktionen"
|
||||
generalTopics: "Allgemeine Themen"
|
||||
advancedTopics: "Erweiterte Themen"
|
||||
admin: "Administration"
|
||||
translateWarn: "Dies ist ein übersetztes Dokument. Es kann zu Unterschieden mit dem Original kommen."
|
||||
_ad:
|
||||
back: "Zurück"
|
||||
reduceFrequencyOfThisAd: "Diese Werbung weniger anzeigen"
|
||||
|
|
|
@ -620,6 +620,8 @@ reportAbuse: "Report"
|
|||
reportAbuseOf: "Report {name}"
|
||||
fillAbuseReportDescription: "Please fill in details regarding this report. If it is about a specific note, please include its URL."
|
||||
abuseReported: "Your report has been sent. Thank you very much."
|
||||
reporteeOrigin: "Reportee Origin"
|
||||
reporterOrigin: "Reporter Origin"
|
||||
send: "Send"
|
||||
abuseMarkAsResolved: "Mark report as resolved"
|
||||
openInNewTab: "Open in new tab"
|
||||
|
@ -802,6 +804,20 @@ makeReactionsPublicDescription: "This will make the list of all your past reacti
|
|||
classic: "Classic"
|
||||
muteThread: "Mute thread"
|
||||
unmuteThread: "Unmute thread"
|
||||
ffVisibility: "Follows/Followers Visibility"
|
||||
ffVisibilityDescription: "Allows you to configure who can see who you follow and who follows you."
|
||||
continueThread: "View thread continuation"
|
||||
deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
|
||||
_emailUnavailable:
|
||||
used: "This email address is already being used"
|
||||
format: "The format of this email address is invalid"
|
||||
disposable: "Disposable email addresses may not be used"
|
||||
mx: "This email server is invalid"
|
||||
smtp: "This email server is not responding"
|
||||
_ffVisibility:
|
||||
public: "Public"
|
||||
followers: "Visible to followers only"
|
||||
private: "Private"
|
||||
_signup:
|
||||
almostThere: "Almost there"
|
||||
emailAddressInfo: "Please enter your email address."
|
||||
|
@ -813,13 +829,6 @@ _accountDelete:
|
|||
requestAccountDelete: "Request account deletion"
|
||||
started: "Deletion has been started."
|
||||
inProgress: "Deletion is currently in progress"
|
||||
_docs:
|
||||
continueReading: "Read more"
|
||||
features: "Features"
|
||||
generalTopics: "General topics"
|
||||
advancedTopics: "Advanced Topics"
|
||||
admin: "Administration"
|
||||
translateWarn: "This is a translated document. Its contents may differ from the original."
|
||||
_ad:
|
||||
back: "Back"
|
||||
reduceFrequencyOfThisAd: "Show this ad less"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
_lang_: "Esperanto"
|
||||
headlineMisskey: "Jen la reto konektata de notoj"
|
||||
introMisskey: "Bonvenon! Misskey estas malfermitkoda malcentraliza etbloga servo.\nKreu \"noto\"n por paroli vian penson al iuj ĉirkaŭ vi. 📡\nLa funkcion \"reago\" ebligas esprimi rapide vian senton pri ies noto en Fediverso. 👍\nBonvole esploru novan mondon. 🚀"
|
||||
monthAndDay: "{{day}}/{{month}}"
|
||||
monthAndDay: "La {day}a de la {month}a"
|
||||
search: "Serĉi"
|
||||
notifications: "Sciigoj"
|
||||
username: "Uzantnomo"
|
||||
|
@ -23,7 +23,7 @@ otherSettings: "Aliaj agordoj"
|
|||
openInWindow: "Malfermi en fenestro"
|
||||
profile: "Profilo"
|
||||
timeline: "Templinio"
|
||||
noAccountDescription: "Neniu priskribo"
|
||||
noAccountDescription: "Neniu sinprezento"
|
||||
login: "Ensaluti"
|
||||
loggingIn: "Ensalutado…"
|
||||
logout: "Elsaluti"
|
||||
|
@ -36,15 +36,15 @@ favorite: "Preferi"
|
|||
favorites: "Preferaĵoj"
|
||||
unfavorite: "Malpreferi"
|
||||
favorited: "Aldonita al via listo de preferaĵoj."
|
||||
alreadyFavorited: "Ĝi jam estis aldonita al via listo de preferaĵoj."
|
||||
cantFavorite: "Ne aldonita al via listo de preferaĵoj."
|
||||
alreadyFavorited: "Jam aldonita al via listo de preferaĵoj."
|
||||
cantFavorite: "Ĝi ne povis esti aldonita al via listo de preferaĵoj."
|
||||
pin: "Alpingli"
|
||||
unpin: "Depingli"
|
||||
copyContent: "Kopii enhavon"
|
||||
copyLink: "Kopii ligilon"
|
||||
delete: "Forviŝi"
|
||||
deleteAndEdit: "Redakti foriginte"
|
||||
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forigi kaj redakti la noton? Tio forviŝos reagojn, plusendojn, kaj respondojn ĉiujn de ĝi."
|
||||
deleteAndEdit: "Forviŝi kaj redakti"
|
||||
deleteAndEditConfirm: "Ĉu vi certas ke vi volas redakti forviŝinte la noton? Tio forviŝos ankaŭ ĉiujn reagojn, plusendojn, kaj respondojn apartenantajn al ĝi."
|
||||
addToList: "Aldoni al listo"
|
||||
sendMessage: "Sendi mesaĝon"
|
||||
copyUsername: "Kopii uzantnomon"
|
||||
|
@ -56,7 +56,7 @@ youGotNewFollower: "eksekvis vin"
|
|||
receiveFollowRequest: "Peto de sekvado estas ricevita"
|
||||
followRequestAccepted: "La peto de sekvado akceptita"
|
||||
mention: "Mencioj"
|
||||
mentions: "Al vi"
|
||||
mentions: "Mencioj"
|
||||
directNotes: "Rekte senditaj"
|
||||
importAndExport: "Importi/eksporti"
|
||||
import: "Importi"
|
||||
|
@ -79,11 +79,13 @@ somethingHappened: "Problemo okazis"
|
|||
retry: "Provi denove"
|
||||
enterListName: "Entajpu nomon de la listo"
|
||||
privacy: "Privateco"
|
||||
makeFollowManuallyApprove: "Eksekvi vin devas peti al vi"
|
||||
defaultNoteVisibility: "Implicitaĵo de videbleco"
|
||||
follow: "Sekvi"
|
||||
followRequest: "Peti de sekvado"
|
||||
followRequests: "Petoj de sekvado"
|
||||
unfollow: "Ne plu sekvi"
|
||||
followRequestPending: "Atendado akcepti vian peton de eksekvado"
|
||||
enterEmoji: "Entajpu emoĵion"
|
||||
renote: "Plusendi la noton"
|
||||
unrenote: "Malfari plusendadon"
|
||||
|
@ -98,11 +100,12 @@ clickToShow: "Klaku por malkaŝu"
|
|||
sensitive: "Enhavo ne estas deca por laborejo (NSFW)"
|
||||
add: "Aldoni"
|
||||
reaction: "Reagoj"
|
||||
rememberNoteVisibility: "Rememoru videblecon de la noto laste sendita "
|
||||
reactionSettingDescription: "Agordi la reagojn kiujn vi volas prefere montrigi ĉe la elektilo de reagoj"
|
||||
rememberNoteVisibility: "Rememori la agordon de videbleco de la noto laste sendita "
|
||||
attachCancel: "Deigi aldonaĵon"
|
||||
markAsSensitive: "Troviĝi NSFW"
|
||||
unmarkAsSensitive: "Ne troviĝi NSFW"
|
||||
enterFileName: "Entajpu nomon de dosiero"
|
||||
enterFileName: "Entajpu nomon de la dosiero"
|
||||
mute: "Silentigi"
|
||||
unmute: "Malsilentigi"
|
||||
block: "Bloki"
|
||||
|
@ -127,7 +130,7 @@ addEmoji: "Aldoni emoĵion"
|
|||
settingGuide: "Agordaj rekomendoj"
|
||||
cacheRemoteFiles: "Stapli transajn dosierojn"
|
||||
flagAsBot: "Agordo por robota uzanto"
|
||||
flagAsCat: "Agordo de katiĝa uzanto"
|
||||
flagAsCat: "Agi kat-iĝon"
|
||||
addAccount: "Aldoni konton"
|
||||
showOnRemote: "Vidi ĉe la surloka nodo"
|
||||
general: "Ĝenerala"
|
||||
|
@ -141,13 +144,14 @@ host: "Gastigo"
|
|||
selectUser: "Elekti uzanton"
|
||||
recipient: "Ricevonto"
|
||||
annotation: "Komentarioj"
|
||||
federation: "Kunfederaĵo"
|
||||
federation: "Federaĵo"
|
||||
instances: "Nodoj"
|
||||
latestRequestSentAt: "Lastatempa sendo"
|
||||
latestRequestReceivedAt: "Lastatempa ricevo"
|
||||
latestStatus: "Laŭstato"
|
||||
perHour: "Po horo"
|
||||
perDay: "Po tago"
|
||||
charts: "Diagramoj"
|
||||
perHour: "por horo"
|
||||
perDay: "por tago"
|
||||
blockThisInstance: "Bloki la nodon"
|
||||
operations: "Agoj"
|
||||
software: "Programaro"
|
||||
|
@ -156,36 +160,37 @@ metadata: "Metadatumoj"
|
|||
withNFiles: "{n} dosiero(j)"
|
||||
monitor: "Monitoro"
|
||||
network: "Reto"
|
||||
disk: "Diskilo"
|
||||
disk: "Disko"
|
||||
instanceInfo: "Informoj pri la nodo"
|
||||
statistics: "Statistikoj"
|
||||
clearCachedFiles: "Malplenigi la staplon"
|
||||
clearCachedFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn transajn dosierojn en la staplo?"
|
||||
blockedInstances: "Blokitaj nodoj"
|
||||
muteAndBlock: "Silentigitoj kaj blokitoj"
|
||||
mutedUsers: "Silentigitaj uzantoj"
|
||||
blockedUsers: "Blokitaj uzantoj"
|
||||
noUsers: "Sen uzantoj"
|
||||
noUsers: "Neniu uzanto"
|
||||
editProfile: "Redakti profilon"
|
||||
noteDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la noton?"
|
||||
pinLimitExceeded: "Vi povas alpingli ne pli noton."
|
||||
pinLimitExceeded: "Vi ne povas alpingli pli"
|
||||
done: "Fini"
|
||||
processing: "Prilaborado…"
|
||||
preview: "Antaŭmontro"
|
||||
default: "Defaŭlta"
|
||||
noCustomEmojis: "Neniu emoĵio"
|
||||
federating: "Nun kunfederanta"
|
||||
blocked: "Blokita"
|
||||
suspended: "Suspendita"
|
||||
noJobs: "Neniu laboro"
|
||||
federating: "Federantaj"
|
||||
blocked: "Blokitaj"
|
||||
suspended: "Suspenditaj"
|
||||
all: "Ĉiuj"
|
||||
subscribing: "Abonata"
|
||||
publishing: "Al kiu dissendas"
|
||||
subscribing: "Abonitaj"
|
||||
publishing: "Abonintaj"
|
||||
notResponding: "Alvokato ne disponeblas"
|
||||
instanceFollowing: "Sekvatoj en la nodo"
|
||||
instanceFollowers: "Sekvantoj el la nodo"
|
||||
instanceUsers: "Uzantoj de tiu ĉi nodo"
|
||||
instanceUsers: "Uzantoj de la nodo"
|
||||
changePassword: "Ŝanĝi pasvorton"
|
||||
security: "Sekureco"
|
||||
retypedNotMatch: "Enigitoj ne estas konformaj."
|
||||
retypedNotMatch: "La enigitoj ne estas konformaj."
|
||||
currentPassword: "Aktuala pasvorto"
|
||||
newPassword: "Nova pasvorto"
|
||||
newPasswordRetype: "Reentajpu la novan pasvorton"
|
||||
|
@ -193,38 +198,47 @@ attachFile: "Aldoni dosieron"
|
|||
more: "Plu!"
|
||||
featured: "Maksimumi"
|
||||
usernameOrUserId: "Uzantnomo aŭ identigilo de uzanto"
|
||||
noSuchUser: "Neniuj uzantoj trovitaj."
|
||||
noSuchUser: "Neniuj uzantoj trovitaj"
|
||||
lookup: "Informpeti"
|
||||
announcements: "Novaĵoj"
|
||||
imageUrl: "URL de bildo"
|
||||
imageUrl: "URL de la bildo"
|
||||
remove: "Forigi"
|
||||
removed: "Forviŝis"
|
||||
removed: "Forigita"
|
||||
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"'(o)n?"
|
||||
deleteAreYouSure: "Ĉu vi certas ke vi volas forviŝi \"{x}\"'(o)n?"
|
||||
resetAreYouSure: "Ĉu vi certas restarigi?"
|
||||
saved: "Konservita"
|
||||
messaging: "Retbabili"
|
||||
upload: "Alŝuti"
|
||||
fromDrive: "De la disko"
|
||||
fromUrl: "De URL"
|
||||
uploadFromUrl: "Alŝuti de URL"
|
||||
uploadFromUrlDescription: "URL de dosiero kiun vi volas alŝuti"
|
||||
uploadFromUrlDescription: "URL de la dosiero kiun vi volas alŝuti"
|
||||
uploadFromUrlRequested: "La alŝutado estis patita"
|
||||
explore: "Esplori"
|
||||
games: "Miskiaj Ludoj"
|
||||
messageRead: "Legita"
|
||||
noMoreHistory: "Ne plu de la historio"
|
||||
startMessaging: "Komenci babiladon"
|
||||
nUsersRead: "Legita de {n} homoj"
|
||||
agreeTo: "Mi akceptas {0}'(o)n"
|
||||
tos: "Kondiĉoj de uzado"
|
||||
start: "Komenciĝi"
|
||||
home: "Hejma"
|
||||
remoteUserCaution: "Ĉi tiuj infomoj ne estas tute ekzaktaj pro transa uzanto."
|
||||
remoteUserCaution: "Ĉi tiuj infomoj estas ne tute ekzaktaj pro transa uzanto."
|
||||
activity: "Aktiveco"
|
||||
images: "Bildoj"
|
||||
birthday: "Naskiĝdato"
|
||||
yearsOld: "{age} jaroj aĝa"
|
||||
registeredDate: "Dato de registriĝo"
|
||||
location: "Loko"
|
||||
theme: "Koloraro"
|
||||
themeForLightMode: "Luma kolararo en la luma modo"
|
||||
themeForDarkMode: "Malluma kolararo en la malluma modo"
|
||||
light: "Luma"
|
||||
dark: "Malluma"
|
||||
lightThemes: "Luma koloraro"
|
||||
darkThemes: "Malluma koloraro"
|
||||
drive: "Disko"
|
||||
fileName: "Dosiernomo"
|
||||
selectFile: "Elekti dosieron"
|
||||
|
@ -240,15 +254,18 @@ addFile: "Aldoni dosieron"
|
|||
emptyDrive: "La disko malplenas"
|
||||
emptyFolder: "La dosierujo malplenas"
|
||||
unableToDelete: "Ne forigebla"
|
||||
inputNewFileName: "Entajpu nova nomon de la dosiero"
|
||||
inputNewFolderName: "Entajpu nova nomon de la dosierujo"
|
||||
inputNewFileName: "Entajpu novan nomon de la dosiero"
|
||||
inputNewDescription: "Entajpu novan priskribon"
|
||||
inputNewFolderName: "Entajpu novan nomon de la dosierujo"
|
||||
hasChildFilesOrFolders: "La dosierujo ne estas forviŝebla, ĉar ĝi ne malplenas."
|
||||
copyUrl: "Kopii URL"
|
||||
rename: "Alinomi"
|
||||
avatar: "Ikono"
|
||||
banner: "Standardo"
|
||||
nsfw: "Enhavo ne estas deca por laborejo (NSFW)"
|
||||
disconnectedFromServer: "Malkonektita de servilo"
|
||||
reload: "Reŝargi"
|
||||
doNothing: "Ignori"
|
||||
watch: "Observi"
|
||||
unwatch: "Malobservi"
|
||||
accept: "Permesi"
|
||||
|
@ -265,6 +282,7 @@ dayX: "{day}a"
|
|||
monthX: "La {month}a monato"
|
||||
yearX: "La jaro {year}"
|
||||
pages: "Paĝoj"
|
||||
integration: "Integri"
|
||||
connectService: "Konekti"
|
||||
disconnectService: "Farkonektiĝi"
|
||||
enableLocalTimeline: "Ebligi lokan templinion"
|
||||
|
@ -281,6 +299,8 @@ basicInfo: "Baza informo"
|
|||
pinnedUsers: "Alpinglita uzanto"
|
||||
pinnedPages: "Alpinglitaj paĝoj"
|
||||
pinnedNotes: "Alpinglita noto"
|
||||
hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "Ebligi hCaptcha"
|
||||
hcaptchaSiteKey: "Reteja ŝlosilo"
|
||||
hcaptchaSecretKey: "Sekreta ŝlosilo"
|
||||
recaptcha: "reCAPTCHA"
|
||||
|
@ -290,6 +310,7 @@ recaptchaSecretKey: "Sekreta ŝlosilo"
|
|||
antennas: "Antenoj"
|
||||
manageAntennas: "Administri antenojn"
|
||||
name: "Nomo"
|
||||
antennaSource: "Fonto de la anteno"
|
||||
notifyAntenna: "Oni sciigos novajn notojn"
|
||||
withFileAntenna: "Nur kun aldonaĵo"
|
||||
withReplies: "Inkluzive respondoj"
|
||||
|
@ -311,6 +332,7 @@ userList: "Listoj"
|
|||
about: "Informoj"
|
||||
aboutMisskey: "Pri Misskey"
|
||||
administrator: "Administranto"
|
||||
token: "Ĵetono"
|
||||
twoStepAuthentication: "Dua-faktora aŭtentiko"
|
||||
moderator: "Kontrolisto"
|
||||
nUsersMentioned: "{n} uzanto(j) menciis"
|
||||
|
@ -331,6 +353,8 @@ close: "Fermi"
|
|||
group: "Grupo"
|
||||
groups: "Grupoj"
|
||||
createGroup: "Krei grupon"
|
||||
ownedGroups: "Administrataj grupoj"
|
||||
joinedGroups: "La grupoj kiujn la uzanto aliĝis"
|
||||
invites: "Inviti"
|
||||
groupName: "Grupa nomo"
|
||||
members: "Membroj"
|
||||
|
@ -390,6 +414,7 @@ showInPage: "Vidi en paĝo"
|
|||
popout: "Superigi"
|
||||
volume: "Laŭteco"
|
||||
masterVolume: "Baza laŭteco"
|
||||
details: "Detaloj"
|
||||
chooseEmoji: "Elekti emoĵion"
|
||||
recentUsed: "Lastatempaj uzitaj"
|
||||
install: "Instali"
|
||||
|
@ -400,11 +425,13 @@ installedDate: "Dato de instalado"
|
|||
lastUsedDate: "Lastfoje uzita je"
|
||||
state: "Stato"
|
||||
sort: "Ordigado"
|
||||
scratchpad: "Malneta redaktilo"
|
||||
output: "Elmeto"
|
||||
script: "Skripto"
|
||||
disablePagesScript: "Malebligi AiScripto en la paĝoj"
|
||||
deleteAllFiles: "Forviŝi ĉiujn dosierojn"
|
||||
deleteAllFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn dosierojn?"
|
||||
removeAllFollowing: "Ĉesi sekvi ĉiujn sekvatojn"
|
||||
userSuspended: "Ĉi tiu uzanto estas flostigita."
|
||||
userSilenced: "Ĉi tiu uzanto estas mutigita."
|
||||
menu: "Menuo"
|
||||
|
@ -512,7 +539,7 @@ editCode: "Redakti kodon"
|
|||
emailNotification: "Sciigoj per retpoŝto"
|
||||
inChannelSearch: "Serĉi en kanalo"
|
||||
useReactionPickerForContextMenu: "Malfermi reago-elektilon per dekstro-klaki"
|
||||
typingUsers: "{users} nun entajpas…"
|
||||
typingUsers: "{users} nun skribas…"
|
||||
clear: "Vakigi"
|
||||
goBack: "Reiri antaŭ"
|
||||
addDescription: "Priskribi"
|
||||
|
@ -544,12 +571,12 @@ translate: "Traduki"
|
|||
translatedFrom: "Tradukita el {x}"
|
||||
controlPanel: "Ŝaltpodio"
|
||||
classic: "Klasika"
|
||||
_docs:
|
||||
continueReading: "Legi plu"
|
||||
features: "Funkcioj"
|
||||
admin: "Administro"
|
||||
_signup:
|
||||
emailAddressInfo: "Entajpu vian retpoŝton"
|
||||
_ad:
|
||||
back: "Nuligi"
|
||||
_forgotPassword:
|
||||
enterEmail: "Entajpu la retpoŝton kiun vi registrigis al via konto. Ligilo por restarigi pasvorton estos sendita al la retpoŝto."
|
||||
_gallery:
|
||||
liked: "Ŝatitaj notoj"
|
||||
like: "Ŝati"
|
||||
|
@ -648,7 +675,7 @@ _ago:
|
|||
secondsAgo: "Antaŭ {n} sekundo(j)"
|
||||
minutesAgo: "Antaŭ {n} minutoj"
|
||||
hoursAgo: "Antaŭ {n} horo(j)"
|
||||
daysAgo: "Antaŭ {n} tagoj"
|
||||
daysAgo: "Antaŭ {n} tago(j)"
|
||||
weeksAgo: "Antaŭ {n} semajnoj"
|
||||
monthsAgo: "Antaŭ {n} monatoj"
|
||||
yearsAgo: "Antaŭ {n} jaroj"
|
||||
|
@ -702,7 +729,7 @@ _widgets:
|
|||
timeline: "Templinio"
|
||||
clock: "Horloĝo"
|
||||
activity: "Aktiveco"
|
||||
federation: "Kunfederaĵo"
|
||||
federation: "Federaĵo"
|
||||
slideshow: "Bildoprezento"
|
||||
button: "Butono"
|
||||
onlineUsers: "Surkonektita uzanto"
|
||||
|
@ -761,6 +788,8 @@ _timelines:
|
|||
_rooms:
|
||||
translate: "Movi"
|
||||
chooseImage: "Elekti bildon"
|
||||
_roomType:
|
||||
default: "Defaŭlta"
|
||||
_furnitures:
|
||||
bed: "Lito"
|
||||
low-table: "Malaltotablo"
|
||||
|
@ -790,10 +819,12 @@ _pages:
|
|||
featured: "Ravaĵoj"
|
||||
contents: "Enhavo"
|
||||
content: "Paĝo en bloko"
|
||||
title: "Temlinio"
|
||||
url: "URL de paĝo"
|
||||
alignCenter: "Centrigi"
|
||||
chooseBlock: "Aldoni blokon"
|
||||
contentBlocks: "Enhavo"
|
||||
inputBlocks: "Enigo"
|
||||
blocks:
|
||||
text: "Teksto"
|
||||
textarea: "Areo de teksto"
|
||||
|
@ -802,7 +833,11 @@ _pages:
|
|||
_post:
|
||||
canvasId: "Kanvasa identigilo"
|
||||
textInput: "Enmeto el teksto"
|
||||
_textInput:
|
||||
text: "Titolo"
|
||||
textareaInput: "Enmeto el teksto en multaj linioj"
|
||||
_textareaInput:
|
||||
text: "Titolo"
|
||||
numberInput: "Nombra enmeto"
|
||||
_numberInput:
|
||||
text: "Titolo"
|
||||
|
@ -810,6 +845,8 @@ _pages:
|
|||
id: "Kanvasa identigilo"
|
||||
_note:
|
||||
id: "Identigilo de noto"
|
||||
_switch:
|
||||
text: "Titolo"
|
||||
_counter:
|
||||
text: "Titolo"
|
||||
_button:
|
||||
|
@ -817,6 +854,8 @@ _pages:
|
|||
_action:
|
||||
_pushEvent:
|
||||
event: "Nomo de la evento"
|
||||
_radioButton:
|
||||
title: "Titolo"
|
||||
script:
|
||||
categories:
|
||||
text: "Manipulo de teksto"
|
||||
|
@ -862,6 +901,9 @@ _pages:
|
|||
stringArray: "List de teksto"
|
||||
emptySlot: "Malplena junto"
|
||||
argVariables: "Eniga junto"
|
||||
_relayStatus:
|
||||
requesting: "Atendado de aprobon"
|
||||
accepted: "Konfirmita"
|
||||
_notification:
|
||||
fileUploaded: "La dosiero sukcese alŝutiĝis."
|
||||
youGotMention: "{name} mencis"
|
||||
|
@ -891,5 +933,5 @@ _deck:
|
|||
tl: "Templinio"
|
||||
antenna: "Antenoj"
|
||||
list: "Listoj"
|
||||
mentions: "Al vi"
|
||||
mentions: "Mencioj"
|
||||
direct: "Rekte"
|
||||
|
|
|
@ -739,8 +739,6 @@ resolved: "Resuelto"
|
|||
unresolved: "Sin resolver"
|
||||
_accountDelete:
|
||||
accountDelete: "Eliminar Cuenta"
|
||||
_docs:
|
||||
admin: "Administrar"
|
||||
_ad:
|
||||
back: "Deseleccionar"
|
||||
_gallery:
|
||||
|
|
|
@ -745,10 +745,8 @@ global: "Federata"
|
|||
sent: "Inviare"
|
||||
hashtags: "Hashtag"
|
||||
troubleshooting: "Risoluzione problemi"
|
||||
_docs:
|
||||
continueReading: "Leggi di più"
|
||||
features: "Funzionalità"
|
||||
admin: "Gestione"
|
||||
_ffVisibility:
|
||||
public: "Pubblico"
|
||||
_ad:
|
||||
back: "Indietro"
|
||||
reduceFrequencyOfThisAd: "Visualizza questa pubblicità meno spesso"
|
||||
|
|
|
@ -806,6 +806,8 @@ muteThread: "スレッドをミュート"
|
|||
unmuteThread: "スレッドのミュートを解除"
|
||||
ffVisibility: "つながりの公開範囲"
|
||||
ffVisibilityDescription: "自分のフォロー/フォロワー情報の公開範囲を設定できます。"
|
||||
continueThread: "さらにスレッドを見る"
|
||||
deleteAccountConfirm: "アカウントが削除されます。よろしいですか?"
|
||||
|
||||
_emailUnavailable:
|
||||
used: "既に使用されています"
|
||||
|
|
|
@ -653,8 +653,6 @@ low: "低い"
|
|||
global: "グローバル"
|
||||
sent: "送信"
|
||||
hashtags: "ハッシュタグ"
|
||||
_docs:
|
||||
admin: "管理"
|
||||
_ad:
|
||||
back: "戻る"
|
||||
_gallery:
|
||||
|
|
|
@ -788,6 +788,8 @@ lastCommunication: "마지막 통신"
|
|||
resolved: "해결됨"
|
||||
unresolved: "해결되지 않음"
|
||||
controlPanel: "제어판"
|
||||
_ffVisibility:
|
||||
public: "게시"
|
||||
_accountDelete:
|
||||
accountDelete: "계정 삭제"
|
||||
mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다."
|
||||
|
@ -795,13 +797,6 @@ _accountDelete:
|
|||
requestAccountDelete: "계정 삭제 요청"
|
||||
started: "삭제 작업이 시작되었습니다."
|
||||
inProgress: "삭제 진행 중"
|
||||
_docs:
|
||||
continueReading: "계속 읽기"
|
||||
features: "기능"
|
||||
generalTopics: "일반 주제"
|
||||
advancedTopics: "심화 주제"
|
||||
admin: "관리"
|
||||
translateWarn: "이 문서는 번역되었기 때문에 원본과는 내용이 다를 수 있습니다."
|
||||
_ad:
|
||||
back: "뒤로"
|
||||
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
---
|
||||
_lang_: "Nederlands"
|
||||
headlineMisskey: "Netwerk verbonden door notities"
|
||||
muteThread: "Discussies dempen "
|
||||
unmuteThread: "Dempen van discussie ongedaan maken"
|
||||
|
|
|
@ -738,8 +738,8 @@ ratio: "Stosunek"
|
|||
global: "Globalna"
|
||||
sent: "Wyślij"
|
||||
hashtags: "Hashtag"
|
||||
_docs:
|
||||
admin: "Zarządzanie"
|
||||
_ffVisibility:
|
||||
public: "Publikuj"
|
||||
_ad:
|
||||
back: "Wróć"
|
||||
reduceFrequencyOfThisAd: "Pokazuj tę reklamę rzadziej"
|
||||
|
|
|
@ -620,6 +620,8 @@ reportAbuse: "Жалоба"
|
|||
reportAbuseOf: "Пожаловаться на пользователя {name}"
|
||||
fillAbuseReportDescription: "Опишите, пожалуйста, причину жалобы подробнее. Если речь о конкретной заметке, будьте добры приложить ссылку на неё."
|
||||
abuseReported: "Жалоба отправлена. Большое спасибо за информацию."
|
||||
reporteeOrigin: "Куда сообщать"
|
||||
reporterOrigin: "Сообщено"
|
||||
send: "Отправить"
|
||||
abuseMarkAsResolved: "Отметить жалобу как решённую"
|
||||
openInNewTab: "Открыть в новой вкладке"
|
||||
|
@ -766,6 +768,7 @@ middle: "Средне"
|
|||
low: "Низкий"
|
||||
emailNotConfiguredWarning: "Не указан адрес электронной почты"
|
||||
ratio: "Соотношение"
|
||||
previewNoteText: "Предварительный просмотр текста"
|
||||
customCss: "Индивидуальный CSS"
|
||||
customCssWarn: "Используйте эту настройку только если знаете, что делаете. Ошибки здесь чреваты тем, что сайт перестанет нормально работать у вас."
|
||||
global: "Всеобщая"
|
||||
|
@ -780,19 +783,43 @@ learnMore: "Подробнее"
|
|||
misskeyUpdated: "Misskey обновился!"
|
||||
whatIsNew: "Что новенького?"
|
||||
translate: "Перевод"
|
||||
translatedFrom: "{x}Перевод с английского"
|
||||
accountDeletionInProgress: "В настоящее время выполняется удаление учетной записи"
|
||||
usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже."
|
||||
aiChanMode: "ИИ режим"
|
||||
keepCw: "Сохраняйте Предупреждения о содержимом"
|
||||
lastCommunication: "Последнее сообщение"
|
||||
resolved: "Решен"
|
||||
unresolved: "Неразрешенные"
|
||||
itsOff: "Он выключен!"
|
||||
emailRequiredForSignup: "Требуется адрес электронной почты для регистрации аккаунта"
|
||||
unread: "Непрочитанное"
|
||||
filter: "Фильтры"
|
||||
controlPanel: "Панель управления"
|
||||
manageAccounts: "Управление аккаунтом"
|
||||
_docs:
|
||||
continueReading: "Читать подробнее"
|
||||
features: "Возможности"
|
||||
generalTopics: "Основные темы"
|
||||
advancedTopics: "Дополнительные темы"
|
||||
admin: "Управление"
|
||||
translateWarn: "Это перевод документа. Он может неточно отражать содержимое оригинала."
|
||||
makeReactionsPublic: "Опубликовать список реакций"
|
||||
makeReactionsPublicDescription: "Список сделанных вами реакций доступен для просмотра всем желающим."
|
||||
classic: "Классика"
|
||||
unmuteThread: "Отключить звук"
|
||||
ffVisibilityDescription: "Вы можете установить объем вашей следующей/последней информации."
|
||||
_emailUnavailable:
|
||||
used: "Уже используется"
|
||||
format: "Неправильный формат"
|
||||
smtp: "Почтовый сервер не отвечает"
|
||||
_ffVisibility:
|
||||
public: "Опубликовать"
|
||||
private: "Частный"
|
||||
_signup:
|
||||
almostThere: "Почти готово!"
|
||||
emailAddressInfo: "Пожалуйста, введите адрес электронной почты, который вы используете."
|
||||
emailSent: "На указанный вами адрес электронной почты ({email}) было отправлено письмо с подтверждением. Перейдите по ссылке в электронном письме, чтобы завершить создание учетной записи."
|
||||
_accountDelete:
|
||||
accountDelete: "Удалить свой аккаунт"
|
||||
mayTakeTime: "Удаление учетной записи - это тяжелый процесс, который может занять много времени, если у вас создано много контента или загружено много файлов."
|
||||
sendEmail: "Мы отправим уведомление на зарегистрированный вами адрес электронной почты, когда ваша учетная запись будет удалена."
|
||||
requestAccountDelete: "Запросить удаление вашей учетной записи"
|
||||
started: "Процесс удаления начался."
|
||||
inProgress: "Удаление в процессе"
|
||||
_ad:
|
||||
back: "Выход"
|
||||
reduceFrequencyOfThisAd: "Реже показывать эту рекламу"
|
||||
|
@ -893,6 +920,8 @@ _mfm:
|
|||
fontDescription: "Так можно писать произвольным шрифтом."
|
||||
rainbow: "Радуга"
|
||||
rainbowDescription: "Заставлять содержимое отображаться в цветах радуги."
|
||||
sparkle: "Блеск"
|
||||
sparkleDescription: "Добавьте эффект искрящихся частиц."
|
||||
_reversi:
|
||||
reversi: "Реверси"
|
||||
gameSettings: "Настройки игры"
|
||||
|
@ -1119,6 +1148,10 @@ _permissions:
|
|||
"write:user-groups": "Изменять и удалять группы пользователей"
|
||||
"read:channels": "Смотреть каналы"
|
||||
"write:channels": "Изменять каналы"
|
||||
"read:gallery": "Смотреть галерею"
|
||||
"write:gallery": "Работа с галереей"
|
||||
"read:gallery-likes": "Посмотреть галерею лайков"
|
||||
"write:gallery-likes": "Манипулируйте понравившейся галереей"
|
||||
_auth:
|
||||
shareAccess: "Дать доступ для «{name}» к вашей учётной записи?"
|
||||
shareAccessAsk: "Уверены, что хотите дать приложению доступ к своей учётной записи?"
|
||||
|
|
|
@ -692,8 +692,6 @@ middle: "Середній"
|
|||
global: "Глобальна"
|
||||
sent: "Відправити"
|
||||
hashtags: "Хештеґ"
|
||||
_docs:
|
||||
admin: "Управління"
|
||||
_ad:
|
||||
back: "Назад"
|
||||
_gallery:
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
_lang_: "中文(简体)"
|
||||
headlineMisskey: "通过帖子连接在一起的网络"
|
||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖子」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖子表达反馈👍\n来探索新的世界吧!🚀"
|
||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖文」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖文表达反馈👍\n来探索新的世界吧!🚀"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜索"
|
||||
notifications: "通知"
|
||||
username: "用户名"
|
||||
password: "密码"
|
||||
forgotPassword: "重置密码"
|
||||
fetchingAsApObject: "联合查询中"
|
||||
forgotPassword: "忘记密码"
|
||||
fetchingAsApObject: "联合查询"
|
||||
ok: "OK"
|
||||
gotIt: "我明白了"
|
||||
cancel: "取消"
|
||||
enterUsername: "输入用户名"
|
||||
renotedBy: "{user} 转发了"
|
||||
noNotes: "没有帖子"
|
||||
renotedBy: "由 {user} 转推"
|
||||
noNotes: "没有帖文"
|
||||
noNotifications: "无通知"
|
||||
instance: "实例"
|
||||
settings: "设置"
|
||||
|
@ -124,9 +124,9 @@ unblockConfirm: "确定要解除拉黑吗?"
|
|||
suspendConfirm: "要冻结吗?"
|
||||
unsuspendConfirm: "要解除冻结吗?"
|
||||
selectList: "选择列表"
|
||||
selectAntenna: "天线选择"
|
||||
selectAntenna: "选择天线"
|
||||
selectWidget: "选择小工具"
|
||||
editWidgets: "编辑小工具"
|
||||
editWidgets: "编辑部件"
|
||||
editWidgetsExit: "完成编辑"
|
||||
customEmojis: "自定义表情符号"
|
||||
emoji: "表情符号"
|
||||
|
@ -139,9 +139,9 @@ cacheRemoteFiles: "远程文件缓存"
|
|||
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
||||
flagAsBot: "这是一个机器人账号"
|
||||
flagAsBotDescription: "如果此帐户由程序控制,请启用此项。启用后,此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为,并让Misskey的内部系统将此帐户识别为机器人。"
|
||||
flagAsCat: "这个账户是一只猫"
|
||||
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。\n开启后,会在您的头像上出现猫耳朵,并将你的帖子中的「na」替换为「nya」,日文同理。"
|
||||
autoAcceptFollowed: "自动允许关注者的关注"
|
||||
flagAsCat: "将这个账户设定为一只猫"
|
||||
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。"
|
||||
autoAcceptFollowed: "自动允许关注"
|
||||
addAccount: "添加账户"
|
||||
loginFailed: "登录失败"
|
||||
showOnRemote: "转到所在实例显示"
|
||||
|
@ -620,6 +620,8 @@ reportAbuse: "举报"
|
|||
reportAbuseOf: "举报{name}"
|
||||
fillAbuseReportDescription: "请填写举报的详细原因。如果有对方发的帖子,请同时填写URL地址。"
|
||||
abuseReported: "内容已发送。感谢您的报告。"
|
||||
reporteeOrigin: "举报来源"
|
||||
reporterOrigin: "举报者来源"
|
||||
send: "发送"
|
||||
abuseMarkAsResolved: "处理完毕"
|
||||
openInNewTab: "在新标签页中打开"
|
||||
|
@ -797,7 +799,25 @@ unread: "未读"
|
|||
filter: "筛选"
|
||||
controlPanel: "控制面板"
|
||||
manageAccounts: "管理账户"
|
||||
makeReactionsPublic: "将回应设置为公开"
|
||||
makeReactionsPublicDescription: "将您发表过的回应设置成公开可见。"
|
||||
classic: "经典"
|
||||
muteThread: "屏蔽帖子列表"
|
||||
unmuteThread: "取消屏蔽帖子列表"
|
||||
ffVisibility: "连接的可见范围"
|
||||
ffVisibilityDescription: "您可以设置您的关注/关注者信息的公开范围"
|
||||
continueThread: "查看更多帖子"
|
||||
deleteAccountConfirm: "将要删除账户。是否确认?"
|
||||
_emailUnavailable:
|
||||
used: "已经被使用过"
|
||||
format: "无效的格式"
|
||||
disposable: "不是永久可用的地址"
|
||||
mx: "邮件服务器不正确"
|
||||
smtp: "邮件服务器没有响应"
|
||||
_ffVisibility:
|
||||
public: "发布"
|
||||
followers: "只有关注你的用户能看到"
|
||||
private: "私密"
|
||||
_signup:
|
||||
almostThere: "即将完成"
|
||||
emailAddressInfo: "请输入您所使用的电子邮件地址"
|
||||
|
@ -809,13 +829,6 @@ _accountDelete:
|
|||
requestAccountDelete: "请求删除账户"
|
||||
started: "账户删除过程已开始。"
|
||||
inProgress: "正在删除"
|
||||
_docs:
|
||||
continueReading: "继续阅读"
|
||||
features: "特性"
|
||||
generalTopics: "通常提示"
|
||||
advancedTopics: "进阶提示"
|
||||
admin: "管理"
|
||||
translateWarn: "本文档是翻译后的文档。内容可能与原文有所不同。"
|
||||
_ad:
|
||||
back: "返回"
|
||||
reduceFrequencyOfThisAd: "减少此广告的频率"
|
||||
|
|
|
@ -754,8 +754,8 @@ ratio: "%"
|
|||
global: "公開"
|
||||
sent: "發送"
|
||||
hashtags: "#tag"
|
||||
_docs:
|
||||
admin: "管理"
|
||||
_ffVisibility:
|
||||
public: "發佈"
|
||||
_ad:
|
||||
back: "返回"
|
||||
reduceFrequencyOfThisAd: "降低此廣告的頻率 "
|
||||
|
|
13
package.json
13
package.json
|
@ -17,10 +17,8 @@
|
|||
"migrate": "cd packages/backend && npx typeorm migration:run",
|
||||
"migrateandstart": "npm run migrate && npm run start",
|
||||
"gulp": "gulp build",
|
||||
"watch": "concurrently \"npm:watch-*\"",
|
||||
"watch-webpack": "webpack --watch",
|
||||
"watch-ts": "tsc -w -p packages/tsconfig.json && tsc-alias -w -p packages/tsconfig.json",
|
||||
"watch-gulp": "gulp watch",
|
||||
"watch": "npm run dev",
|
||||
"dev": "node ./scripts/dev.js",
|
||||
"lint": "node ./scripts/lint.js",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
|
@ -40,13 +38,16 @@
|
|||
"gulp-cssnano": "2.1.3",
|
||||
"gulp-rename": "2.0.0",
|
||||
"gulp-replace": "1.1.3",
|
||||
"gulp-terser": "2.1.0"
|
||||
"gulp-terser": "2.1.0",
|
||||
"js-yaml": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redocly/openapi-core": "1.0.0-beta.54",
|
||||
"@types/fluent-ffmpeg": "2.1.17",
|
||||
"@typescript-eslint/parser": "5.4.0",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "9.0.0",
|
||||
"start-server-and-test": "1.14.0"
|
||||
"start-server-and-test": "1.14.0",
|
||||
"typescript": "4.5.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,64 +1,9 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
'import'
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript'
|
||||
'../shared/.eslintrc.js',
|
||||
],
|
||||
rules: {
|
||||
'indent': ['warn', 'tab', {
|
||||
'SwitchCase': 1,
|
||||
'MemberExpression': 'off',
|
||||
'flatTernaryExpressions': true,
|
||||
'ArrayExpression': 'first',
|
||||
'ObjectExpression': 'first',
|
||||
}],
|
||||
'eol-last': ['error', 'always'],
|
||||
'semi': ['error', 'always'],
|
||||
'quotes': ['warn', 'single'],
|
||||
'comma-dangle': ['warn', 'always-multiline'],
|
||||
'keyword-spacing': ['error', {
|
||||
'before': true,
|
||||
'after': true,
|
||||
}],
|
||||
/* TODO: path aliasを使わないとwarnする
|
||||
'no-restricted-imports': ['warn', {
|
||||
'patterns': [
|
||||
]
|
||||
}],
|
||||
*/
|
||||
'no-multi-spaces': ['error'],
|
||||
'no-var': ['error'],
|
||||
'prefer-arrow-callback': ['error'],
|
||||
'no-throw-literal': ['warn'],
|
||||
'no-param-reassign': ['warn'],
|
||||
'no-constant-condition': ['warn'],
|
||||
'no-empty-pattern': ['warn'],
|
||||
'no-async-promise-executor': ['off'],
|
||||
'no-useless-escape': ['off'],
|
||||
'no-multi-spaces': ['warn'],
|
||||
'no-control-regex': ['warn'],
|
||||
'no-empty': ['warn'],
|
||||
'no-inner-declarations': ['off'],
|
||||
'no-sparse-arrays': ['off'],
|
||||
'@typescript-eslint/no-var-requires': ['warn'],
|
||||
'@typescript-eslint/no-inferrable-types': ['warn'],
|
||||
'@typescript-eslint/no-empty-function': ['off'],
|
||||
'@typescript-eslint/no-non-null-assertion': ['off'],
|
||||
'@typescript-eslint/no-misused-promises': ['error', {
|
||||
'checksVoidReturn': false,
|
||||
}],
|
||||
'import/no-unresolved': ['off'],
|
||||
'import/no-default-export': ['warn'],
|
||||
},
|
||||
};
|
||||
|
|
6
packages/backend/.vscode/settings.json
vendored
Normal file
6
packages/backend/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib",
|
||||
"path-intellisense.mappings": {
|
||||
"@": "${workspaceRoot}/packages/backend/src/"
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"scripts": {
|
||||
"init": "npm run migrate",
|
||||
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json",
|
||||
"watch": "tsc -w -p tsconfig.json && tsc-alias -w -p tsconfig.json",
|
||||
"watch": "node watch.mjs",
|
||||
"lint": "eslint --quiet src/**/*.ts",
|
||||
"mocha": "cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
|
||||
"test": "npm run mocha"
|
||||
|
@ -179,7 +179,7 @@
|
|||
"tmp": "0.2.1",
|
||||
"ts-loader": "9.2.6",
|
||||
"ts-node": "10.4.0",
|
||||
"tsc-alias": "1.3.10",
|
||||
"tsc-alias": "1.4.1",
|
||||
"tsconfig-paths": "3.11.0",
|
||||
"twemoji-parser": "13.1.0",
|
||||
"typeorm": "0.2.39",
|
||||
|
@ -194,6 +194,7 @@
|
|||
"devDependencies": {
|
||||
"@redocly/openapi-core": "1.0.0-beta.54",
|
||||
"@types/fluent-ffmpeg": "2.1.17",
|
||||
"cross-env": "7.0.3"
|
||||
"cross-env": "7.0.3",
|
||||
"execa": "6.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,8 +82,7 @@ export default class Reversi {
|
|||
//#endregion
|
||||
|
||||
// ゲームが始まった時点で片方の色の石しかないか、始まった時点で勝敗が決定するようなマップの場合がある
|
||||
if (!this.canPutSomewhere(BLACK))
|
||||
this.turn = this.canPutSomewhere(WHITE) ? WHITE : null;
|
||||
if (!this.canPutSomewhere(BLACK)) this.turn = this.canPutSomewhere(WHITE) ? WHITE : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -226,11 +225,12 @@ export default class Reversi {
|
|||
// 座標が指し示す位置がボード外に出たとき
|
||||
if (this.opts.loopedBoard && this.transformXyToPos(
|
||||
(x = ((x % this.mapWidth) + this.mapWidth) % this.mapWidth),
|
||||
(y = ((y % this.mapHeight) + this.mapHeight) % this.mapHeight)) === initPos)
|
||||
(y = ((y % this.mapHeight) + this.mapHeight) % this.mapHeight)) === initPos) {
|
||||
// 盤面の境界でループし、自分が石を置く位置に戻ってきたとき、挟めるようにしている (ref: Test4のマップ)
|
||||
return found;
|
||||
else if (x === -1 || y === -1 || x === this.mapWidth || y === this.mapHeight)
|
||||
} else if (x === -1 || y === -1 || x === this.mapWidth || y === this.mapHeight) {
|
||||
return []; // 挟めないことが確定 (盤面外に到達)
|
||||
}
|
||||
|
||||
const pos = this.transformXyToPos(x, y);
|
||||
if (this.mapDataGet(pos) === 'null') return []; // 挟めないことが確定 (配置不可能なマスに到達)
|
||||
|
|
|
@ -54,7 +54,7 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
|
|||
|
||||
const queryOrNull = async () => (await Emojis.findOne({
|
||||
name,
|
||||
host
|
||||
host,
|
||||
})) || null;
|
||||
|
||||
const emoji = await cache.fetch(`${name} ${host}`, queryOrNull);
|
||||
|
@ -62,7 +62,7 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
|
|||
if (emoji == null) return null;
|
||||
|
||||
const isLocal = emoji.host == null;
|
||||
const url = isLocal ? emoji.url : `${config.url}/proxy/image.png?${query({url: emoji.url})}`;
|
||||
const url = isLocal ? emoji.url : `${config.url}/proxy/image.png?${query({ url: emoji.url })}`;
|
||||
|
||||
return {
|
||||
name: emojiName,
|
||||
|
@ -111,12 +111,12 @@ export async function prefetchEmojis(emojis: { name: string; host: string | null
|
|||
for (const host of hosts) {
|
||||
emojisQuery.push({
|
||||
name: In(notCachedEmojis.filter(e => e.host === host).map(e => e.name)),
|
||||
host: host
|
||||
host: host,
|
||||
});
|
||||
}
|
||||
const _emojis = emojisQuery.length > 0 ? await Emojis.find({
|
||||
where: emojisQuery,
|
||||
select: ['name', 'host', 'url']
|
||||
select: ['name', 'host', 'url'],
|
||||
}) : [];
|
||||
for (const emoji of _emojis) {
|
||||
cache.set(`${emoji.name} ${emoji.host}`, emoji);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable key-spacing */
|
||||
import { emojiRegex } from './emoji-regex';
|
||||
import { fetchMeta } from './fetch-meta';
|
||||
import { Emojis } from '@/models/index';
|
||||
|
|
|
@ -66,7 +66,7 @@ function signToRequest(request: Request, key: PrivateKey, includeHeaders: string
|
|||
const signatureHeader = `keyId="${key.keyId}",algorithm="rsa-sha256",headers="${includeHeaders.join(' ')}",signature="${signature}"`;
|
||||
|
||||
request.headers = objectAssignWithLcKey(request.headers, {
|
||||
Signature: signatureHeader
|
||||
Signature: signatureHeader,
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -163,7 +163,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||
uri: person.id,
|
||||
tags,
|
||||
isBot,
|
||||
isCat: (person as any).isCat === true
|
||||
isCat: (person as any).isCat === true,
|
||||
})) as IRemoteUser;
|
||||
|
||||
await transactionalEntityManager.save(new UserProfile({
|
||||
|
@ -173,14 +173,14 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||
fields,
|
||||
birthday: bday ? bday[0] : null,
|
||||
location: person['vcard:Address'] || null,
|
||||
userHost: host
|
||||
userHost: host,
|
||||
}));
|
||||
|
||||
if (person.publicKey) {
|
||||
await transactionalEntityManager.save(new UserPublickey({
|
||||
userId: user.id,
|
||||
keyId: person.publicKey.id,
|
||||
keyPem: person.publicKey.publicKeyPem
|
||||
keyPem: person.publicKey.publicKeyPem,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -189,7 +189,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||
if (isDuplicateKeyValueError(e)) {
|
||||
// /users/@a => /users/:id のように入力がaliasなときにエラーになることがあるのを対応
|
||||
const u = await Users.findOne({
|
||||
uri: person.id
|
||||
uri: person.id,
|
||||
});
|
||||
|
||||
if (u) {
|
||||
|
@ -218,11 +218,11 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||
//#region アバターとヘッダー画像をフェッチ
|
||||
const [avatar, banner] = await Promise.all([
|
||||
person.icon,
|
||||
person.image
|
||||
person.image,
|
||||
].map(img =>
|
||||
img == null
|
||||
? Promise.resolve(null)
|
||||
: resolveImage(user!, img).catch(() => null)
|
||||
: resolveImage(user!, img).catch(() => null),
|
||||
));
|
||||
|
||||
const avatarId = avatar ? avatar.id : null;
|
||||
|
@ -258,7 +258,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||
const emojiNames = emojis.map(emoji => emoji.name);
|
||||
|
||||
await Users.update(user!.id, {
|
||||
emojis: emojiNames
|
||||
emojis: emojiNames,
|
||||
});
|
||||
//#endregion
|
||||
|
||||
|
@ -301,11 +301,11 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
|||
// アバターとヘッダー画像をフェッチ
|
||||
const [avatar, banner] = await Promise.all([
|
||||
person.icon,
|
||||
person.image
|
||||
person.image,
|
||||
].map(img =>
|
||||
img == null
|
||||
? Promise.resolve(null)
|
||||
: resolveImage(exist, img).catch(() => null)
|
||||
: resolveImage(exist, img).catch(() => null),
|
||||
));
|
||||
|
||||
// カスタム絵文字取得
|
||||
|
@ -355,7 +355,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
|||
if (person.publicKey) {
|
||||
await UserPublickeys.update({ userId: exist.id }, {
|
||||
keyId: person.publicKey.id,
|
||||
keyPem: person.publicKey.publicKeyPem
|
||||
keyPem: person.publicKey.publicKeyPem,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -372,9 +372,9 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
|||
|
||||
// 該当ユーザーが既にフォロワーになっていた場合はFollowingもアップデートする
|
||||
await Followings.update({
|
||||
followerId: exist.id
|
||||
followerId: exist.id,
|
||||
}, {
|
||||
followerSharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined)
|
||||
followerSharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
|
||||
});
|
||||
|
||||
await updateFeatured(exist.id).catch(err => logger.error(err));
|
||||
|
@ -411,8 +411,9 @@ const services: {
|
|||
};
|
||||
|
||||
const $discord = (id: string, name: string) => {
|
||||
if (typeof name !== 'string')
|
||||
if (typeof name !== 'string') {
|
||||
name = 'unknown#0000';
|
||||
}
|
||||
const [username, discriminator] = name.split('#');
|
||||
return { id, username, discriminator };
|
||||
};
|
||||
|
@ -420,13 +421,15 @@ const $discord = (id: string, name: string) => {
|
|||
function addService(target: { [x: string]: any }, source: IApPropertyValue) {
|
||||
const service = services[source.name];
|
||||
|
||||
if (typeof source.value !== 'string')
|
||||
if (typeof source.value !== 'string') {
|
||||
source.value = 'unknown';
|
||||
}
|
||||
|
||||
const [id, username] = source.value.split('@');
|
||||
|
||||
if (service)
|
||||
if (service) {
|
||||
target[source.name.split(':')[2]] = service(id, username);
|
||||
}
|
||||
}
|
||||
|
||||
export function analyzeAttachments(attachments: IObject | IObject[] | undefined) {
|
||||
|
@ -443,7 +446,7 @@ export function analyzeAttachments(attachments: IObject | IObject[] | undefined)
|
|||
} else {
|
||||
fields.push({
|
||||
name: attachment.name,
|
||||
value: fromHtml(attachment.value)
|
||||
value: fromHtml(attachment.value),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +490,7 @@ export async function updateFeatured(userId: User['id']) {
|
|||
id: genId(new Date(Date.now() + td)),
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
noteId: note!.id
|
||||
noteId: note!.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ const ECC_PRELUDE = Buffer.from([0x04]);
|
|||
const NULL_BYTE = Buffer.from([0]);
|
||||
const PEM_PRELUDE = Buffer.from(
|
||||
'3059301306072a8648ce3d020106082a8648ce3d030107034200',
|
||||
'hex'
|
||||
'hex',
|
||||
);
|
||||
|
||||
// Android Safetynet attestations are signed with this cert:
|
||||
|
@ -68,7 +68,7 @@ function verifyCertificateChain(certificates: string[]) {
|
|||
const signatureHex = certificate.getSignatureValueHex();
|
||||
|
||||
// Verify against CA
|
||||
const Signature = new jsrsasign.KJUR.crypto.Signature({alg: algorithm});
|
||||
const Signature = new jsrsasign.KJUR.crypto.Signature({ alg: algorithm });
|
||||
Signature.init(CACert);
|
||||
Signature.updateHex(certStruct);
|
||||
valid = valid && !!Signature.verify(signatureHex); // true if CA signed the certificate
|
||||
|
@ -134,7 +134,7 @@ export function verifyLogin({
|
|||
|
||||
const verificationData = Buffer.concat(
|
||||
[authenticatorData, hash(clientDataJSON)],
|
||||
32 + authenticatorData.length
|
||||
32 + authenticatorData.length,
|
||||
);
|
||||
|
||||
return crypto
|
||||
|
@ -145,7 +145,7 @@ export function verifyLogin({
|
|||
|
||||
export const procedures = {
|
||||
none: {
|
||||
verify({publicKey}: {publicKey: Map<number, Buffer>}) {
|
||||
verify({ publicKey }: {publicKey: Map<number, Buffer>}) {
|
||||
const negTwo = publicKey.get(-2);
|
||||
|
||||
if (!negTwo || negTwo.length != 32) {
|
||||
|
@ -158,14 +158,14 @@ export const procedures = {
|
|||
|
||||
const publicKeyU2F = Buffer.concat(
|
||||
[ECC_PRELUDE, negTwo, negThree],
|
||||
1 + 32 + 32
|
||||
1 + 32 + 32,
|
||||
);
|
||||
|
||||
return {
|
||||
publicKey: publicKeyU2F,
|
||||
valid: true
|
||||
valid: true,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
'android-key': {
|
||||
verify({
|
||||
|
@ -174,7 +174,7 @@ export const procedures = {
|
|||
clientDataHash,
|
||||
publicKey,
|
||||
rpIdHash,
|
||||
credentialId
|
||||
credentialId,
|
||||
}: {
|
||||
attStmt: any,
|
||||
authenticatorData: Buffer,
|
||||
|
@ -189,7 +189,7 @@ export const procedures = {
|
|||
|
||||
const verificationData = Buffer.concat([
|
||||
authenticatorData,
|
||||
clientDataHash
|
||||
clientDataHash,
|
||||
]);
|
||||
|
||||
const attCert: Buffer = attStmt.x5c[0];
|
||||
|
@ -206,7 +206,7 @@ export const procedures = {
|
|||
|
||||
const publicKeyData = Buffer.concat(
|
||||
[ECC_PRELUDE, negTwo, negThree],
|
||||
1 + 32 + 32
|
||||
1 + 32 + 32,
|
||||
);
|
||||
|
||||
if (!attCert.equals(publicKeyData)) {
|
||||
|
@ -222,9 +222,9 @@ export const procedures = {
|
|||
|
||||
return {
|
||||
valid: isValid,
|
||||
publicKey: publicKeyData
|
||||
publicKey: publicKeyData,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
// what a stupid attestation
|
||||
'android-safetynet': {
|
||||
|
@ -234,7 +234,7 @@ export const procedures = {
|
|||
clientDataHash,
|
||||
publicKey,
|
||||
rpIdHash,
|
||||
credentialId
|
||||
credentialId,
|
||||
}: {
|
||||
attStmt: any,
|
||||
authenticatorData: Buffer,
|
||||
|
@ -244,14 +244,14 @@ export const procedures = {
|
|||
credentialId: Buffer,
|
||||
}) {
|
||||
const verificationData = hash(
|
||||
Buffer.concat([authenticatorData, clientDataHash])
|
||||
Buffer.concat([authenticatorData, clientDataHash]),
|
||||
);
|
||||
|
||||
const jwsParts = attStmt.response.toString('utf-8').split('.');
|
||||
|
||||
const header = JSON.parse(base64URLDecode(jwsParts[0]).toString('utf-8'));
|
||||
const response = JSON.parse(
|
||||
base64URLDecode(jwsParts[1]).toString('utf-8')
|
||||
base64URLDecode(jwsParts[1]).toString('utf-8'),
|
||||
);
|
||||
const signature = jwsParts[2];
|
||||
|
||||
|
@ -273,7 +273,7 @@ export const procedures = {
|
|||
|
||||
const signatureBase = Buffer.from(
|
||||
jwsParts[0] + '.' + jwsParts[1],
|
||||
'utf-8'
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const valid = crypto
|
||||
|
@ -293,13 +293,13 @@ export const procedures = {
|
|||
|
||||
const publicKeyData = Buffer.concat(
|
||||
[ECC_PRELUDE, negTwo, negThree],
|
||||
1 + 32 + 32
|
||||
1 + 32 + 32,
|
||||
);
|
||||
return {
|
||||
valid,
|
||||
publicKey: publicKeyData
|
||||
publicKey: publicKeyData,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
packed: {
|
||||
verify({
|
||||
|
@ -308,7 +308,7 @@ export const procedures = {
|
|||
clientDataHash,
|
||||
publicKey,
|
||||
rpIdHash,
|
||||
credentialId
|
||||
credentialId,
|
||||
}: {
|
||||
attStmt: any,
|
||||
authenticatorData: Buffer,
|
||||
|
@ -319,7 +319,7 @@ export const procedures = {
|
|||
}) {
|
||||
const verificationData = Buffer.concat([
|
||||
authenticatorData,
|
||||
clientDataHash
|
||||
clientDataHash,
|
||||
]);
|
||||
|
||||
if (attStmt.x5c) {
|
||||
|
@ -342,12 +342,12 @@ export const procedures = {
|
|||
|
||||
const publicKeyData = Buffer.concat(
|
||||
[ECC_PRELUDE, negTwo, negThree],
|
||||
1 + 32 + 32
|
||||
1 + 32 + 32,
|
||||
);
|
||||
|
||||
return {
|
||||
valid: validSignature,
|
||||
publicKey: publicKeyData
|
||||
publicKey: publicKeyData,
|
||||
};
|
||||
} else if (attStmt.ecdaaKeyId) {
|
||||
// https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-ecdaa-algorithm-v2.0-id-20180227.html#ecdaa-verify-operation
|
||||
|
@ -357,7 +357,7 @@ export const procedures = {
|
|||
|
||||
throw new Error('self attestation is not supported');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
'fido-u2f': {
|
||||
|
@ -367,7 +367,7 @@ export const procedures = {
|
|||
clientDataHash,
|
||||
publicKey,
|
||||
rpIdHash,
|
||||
credentialId
|
||||
credentialId,
|
||||
}: {
|
||||
attStmt: any,
|
||||
authenticatorData: Buffer,
|
||||
|
@ -397,7 +397,7 @@ export const procedures = {
|
|||
|
||||
const publicKeyU2F = Buffer.concat(
|
||||
[ECC_PRELUDE, negTwo, negThree],
|
||||
1 + 32 + 32
|
||||
1 + 32 + 32,
|
||||
);
|
||||
|
||||
const verificationData = Buffer.concat([
|
||||
|
@ -405,7 +405,7 @@ export const procedures = {
|
|||
rpIdHash,
|
||||
clientDataHash,
|
||||
credentialId,
|
||||
publicKeyU2F
|
||||
publicKeyU2F,
|
||||
]);
|
||||
|
||||
const validSignature = crypto
|
||||
|
@ -415,8 +415,8 @@ export const procedures = {
|
|||
|
||||
return {
|
||||
valid: validSignature,
|
||||
publicKey: publicKeyU2F
|
||||
publicKey: publicKeyU2F,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -244,8 +244,9 @@ export default define(meta, async (ps, user) => {
|
|||
|
||||
if (ps.poll) {
|
||||
if (typeof ps.poll.expiresAt === 'number') {
|
||||
if (ps.poll.expiresAt < Date.now())
|
||||
if (ps.poll.expiresAt < Date.now()) {
|
||||
throw new ApiError(meta.errors.cannotCreateAlreadyExpiredPoll);
|
||||
}
|
||||
} else if (typeof ps.poll.expiredAfter === 'number') {
|
||||
ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter;
|
||||
}
|
||||
|
|
|
@ -112,8 +112,9 @@ export default define(meta, async (ps, user) => {
|
|||
|
||||
if (exist.length) {
|
||||
if (poll.multiple) {
|
||||
if (exist.some(x => x.choice == ps.choice))
|
||||
if (exist.some(x => x.choice == ps.choice)) {
|
||||
throw new ApiError(meta.errors.alreadyVoted);
|
||||
}
|
||||
} else {
|
||||
throw new ApiError(meta.errors.alreadyVoted);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ router.get('/disconnect/github', async ctx => {
|
|||
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
token: userToken,
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
@ -58,7 +58,7 @@ router.get('/disconnect/github', async ctx => {
|
|||
// Publish i updated event
|
||||
publishMainStream(user.id, 'meUpdated', await Users.pack(user, user, {
|
||||
detail: true,
|
||||
includeSecrets: true
|
||||
includeSecrets: true,
|
||||
}));
|
||||
});
|
||||
|
||||
|
@ -209,12 +209,13 @@ router.get('/gh/cb', async ctx => {
|
|||
code,
|
||||
{ redirect_uri },
|
||||
(err, accessToken, refresh, result) => {
|
||||
if (err)
|
||||
if (err) {
|
||||
rej(err);
|
||||
else if (result.error)
|
||||
} else if (result.error) {
|
||||
rej(result.error);
|
||||
else
|
||||
} else {
|
||||
res({ accessToken });
|
||||
}
|
||||
}));
|
||||
|
||||
const { login, id } = await getJson('https://api.github.com/user', 'application/vnd.github.v3+json', 10 * 1000, {
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
localStorage.setItem('lang', lang);
|
||||
localStorage.setItem('locale', await res.text());
|
||||
localStorage.setItem('localeVersion', v);
|
||||
} else if (localeOutdated) {
|
||||
// nop
|
||||
} else {
|
||||
await checkUpdate();
|
||||
renderError('LOCALE_FETCH_FAILED');
|
||||
|
|
|
@ -41,8 +41,8 @@ router.get('/.well-known/host-meta', async ctx => {
|
|||
ctx.set('Content-Type', xrd);
|
||||
ctx.body = XRD({ element: 'Link', attributes: {
|
||||
type: xrd,
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`
|
||||
}});
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`,
|
||||
} });
|
||||
});
|
||||
|
||||
router.get('/.well-known/host-meta.json', async ctx => {
|
||||
|
@ -51,8 +51,8 @@ router.get('/.well-known/host-meta.json', async ctx => {
|
|||
links: [{
|
||||
rel: 'lrdd',
|
||||
type: jrd,
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`
|
||||
}]
|
||||
template: `${config.url}${webFingerPath}?resource={uri}`,
|
||||
}],
|
||||
};
|
||||
});
|
||||
|
||||
|
|
23
packages/backend/watch.mjs
Normal file
23
packages/backend/watch.mjs
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { execa } from 'execa';
|
||||
|
||||
(async () => {
|
||||
// なぜかchokidarが動かない影響で、watchされない
|
||||
/*
|
||||
execa('tsc-alias', ['-w', '-p', 'tsconfig.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
*/
|
||||
|
||||
setInterval(() => {
|
||||
execa('tsc-alias', ['-p', 'tsconfig.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
execa('tsc', ['-w', '-p', 'tsconfig.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
})();
|
|
@ -111,22 +111,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
|
||||
integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
|
||||
|
||||
"@jfonx/console-utils@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@jfonx/console-utils/-/console-utils-1.0.3.tgz#cbb7f911e4191a4a2fe1ba4807d29f100b5d099f"
|
||||
integrity sha512-/XbnqjWc7yNZVLAJJO9rimfIz9DYte+cj3EF9hwhIv7vw6ok2t3cjl0huYsmD89srKH03vWjeqAcIH86CuYj3g==
|
||||
dependencies:
|
||||
colors "^1.3.3"
|
||||
|
||||
"@jfonx/file-utils@^3.0.1":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@jfonx/file-utils/-/file-utils-3.0.1.tgz#8d3d6e931a283420fe29802ea71c28dd397cd8d3"
|
||||
integrity sha512-qwH0CuzWmghtTHGMyuPHj6SJPQgWeiXFJBfrxCWMbzxVCa3aLZPEfzSdlSnC/UABsk6feRkNdHXw59rVshNPqw==
|
||||
dependencies:
|
||||
"@jfonx/console-utils" "^1.0.3"
|
||||
comment-json "^4.1.0"
|
||||
find-up "^4.1.0"
|
||||
|
||||
"@koa/cors@3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.1.0.tgz#618bb073438cfdbd3ebd0e648a76e33b84f3a3b2"
|
||||
|
@ -1380,11 +1364,6 @@ array-includes@^3.1.4:
|
|||
get-intrinsic "^1.1.1"
|
||||
is-string "^1.0.7"
|
||||
|
||||
array-timsort@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/array-timsort/-/array-timsort-1.0.3.tgz#3c9e4199e54fb2b9c3fe5976396a21614ef0d926"
|
||||
integrity sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==
|
||||
|
||||
array-union@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||
|
@ -2007,7 +1986,7 @@ cheerio@^0.22.0:
|
|||
lodash.reject "^4.4.0"
|
||||
lodash.some "^4.4.0"
|
||||
|
||||
chokidar@3.5.1, chokidar@^3.3.1, chokidar@^3.5.0:
|
||||
chokidar@3.5.1, chokidar@^3.3.1, chokidar@^3.5.2:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
|
||||
integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
|
||||
|
@ -2166,7 +2145,7 @@ colorette@^1.2.0, colorette@^1.2.1, colorette@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
||||
|
||||
colors@^1.1.2, colors@^1.3.3, colors@^1.4.0:
|
||||
colors@^1.1.2, colors@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
@ -2183,26 +2162,15 @@ commander@^2.19.0, commander@^2.20.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
commander@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
|
||||
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
|
||||
|
||||
comment-json@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.1.1.tgz#49df4948704bebb1cc0ffa6910e25669b668b7c5"
|
||||
integrity sha512-v8gmtPvxhBlhdRBLwdHSjGy9BgA23t9H1FctdQKyUrErPjSrJcdDMqBq9B4Irtm7w3TNYLQJNH6ARKnpyag1sA==
|
||||
dependencies:
|
||||
array-timsort "^1.0.3"
|
||||
core-util-is "^1.0.2"
|
||||
esprima "^4.0.1"
|
||||
has-own-prop "^2.0.0"
|
||||
repeat-string "^1.6.1"
|
||||
commander@^8.2.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
compare-versions@3.6.0:
|
||||
version "3.6.0"
|
||||
|
@ -2305,11 +2273,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
core-util-is@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
|
||||
|
||||
crc-32@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
|
||||
|
@ -2338,7 +2301,7 @@ cross-env@7.0.3:
|
|||
dependencies:
|
||||
cross-spawn "^7.0.1"
|
||||
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
|
@ -3295,6 +3258,21 @@ events@^3.2.0:
|
|||
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
|
||||
integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==
|
||||
|
||||
execa@6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-6.0.0.tgz#598b46f09ae44f5d8097a30cfb1681d0f0371503"
|
||||
integrity sha512-m4wU9j4Z9nXXoqT8RSfl28JSwmMNLFF69OON8H/lL3NeU0tNpGz313bcOfYoBBHokB0dC2tMl3VUcKgHELhL2Q==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.3"
|
||||
get-stream "^6.0.1"
|
||||
human-signals "^3.0.1"
|
||||
is-stream "^3.0.0"
|
||||
merge-stream "^2.0.0"
|
||||
npm-run-path "^5.0.1"
|
||||
onetime "^6.0.0"
|
||||
signal-exit "^3.0.5"
|
||||
strip-final-newline "^3.0.0"
|
||||
|
||||
execa@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
|
||||
|
@ -3435,7 +3413,7 @@ fill-range@^7.0.1:
|
|||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
find-node-modules@^2.1.0:
|
||||
find-node-modules@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-2.1.2.tgz#57565a3455baf671b835bc6b2134a9b938b9c53c"
|
||||
integrity sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==
|
||||
|
@ -3465,14 +3443,6 @@ find-up@^3.0.0:
|
|||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
find-up@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||
dependencies:
|
||||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
findup-sync@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0"
|
||||
|
@ -3637,6 +3607,11 @@ get-stream@^5.0.0, get-stream@^5.1.0:
|
|||
dependencies:
|
||||
pump "^3.0.0"
|
||||
|
||||
get-stream@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
|
||||
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
|
||||
|
||||
get-symbol-description@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
|
||||
|
@ -3734,7 +3709,7 @@ globals@^13.9.0:
|
|||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globby@^11.0.2, globby@^11.0.4:
|
||||
globby@^11.0.4:
|
||||
version "11.0.4"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
|
||||
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
|
||||
|
@ -3816,11 +3791,6 @@ has-flag@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-own-prop@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-own-prop/-/has-own-prop-2.0.0.tgz#f0f95d58f65804f5d218db32563bb85b8e0417af"
|
||||
integrity sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==
|
||||
|
||||
has-symbols@^1.0.0, has-symbols@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
|
@ -4007,6 +3977,11 @@ human-signals@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
||||
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
|
||||
|
||||
human-signals@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5"
|
||||
integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==
|
||||
|
||||
humanize-ms@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
|
||||
|
@ -4425,6 +4400,11 @@ is-stream@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
|
||||
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
|
||||
|
||||
is-stream@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
|
||||
integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
|
||||
|
||||
is-string@^1.0.5, is-string@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
|
||||
|
@ -5008,13 +4988,6 @@ locate-path@^3.0.0:
|
|||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
|
||||
|
@ -5266,6 +5239,11 @@ mimic-fn@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-fn@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
|
||||
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
|
||||
|
||||
mimic-response@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
|
@ -5467,6 +5445,11 @@ multer@1.4.3:
|
|||
type-is "^1.6.4"
|
||||
xtend "^4.0.0"
|
||||
|
||||
mylas@^2.1.4:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.5.tgz#7ccf41ec5a93ab2d63fc3678abf1942c0e7bdeb1"
|
||||
integrity sha512-7ZyrJux1lipSR45IxDvWz7zJOXWTazTFCqD4/p8XBF4O+mtJwf7QpMWTH+jE4lV9O2I38xcpS0KTIp7GwhUTmA==
|
||||
|
||||
mz@^2.4.0, mz@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
|
@ -5657,6 +5640,13 @@ npm-run-path@^4.0.0:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npm-run-path@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.0.1.tgz#748dd68ed7de377bb1f7132c7dafe657be5ab400"
|
||||
integrity sha512-ybBJQUSyFwEEhqO2lXmyKOl9ucHtyZBWVM0h0FiMfT/+WKxCUZFa95qAR2X3w/w6oigN3B0b2UNHZbD+kdfD5w==
|
||||
dependencies:
|
||||
path-key "^4.0.0"
|
||||
|
||||
npmlog@^4.0.1, npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
|
@ -5784,6 +5774,13 @@ onetime@^5.1.0:
|
|||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
onetime@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
|
||||
integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
|
||||
dependencies:
|
||||
mimic-fn "^4.0.0"
|
||||
|
||||
only@~0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
|
||||
|
@ -5877,7 +5874,7 @@ p-limit@^1.1.0:
|
|||
dependencies:
|
||||
p-try "^1.0.0"
|
||||
|
||||
p-limit@^2.0.0, p-limit@^2.2.0:
|
||||
p-limit@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
|
||||
|
@ -5912,13 +5909,6 @@ p-locate@^3.0.0:
|
|||
dependencies:
|
||||
p-limit "^2.0.0"
|
||||
|
||||
p-locate@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
|
||||
dependencies:
|
||||
p-limit "^2.2.0"
|
||||
|
||||
p-locate@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
|
||||
|
@ -6024,6 +6014,11 @@ path-key@^3.0.0, path-key@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-key@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
|
||||
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
|
||||
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
|
@ -6907,11 +6902,6 @@ rename@1.0.4:
|
|||
dependencies:
|
||||
debug "^2.5.2"
|
||||
|
||||
repeat-string@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
|
||||
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
|
||||
|
||||
request-promise-core@1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
|
||||
|
@ -7252,6 +7242,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||
|
||||
signal-exit@^3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
|
||||
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
|
||||
|
||||
simple-concat@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
|
||||
|
@ -7572,6 +7567,11 @@ strip-final-newline@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
|
||||
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
|
||||
|
||||
strip-final-newline@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
|
||||
integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
|
||||
|
||||
strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
|
@ -7915,17 +7915,16 @@ ts-node@10.4.0:
|
|||
make-error "^1.1.1"
|
||||
yn "3.1.1"
|
||||
|
||||
tsc-alias@1.3.10:
|
||||
version "1.3.10"
|
||||
resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.3.10.tgz#6ccf81c644092387ab9be3a3a75549a95eeffd80"
|
||||
integrity sha512-7SF56qiV7Oh/bON+XjF/uAzEFqbmwCuEIHQyoTyVJAK80WnxaIyhO9TBwD/x8InIMU8lnvExQBOrgKkRPsHH+w==
|
||||
tsc-alias@1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.4.1.tgz#6a6075dd94267d9befdad1431f410bd0b8819805"
|
||||
integrity sha512-nHTR8qvM/LiYI8Fx6UrzAQXRngAuE2PEK+n9uXmQY6fN+oLZhweNFkCLbyxKDmlLfYnclSuaR+dSuvRd7FUu8Q==
|
||||
dependencies:
|
||||
"@jfonx/console-utils" "^1.0.3"
|
||||
"@jfonx/file-utils" "^3.0.1"
|
||||
chokidar "^3.5.0"
|
||||
commander "^6.2.1"
|
||||
find-node-modules "^2.1.0"
|
||||
globby "^11.0.2"
|
||||
chokidar "^3.5.2"
|
||||
commander "^8.2.0"
|
||||
find-node-modules "^2.1.2"
|
||||
globby "^11.0.4"
|
||||
mylas "^2.1.4"
|
||||
normalize-path "^3.0.0"
|
||||
|
||||
tsconfig-paths@3.11.0, tsconfig-paths@^3.11.0:
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": false
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"vue/require-v-for-key": 0,
|
||||
"vue/max-attributes-per-line": 0,
|
||||
"vue/html-indent": 0,
|
||||
"vue/html-self-closing": 0,
|
||||
"vue/no-unused-vars": 0,
|
||||
"vue/attributes-order": 0,
|
||||
"vue/require-prop-types": 0,
|
||||
"vue/require-default-prop": 0,
|
||||
"vue/html-closing-bracket-spacing": 0,
|
||||
"vue/singleline-html-element-content-newline": 0,
|
||||
"vue/no-v-html": 0
|
||||
},
|
||||
"globals": {
|
||||
"_DEV_": false,
|
||||
"_LANGS_": false,
|
||||
"_VERSION_": false,
|
||||
"_ENV_": false,
|
||||
"_PERF_PREFIX_": false,
|
||||
"_DATA_TRANSFER_DRIVE_FILE_": false,
|
||||
"_DATA_TRANSFER_DRIVE_FOLDER_": false,
|
||||
"_DATA_TRANSFER_DECK_COLUMN_": false
|
||||
}
|
||||
}
|
61
packages/client/.eslintrc.js
Normal file
61
packages/client/.eslintrc.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
"node": false
|
||||
},
|
||||
parser: "vue-eslint-parser",
|
||||
parserOptions: {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
tsconfigRootDir: __dirname,
|
||||
//project: ['./tsconfig.json'],
|
||||
},
|
||||
extends: [
|
||||
//"../shared/.eslintrc.js",
|
||||
"plugin:vue/vue3-recommended"
|
||||
],
|
||||
rules: {
|
||||
"vue/attributes-order": ["error", {
|
||||
"alphabetical": false
|
||||
}],
|
||||
"vue/no-use-v-if-with-v-for": ["error", {
|
||||
"allowUsingIterationVar": false
|
||||
}],
|
||||
"vue/no-ref-as-operand": "error",
|
||||
"vue/no-multi-spaces": ["error", {
|
||||
"ignoreProperties": false
|
||||
}],
|
||||
"vue/no-v-html": "error",
|
||||
"vue/order-in-components": "error",
|
||||
"vue/html-indent": ["warn", "tab", {
|
||||
"attribute": 1,
|
||||
"baseIndent": 0,
|
||||
"closeBracket": 0,
|
||||
"alignAttributesVertically": true,
|
||||
"ignores": []
|
||||
}],
|
||||
"vue/html-closing-bracket-spacing": ["warn", {
|
||||
"startTag": "never",
|
||||
"endTag": "never",
|
||||
"selfClosingTag": "never"
|
||||
}],
|
||||
"vue/multi-word-component-names": "warn",
|
||||
"vue/require-v-for-key": "warn",
|
||||
"vue/no-unused-components": "warn",
|
||||
"vue/valid-v-for": "warn",
|
||||
"vue/return-in-computed-property": "warn",
|
||||
"vue/max-attributes-per-line": "off",
|
||||
"vue/html-self-closing": "off",
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
},
|
||||
globals: {
|
||||
"require": false,
|
||||
"_DEV_": false,
|
||||
"_LANGS_": false,
|
||||
"_VERSION_": false,
|
||||
"_ENV_": false,
|
||||
"_PERF_PREFIX_": false,
|
||||
"_DATA_TRANSFER_DRIVE_FILE_": false,
|
||||
"_DATA_TRANSFER_DRIVE_FOLDER_": false,
|
||||
"_DATA_TRANSFER_DECK_COLUMN_": false
|
||||
}
|
||||
}
|
11
packages/client/.vscode/settings.json
vendored
Normal file
11
packages/client/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib",
|
||||
"path-intellisense.mappings": {
|
||||
"@": "${workspaceRoot}/packages/client/src/"
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"vue"
|
||||
]
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"watch": "webpack --watch",
|
||||
"build": "webpack"
|
||||
"build": "webpack",
|
||||
"lint": "eslint --quiet src/**/*.{ts,vue}"
|
||||
},
|
||||
"resolutions": {
|
||||
"chokidar": "^3.3.1",
|
||||
|
@ -72,7 +73,7 @@
|
|||
"dateformat": "4.5.1",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "8.2.0",
|
||||
"eslint-plugin-vue": "8.0.3",
|
||||
"eslint-plugin-vue": "8.1.1",
|
||||
"eventemitter3": "4.0.7",
|
||||
"feed": "4.2.2",
|
||||
"glob": "7.2.0",
|
||||
|
@ -106,6 +107,7 @@
|
|||
"punycode": "2.1.1",
|
||||
"pureimage": "0.3.5",
|
||||
"qrcode": "1.4.4",
|
||||
"querystring": "0.2.1",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"reflect-metadata": "0.1.13",
|
||||
|
@ -151,8 +153,10 @@
|
|||
"devDependencies": {
|
||||
"@redocly/openapi-core": "1.0.0-beta.54",
|
||||
"@types/fluent-ffmpeg": "2.1.17",
|
||||
"@typescript-eslint/eslint-plugin": "5.4.0",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "8.5.0",
|
||||
"eslint-plugin-import": "2.25.3",
|
||||
"start-server-and-test": "1.14.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</MkTextarea>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<MkButton @click="send" primary full :disabled="comment.length === 0">{{ $ts.send }}</MkButton>
|
||||
<MkButton primary full :disabled="comment.length === 0" @click="send">{{ $ts.send }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</XWindow>
|
||||
|
@ -61,7 +61,7 @@ export default defineComponent({
|
|||
userId: this.user.id,
|
||||
comment: this.comment,
|
||||
}, undefined, res => {
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'success',
|
||||
text: this.$ts.abuseReported
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<svg class="mbcofsoe" viewBox="0 0 10 10" preserveAspectRatio="none">
|
||||
<circle v-for="(angle, i) in graduations"
|
||||
:key="i"
|
||||
:cx="5 + (Math.sin(angle) * (5 - graduationsPadding))"
|
||||
:cy="5 - (Math.cos(angle) * (5 - graduationsPadding))"
|
||||
:r="i % 5 == 0 ? 0.125 : 0.05"
|
||||
:fill="i % 5 == 0 ? majorGraduationColor : minorGraduationColor"
|
||||
:key="i"
|
||||
/>
|
||||
|
||||
<line
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
<template>
|
||||
<div class="swhvrteh _popup _shadow" @contextmenu.prevent="() => {}">
|
||||
<ol class="users" ref="suggests" v-if="type === 'user'">
|
||||
<li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1" class="user">
|
||||
<ol v-if="type === 'user'" ref="suggests" class="users">
|
||||
<li v-for="user in users" tabindex="-1" class="user" @click="complete(type, user)" @keydown="onKeydown">
|
||||
<img class="avatar" :src="user.avatarUrl"/>
|
||||
<span class="name">
|
||||
<MkUserName :user="user" :key="user.id"/>
|
||||
<MkUserName :key="user.id" :user="user"/>
|
||||
</span>
|
||||
<span class="username">@{{ acct(user) }}</span>
|
||||
</li>
|
||||
<li @click="chooseUser()" @keydown="onKeydown" tabindex="-1" class="choose">{{ $ts.selectUser }}</li>
|
||||
<li tabindex="-1" class="choose" @click="chooseUser()" @keydown="onKeydown">{{ $ts.selectUser }}</li>
|
||||
</ol>
|
||||
<ol class="hashtags" ref="suggests" v-else-if="hashtags.length > 0">
|
||||
<li v-for="hashtag in hashtags" @click="complete(type, hashtag)" @keydown="onKeydown" tabindex="-1">
|
||||
<ol v-else-if="hashtags.length > 0" ref="suggests" class="hashtags">
|
||||
<li v-for="hashtag in hashtags" tabindex="-1" @click="complete(type, hashtag)" @keydown="onKeydown">
|
||||
<span class="name">{{ hashtag }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
<ol class="emojis" ref="suggests" v-else-if="emojis.length > 0">
|
||||
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
|
||||
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else-if="!$store.state.useOsNativeEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else>{{ emoji.emoji }}</span>
|
||||
<ol v-else-if="emojis.length > 0" ref="suggests" class="emojis">
|
||||
<li v-for="emoji in emojis" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
|
||||
<span v-if="emoji.isCustomEmoji" class="emoji"><img :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span v-else-if="!$store.state.useOsNativeEmojis" class="emoji"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span v-else class="emoji">{{ emoji.emoji }}</span>
|
||||
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
|
||||
<span class="alias" v-if="emoji.aliasOf">({{ emoji.aliasOf }})</span>
|
||||
<span v-if="emoji.aliasOf" class="alias">({{ emoji.aliasOf }})</span>
|
||||
</li>
|
||||
</ol>
|
||||
<ol class="mfmTags" ref="suggests" v-else-if="mfmTags.length > 0">
|
||||
<li v-for="tag in mfmTags" @click="complete(type, tag)" @keydown="onKeydown" tabindex="-1">
|
||||
<ol v-else-if="mfmTags.length > 0" ref="suggests" class="mfmTags">
|
||||
<li v-for="tag in mfmTags" tabindex="-1" @click="complete(type, tag)" @keydown="onKeydown">
|
||||
<span class="tag">{{ tag }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<button class="hdcaacmi _button"
|
||||
:class="{ wait, active: isFollowing, full }"
|
||||
@click="onClick"
|
||||
:disabled="wait"
|
||||
@click="onClick"
|
||||
>
|
||||
<template v-if="!wait">
|
||||
<template v-if="isFollowing">
|
||||
|
|
|
@ -44,6 +44,11 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
bannerStyle() {
|
||||
if (this.channel.bannerUrl) {
|
||||
|
@ -53,11 +58,6 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<code v-if="inline" v-html="html" :class="`language-${prismLang}`"></code>
|
||||
<pre v-else :class="`language-${prismLang}`"><code v-html="html" :class="`language-${prismLang}`"></code></pre>
|
||||
<code v-if="inline" :class="`language-${prismLang}`" v-html="html"></code>
|
||||
<pre v-else :class="`language-${prismLang}`"><code :class="`language-${prismLang}`" v-html="html"></code></pre>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
|
|
@ -31,10 +31,6 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
methods: {
|
||||
focus() {
|
||||
this.$slots.default[0].elm.focus();
|
||||
},
|
||||
|
||||
getDateText(time: string) {
|
||||
const date = new Date(time).getDate();
|
||||
const month = new Date(time).getMonth() + 1;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="rbusrurv" :class="{ wide: forceWide }" v-size="{ max: [400] }">
|
||||
<div v-size="{ max: [400] }" class="rbusrurv" :class="{ wide: forceWide }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="vrtktovg _debobigegoItem _debobigegoNoConcat" v-size="{ max: [500] }" v-sticky-container>
|
||||
<div v-size="{ max: [500] }" v-sticky-container class="vrtktovg _debobigegoItem _debobigegoNoConcat">
|
||||
<div class="_debobigegoLabel"><slot name="label"></slot></div>
|
||||
<div class="main _debobigego_group" ref="child">
|
||||
<div ref="child" class="main _debobigego_group">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="_debobigegoCaption"><slot name="caption"></slot></div>
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<FormGroup class="_debobigegoItem">
|
||||
<template #label><slot></slot></template>
|
||||
<div class="ztzhwixg _debobigegoItem" :class="{ inline, disabled }">
|
||||
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||
<div ref="icon" class="icon"><slot name="icon"></slot></div>
|
||||
<div class="input _debobigegoPanel">
|
||||
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||
<div ref="prefixEl" class="prefix"><slot name="prefix"></slot></div>
|
||||
<input ref="inputEl"
|
||||
:type="type"
|
||||
v-model="v"
|
||||
:type="type"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
|
@ -16,21 +16,21 @@
|
|||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
:step="step"
|
||||
:list="id"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keydown="onKeydown($event)"
|
||||
@input="onInput"
|
||||
:list="id"
|
||||
>
|
||||
<datalist :id="id" v-if="datalist">
|
||||
<datalist v-if="datalist" :id="id">
|
||||
<option v-for="data in datalist" :value="data"/>
|
||||
</datalist>
|
||||
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
|
||||
<div ref="suffixEl" class="suffix"><slot name="suffix"></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
<template #caption><slot name="desc"></slot></template>
|
||||
|
||||
<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
<FormButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
</FormGroup>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="qmfkfnzi _debobigegoItem">
|
||||
<a class="main _button _debobigegoPanel _debobigegoClickable" :href="to" target="_blank" v-if="external">
|
||||
<a v-if="external" class="main _button _debobigegoPanel _debobigegoClickable" :href="to" target="_blank">
|
||||
<span class="icon"><slot name="icon"></slot></span>
|
||||
<span class="text"><slot></slot></span>
|
||||
<span class="right">
|
||||
|
@ -8,7 +8,7 @@
|
|||
<i class="fas fa-external-link-alt icon"></i>
|
||||
</span>
|
||||
</a>
|
||||
<MkA class="main _button _debobigegoPanel _debobigegoClickable" :class="{ active }" :to="to" :behavior="behavior" v-else>
|
||||
<MkA v-else class="main _button _debobigegoPanel _debobigegoClickable" :class="{ active }" :to="to" :behavior="behavior">
|
||||
<span class="icon"><slot name="icon"></slot></span>
|
||||
<span class="text"><slot></slot></span>
|
||||
<span class="right">
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<template #label><slot></slot></template>
|
||||
<div class="drooglns _debobigegoItem" :class="{ tall }">
|
||||
<div class="input _debobigegoPanel">
|
||||
<textarea class="_monospace"
|
||||
v-model="v"
|
||||
<textarea v-model="v"
|
||||
class="_monospace"
|
||||
readonly
|
||||
:spellcheck="false"
|
||||
></textarea>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<FormGroup class="uljviswt _debobigegoItem">
|
||||
<template #label><slot name="label"></slot></template>
|
||||
<slot :items="items"></slot>
|
||||
<div class="empty" v-if="empty" key="_empty_">
|
||||
<div v-if="empty" key="_empty_" class="empty">
|
||||
<slot name="empty"></slot>
|
||||
</div>
|
||||
<FormButton v-show="more" class="button" @click="fetchMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary>
|
||||
<FormButton v-show="more" class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMore">
|
||||
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
|
||||
<template v-if="moreFetching"><MkLoading inline/></template>
|
||||
</FormButton>
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<div class="_debobigegoLabel"><slot name="label"></slot></div>
|
||||
<div class="_debobigegoPanel main">
|
||||
<input
|
||||
type="range"
|
||||
ref="input"
|
||||
v-model="v"
|
||||
type="range"
|
||||
:disabled="disabled"
|
||||
:min="min"
|
||||
:max="max"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="yrtfrpux _debobigegoItem" :class="{ disabled, inline }">
|
||||
<div class="_debobigegoLabel"><slot name="label"></slot></div>
|
||||
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||
<div ref="icon" class="icon"><slot name="icon"></slot></div>
|
||||
<div class="input _debobigegoPanel _debobigegoClickable" @click="focus">
|
||||
<div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
|
||||
<div ref="prefix" class="prefix"><slot name="prefix"></slot></div>
|
||||
<select ref="input"
|
||||
v-model="v"
|
||||
:required="required"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="_debobigegoItem" v-if="pending">
|
||||
<div v-if="pending" class="_debobigegoItem">
|
||||
<div class="_debobigegoPanel">
|
||||
<MkLoading/>
|
||||
</div>
|
||||
|
@ -8,10 +8,10 @@
|
|||
<div v-else-if="resolved" class="_debobigegoItem">
|
||||
<slot :result="result"></slot>
|
||||
</div>
|
||||
<div class="_debobigegoItem" v-else>
|
||||
<div v-else class="_debobigegoItem">
|
||||
<div class="_debobigegoPanel eiurkvay">
|
||||
<div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div>
|
||||
<MkButton inline @click="retry" class="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton>
|
||||
<MkButton inline class="retry" @click="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
@click.prevent="toggle"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
ref="input"
|
||||
type="checkbox"
|
||||
:disabled="disabled"
|
||||
@keydown.enter="toggle"
|
||||
>
|
||||
<span class="button" v-tooltip="checked ? $ts.itsOn : $ts.itsOff">
|
||||
<span v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button">
|
||||
<span class="handle"></span>
|
||||
</span>
|
||||
<span class="label">
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<template #label><slot></slot></template>
|
||||
<div class="rivhosbp _debobigegoItem" :class="{ tall, pre }">
|
||||
<div class="input _debobigegoPanel">
|
||||
<textarea ref="input" :class="{ code, _monospace: code }"
|
||||
v-model="v"
|
||||
<textarea ref="input" v-model="v"
|
||||
:class="{ code, _monospace: code }"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
<template #caption><slot name="desc"></slot></template>
|
||||
|
||||
<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
<FormButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
</FormGroup>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="wthhikgt _debobigegoItem" v-size="{ max: [500] }">
|
||||
<div v-size="{ max: [500] }" class="wthhikgt _debobigegoItem">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
|
||||
<div class="mk-dialog">
|
||||
<div class="icon" v-if="icon">
|
||||
<div v-if="icon" class="icon">
|
||||
<i :class="icon"></i>
|
||||
</div>
|
||||
<div class="icon" v-else-if="!input && !select" :class="type">
|
||||
<div v-else-if="!input && !select" class="icon" :class="type">
|
||||
<i v-if="type === 'success'" class="fas fa-check"></i>
|
||||
<i v-else-if="type === 'error'" class="fas fa-times-circle"></i>
|
||||
<i v-else-if="type === 'warning'" class="fas fa-exclamation-triangle"></i>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<i v-else-if="type === 'waiting'" class="fas fa-spinner fa-pulse"></i>
|
||||
</div>
|
||||
<header v-if="title"><Mfm :text="title"/></header>
|
||||
<div class="body" v-if="text"><Mfm :text="text"/></div>
|
||||
<div v-if="text" class="body"><Mfm :text="text"/></div>
|
||||
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></MkInput>
|
||||
<MkSelect v-if="select" v-model="selectedValue" autofocus>
|
||||
<template v-if="select.items">
|
||||
|
@ -25,12 +25,12 @@
|
|||
</optgroup>
|
||||
</template>
|
||||
</MkSelect>
|
||||
<div class="buttons" v-if="(showOkButton || showCancelButton) && !actions">
|
||||
<MkButton inline @click="ok" v-if="showOkButton" primary :autofocus="!input && !select">{{ (showCancelButton || input || select) ? $ts.ok : $ts.gotIt }}</MkButton>
|
||||
<MkButton inline @click="cancel" v-if="showCancelButton || input || select">{{ $ts.cancel }}</MkButton>
|
||||
<div v-if="(showOkButton || showCancelButton) && !actions" class="buttons">
|
||||
<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" @click="ok">{{ (showCancelButton || input || select) ? $ts.ok : $ts.gotIt }}</MkButton>
|
||||
<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ $ts.cancel }}</MkButton>
|
||||
</div>
|
||||
<div class="buttons" v-if="actions">
|
||||
<MkButton v-for="action in actions" inline @click="() => { action.callback(); close(); }" :primary="action.primary" :key="action.text">{{ action.text }}</MkButton>
|
||||
<div v-if="actions" class="buttons">
|
||||
<MkButton v-for="action in actions" :key="action.text" inline :primary="action.primary" @click="() => { action.callback(); close(); }">{{ action.text }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</MkModal>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="zdjebgpv" ref="thumbnail">
|
||||
<div ref="thumbnail" class="zdjebgpv">
|
||||
<ImgWithBlurhash v-if="isThumbnailAvailable" :hash="file.blurhash" :src="file.thumbnailUrl" :alt="file.name" :title="file.name" :style="`object-fit: ${ fit }`"/>
|
||||
<i v-else-if="is === 'image'" class="fas fa-file-image icon"></i>
|
||||
<i v-else-if="is === 'video'" class="fas fa-file-video icon"></i>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{ multiple ? ((type === 'file') ? $ts.selectFiles : $ts.selectFolders) : ((type === 'file') ? $ts.selectFile : $ts.selectFolder) }}
|
||||
<span v-if="selected.length > 0" style="margin-left: 8px; opacity: 0.5;">({{ number(selected.length) }})</span>
|
||||
</template>
|
||||
<XDrive :multiple="multiple" @changeSelection="onChangeSelection" @selected="ok()" :select="type"/>
|
||||
<XDrive :multiple="multiple" :select="type" @changeSelection="onChangeSelection" @selected="ok()"/>
|
||||
</XModalWindow>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<div class="ncvczrfv"
|
||||
:class="{ isSelected }"
|
||||
draggable="true"
|
||||
:title="title"
|
||||
@click="onClick"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
draggable="true"
|
||||
@dragstart="onDragstart"
|
||||
@dragend="onDragend"
|
||||
:title="title"
|
||||
>
|
||||
<div class="label" v-if="$i.avatarId == file.id">
|
||||
<div v-if="$i.avatarId == file.id" class="label">
|
||||
<img src="/client-assets/label.svg"/>
|
||||
<p>{{ $ts.avatar }}</p>
|
||||
</div>
|
||||
<div class="label" v-if="$i.bannerId == file.id">
|
||||
<div v-if="$i.bannerId == file.id" class="label">
|
||||
<img src="/client-assets/label.svg"/>
|
||||
<p>{{ $ts.banner }}</p>
|
||||
</div>
|
||||
<div class="label red" v-if="file.isSensitive">
|
||||
<div v-if="file.isSensitive" class="label red">
|
||||
<img src="/client-assets/label-red.svg"/>
|
||||
<p>{{ $ts.nsfw }}</p>
|
||||
</div>
|
||||
|
@ -25,7 +25,7 @@
|
|||
|
||||
<p class="name">
|
||||
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>
|
||||
<span class="ext" v-if="file.name.lastIndexOf('.') != -1">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span>
|
||||
<span v-if="file.name.lastIndexOf('.') != -1" class="ext">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -138,13 +138,11 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
rename() {
|
||||
os.dialog({
|
||||
os.inputText({
|
||||
title: this.$ts.renameFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewFileName,
|
||||
default: this.file.name,
|
||||
allowEmpty: false
|
||||
}
|
||||
}).then(({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/files/update', {
|
||||
|
@ -191,10 +189,9 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
async deleteFile() {
|
||||
const { canceled } = await os.dialog({
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: this.$t('driveFileDeleteConfirm', { name: this.file.name }),
|
||||
showCancelButton: true
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<template>
|
||||
<div class="rghtznwe"
|
||||
:class="{ draghover }"
|
||||
draggable="true"
|
||||
:title="title"
|
||||
@click="onClick"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
@mouseover="onMouseover"
|
||||
|
@ -9,17 +11,15 @@
|
|||
@dragenter.prevent="onDragenter"
|
||||
@dragleave="onDragleave"
|
||||
@drop.prevent.stop="onDrop"
|
||||
draggable="true"
|
||||
@dragstart="onDragstart"
|
||||
@dragend="onDragend"
|
||||
:title="title"
|
||||
>
|
||||
<p class="name">
|
||||
<template v-if="hover"><i class="fas fa-folder-open fa-fw"></i></template>
|
||||
<template v-if="!hover"><i class="fas fa-folder fa-fw"></i></template>
|
||||
{{ folder.name }}
|
||||
</p>
|
||||
<p class="upload" v-if="$store.state.uploadFolder == folder.id">
|
||||
<p v-if="$store.state.uploadFolder == folder.id" class="upload">
|
||||
{{ $ts.uploadFolder }}
|
||||
</p>
|
||||
<button v-if="selectMode" class="checkbox _button" :class="{ checked: isSelected }" @click.prevent.stop="checkboxClicked"></button>
|
||||
|
@ -151,13 +151,13 @@ export default defineComponent({
|
|||
}).catch(err => {
|
||||
switch (err) {
|
||||
case 'detected-circular-definition':
|
||||
os.dialog({
|
||||
os.alert({
|
||||
title: this.$ts.unableToProcess,
|
||||
text: this.$ts.circularReferenceFolder
|
||||
});
|
||||
break;
|
||||
default:
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: this.$ts.somethingHappened
|
||||
});
|
||||
|
@ -191,12 +191,10 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
rename() {
|
||||
os.dialog({
|
||||
os.inputText({
|
||||
title: this.$ts.renameFolder,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewFolderName,
|
||||
default: this.folder.name
|
||||
}
|
||||
}).then(({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/folders/update', {
|
||||
|
@ -216,14 +214,14 @@ export default defineComponent({
|
|||
}).catch(err => {
|
||||
switch(err.id) {
|
||||
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
title: this.$ts.unableToDelete,
|
||||
text: this.$ts.hasChildFilesOrFolders
|
||||
});
|
||||
break;
|
||||
default:
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: this.$ts.unableToDelete
|
||||
});
|
||||
|
|
|
@ -7,33 +7,33 @@
|
|||
<span class="separator"><i class="fas fa-angle-right"></i></span>
|
||||
<XNavFolder :folder="f"/>
|
||||
</template>
|
||||
<span class="separator" v-if="folder != null"><i class="fas fa-angle-right"></i></span>
|
||||
<span class="folder current" v-if="folder != null">{{ folder.name }}</span>
|
||||
<span v-if="folder != null" class="separator"><i class="fas fa-angle-right"></i></span>
|
||||
<span v-if="folder != null" class="folder current">{{ folder.name }}</span>
|
||||
</div>
|
||||
<button @click="showMenu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
|
||||
<button class="menu _button" @click="showMenu"><i class="fas fa-ellipsis-h"></i></button>
|
||||
</nav>
|
||||
<div class="main" :class="{ uploading: uploadings.length > 0, fetching }"
|
||||
ref="main"
|
||||
<div ref="main" class="main"
|
||||
:class="{ uploading: uploadings.length > 0, fetching }"
|
||||
@dragover.prevent.stop="onDragover"
|
||||
@dragenter="onDragenter"
|
||||
@dragleave="onDragleave"
|
||||
@drop.prevent.stop="onDrop"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
>
|
||||
<div class="contents" ref="contents">
|
||||
<div class="folders" ref="foldersContainer" v-show="folders.length > 0">
|
||||
<XFolder v-for="(f, i) in folders" :key="f.id" class="folder" :folder="f" :select-mode="select === 'folder'" :is-selected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder" v-anim="i"/>
|
||||
<div ref="contents" class="contents">
|
||||
<div v-show="folders.length > 0" ref="foldersContainer" class="folders">
|
||||
<XFolder v-for="(f, i) in folders" :key="f.id" v-anim="i" class="folder" :folder="f" :select-mode="select === 'folder'" :is-selected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder"/>
|
||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
||||
<MkButton ref="moreFolders" v-if="moreFolders">{{ $ts.loadMore }}</MkButton>
|
||||
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
|
||||
<MkButton v-if="moreFolders" ref="moreFolders">{{ $ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
<div class="files" ref="filesContainer" v-show="files.length > 0">
|
||||
<XFile v-for="(file, i) in files" :key="file.id" class="file" :file="file" :select-mode="select === 'file'" :is-selected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile" v-anim="i"/>
|
||||
<div v-show="files.length > 0" ref="filesContainer" class="files">
|
||||
<XFile v-for="(file, i) in files" :key="file.id" v-anim="i" class="file" :file="file" :select-mode="select === 'file'" :is-selected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile"/>
|
||||
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
|
||||
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
|
||||
<MkButton ref="loadMoreFiles" @click="fetchMoreFiles" v-show="moreFiles">{{ $ts.loadMore }}</MkButton>
|
||||
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
|
||||
<MkButton v-show="moreFiles" ref="loadMoreFiles" @click="fetchMoreFiles">{{ $ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
<div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching">
|
||||
<div v-if="files.length == 0 && folders.length == 0 && !fetching" class="empty">
|
||||
<p v-if="draghover">{{ $t('empty-draghover') }}</p>
|
||||
<p v-if="!draghover && folder == null"><strong>{{ $ts.emptyDrive }}</strong><br/>{{ $t('empty-drive-description') }}</p>
|
||||
<p v-if="!draghover && folder != null">{{ $ts.emptyFolder }}</p>
|
||||
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
<MkLoading v-if="fetching"/>
|
||||
</div>
|
||||
<div class="dropzone" v-if="draghover"></div>
|
||||
<div v-if="draghover" class="dropzone"></div>
|
||||
<input ref="fileInput" type="file" accept="*/*" multiple="multiple" tabindex="-1" @change="onChangeFileInput"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -274,13 +274,13 @@ export default defineComponent({
|
|||
}).catch(err => {
|
||||
switch (err) {
|
||||
case 'detected-circular-definition':
|
||||
os.dialog({
|
||||
os.alert({
|
||||
title: this.$ts.unableToProcess,
|
||||
text: this.$ts.circularReferenceFolder
|
||||
});
|
||||
break;
|
||||
default:
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: this.$ts.somethingHappened
|
||||
});
|
||||
|
@ -295,11 +295,10 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
urlUpload() {
|
||||
os.dialog({
|
||||
os.inputText({
|
||||
title: this.$ts.uploadFromUrl,
|
||||
input: {
|
||||
type: 'url',
|
||||
placeholder: this.$ts.uploadFromUrlDescription
|
||||
}
|
||||
}).then(({ canceled, result: url }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/files/upload-from-url', {
|
||||
|
@ -307,7 +306,7 @@ export default defineComponent({
|
|||
folderId: this.folder ? this.folder.id : undefined
|
||||
});
|
||||
|
||||
os.dialog({
|
||||
os.alert({
|
||||
title: this.$ts.uploadFromUrlRequested,
|
||||
text: this.$ts.uploadFromUrlMayTakeTime
|
||||
});
|
||||
|
@ -315,11 +314,9 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
createFolder() {
|
||||
os.dialog({
|
||||
os.inputText({
|
||||
title: this.$ts.createFolder,
|
||||
input: {
|
||||
placeholder: this.$ts.folderName
|
||||
}
|
||||
}).then(({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/folders/create', {
|
||||
|
@ -332,12 +329,10 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
renameFolder(folder) {
|
||||
os.dialog({
|
||||
os.inputText({
|
||||
title: this.$ts.renameFolder,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewFolderName,
|
||||
default: folder.name
|
||||
}
|
||||
}).then(({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/folders/update', {
|
||||
|
@ -359,14 +354,14 @@ export default defineComponent({
|
|||
}).catch(err => {
|
||||
switch(err.id) {
|
||||
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
title: this.$ts.unableToDelete,
|
||||
text: this.$ts.hasChildFilesOrFolders
|
||||
});
|
||||
break;
|
||||
default:
|
||||
os.dialog({
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: this.$ts.unableToDelete
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<MkPopup ref="popup" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.popup.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')" #default="{point}">
|
||||
<MkEmojiPicker class="ryghynhb _popup _shadow" :class="{ pointer: point === 'top' }" :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
|
||||
<MkPopup ref="popup" #default="{point}" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.popup.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
|
||||
<MkEmojiPicker ref="picker" class="ryghynhb _popup _shadow" :class="{ pointer: point === 'top' }" :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen"/>
|
||||
</MkPopup>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
</header>
|
||||
<div v-if="shown">
|
||||
<button v-for="emoji in emojis"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
@click="chosen(emoji, $event)"
|
||||
:key="emoji"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div class="omfetrab" :class="['w' + width, 'h' + height, { big }]">
|
||||
<input ref="search" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
|
||||
<div class="emojis" ref="emojis">
|
||||
<input ref="search" v-model.trim="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
|
||||
<div ref="emojis" class="emojis">
|
||||
<section class="result">
|
||||
<div v-if="searchResultCustom.length > 0">
|
||||
<button v-for="emoji in searchResultCustom"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
:title="emoji.name"
|
||||
@click="chosen(emoji, $event)"
|
||||
:key="emoji"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>
|
||||
<img v-else :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
||||
|
@ -17,25 +17,25 @@
|
|||
</div>
|
||||
<div v-if="searchResultUnicode.length > 0">
|
||||
<button v-for="emoji in searchResultUnicode"
|
||||
:key="emoji.name"
|
||||
class="_button"
|
||||
:title="emoji.name"
|
||||
@click="chosen(emoji, $event)"
|
||||
:key="emoji.name"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji.char"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="index" v-if="tab === 'index'">
|
||||
<div v-if="tab === 'index'" class="index">
|
||||
<section v-if="showPinned">
|
||||
<div>
|
||||
<button v-for="emoji in pinned"
|
||||
class="_button"
|
||||
@click="chosen(emoji, $event)"
|
||||
tabindex="0"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
tabindex="0"
|
||||
@click="chosen(emoji, $event)"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
|
@ -46,9 +46,9 @@
|
|||
<header class="_acrylic"><i class="far fa-clock fa-fw"></i> {{ $ts.recentUsed }}</header>
|
||||
<div>
|
||||
<button v-for="emoji in $store.state.recentlyUsedEmojis"
|
||||
:key="emoji"
|
||||
class="_button"
|
||||
@click="chosen(emoji, $event)"
|
||||
:key="emoji"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="xfbouadm" v-if="meta" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }"></div>
|
||||
<div v-if="meta" class="xfbouadm" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<button class="kpoogebi _button"
|
||||
:class="{ wait, active: isFollowing || hasPendingFollowRequestFromYou, full, large }"
|
||||
@click="onClick"
|
||||
:disabled="wait"
|
||||
@click="onClick"
|
||||
>
|
||||
<template v-if="!wait">
|
||||
<template v-if="hasPendingFollowRequestFromYou && user.isLocked">
|
||||
|
@ -94,10 +94,9 @@ export default defineComponent({
|
|||
|
||||
try {
|
||||
if (this.isFollowing) {
|
||||
const { canceled } = await os.dialog({
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: this.$t('unfollowConfirm', { name: this.user.name || this.user.username }),
|
||||
showCancelButton: true
|
||||
});
|
||||
|
||||
if (canceled) return;
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
>
|
||||
<template #header>{{ $ts.forgotPassword }}</template>
|
||||
|
||||
<form class="bafeceda" @submit.prevent="onSubmit" v-if="$instance.enableEmail">
|
||||
<form v-if="$instance.enableEmail" class="bafeceda" @submit.prevent="onSubmit">
|
||||
<div class="main _formRoot">
|
||||
<MkInput class="_formBlock" v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required>
|
||||
<MkInput v-model="username" class="_formBlock" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required>
|
||||
<template #label>{{ $ts.username }}</template>
|
||||
<template #prefix>@</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInput class="_formBlock" v-model="email" type="email" spellcheck="false" required>
|
||||
<MkInput v-model="email" class="_formBlock" type="email" spellcheck="false" required>
|
||||
<template #label>{{ $ts.emailAddress }}</template>
|
||||
<template #caption>{{ $ts._forgotPassword.enterEmail }}</template>
|
||||
</MkInput>
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
</FormSwitch>
|
||||
<FormSelect v-else-if="form[item].type === 'enum'" v-model="values[item]">
|
||||
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
<option v-for="item in form[item].enum" :value="item.value" :key="item.value">{{ item.label }}</option>
|
||||
<option v-for="item in form[item].enum" :key="item.value" :value="item.value">{{ item.label }}</option>
|
||||
</FormSelect>
|
||||
<FormRadios v-else-if="form[item].type === 'radio'" v-model="values[item]">
|
||||
<template #desc><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
<option v-for="item in form[item].options" :value="item.value" :key="item.value">{{ item.label }}</option>
|
||||
<option v-for="item in form[item].options" :key="item.value" :value="item.value">{{ item.label }}</option>
|
||||
</FormRadios>
|
||||
<FormRange v-else-if="form[item].type === 'range'" v-model="values[item]" :min="form[item].mim" :max="form[item].max" :step="form[item].step">
|
||||
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<div class="matxzzsk">
|
||||
<div class="label" @click="focus"><slot name="label"></slot></div>
|
||||
<div class="input" :class="{ inline, disabled, focused }">
|
||||
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||
<div ref="prefixEl" class="prefix"><slot name="prefix"></slot></div>
|
||||
<input ref="inputEl"
|
||||
:type="type"
|
||||
v-model="v"
|
||||
:type="type"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
|
@ -14,20 +14,20 @@
|
|||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
:step="step"
|
||||
:list="id"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keydown="onKeydown($event)"
|
||||
@input="onInput"
|
||||
:list="id"
|
||||
>
|
||||
<datalist :id="id" v-if="datalist">
|
||||
<datalist v-if="datalist" :id="id">
|
||||
<option v-for="data in datalist" :value="data"/>
|
||||
</datalist>
|
||||
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
|
||||
<div ref="suffixEl" class="suffix"><slot name="suffix"></slot></div>
|
||||
</div>
|
||||
<div class="caption"><slot name="caption"></slot></div>
|
||||
|
||||
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
<MkButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<div class="icon"><slot name="icon"></slot></div>
|
||||
<span class="label"><slot name="label"></slot></span>
|
||||
<input
|
||||
type="range"
|
||||
ref="input"
|
||||
v-model="v"
|
||||
type="range"
|
||||
:disabled="disabled"
|
||||
:min="min"
|
||||
:max="max"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="vrtktovh" v-size="{ max: [500] }" v-sticky-container>
|
||||
<div v-size="{ max: [500] }" v-sticky-container class="vrtktovh">
|
||||
<div class="label"><slot name="label"></slot></div>
|
||||
<div class="main">
|
||||
<slot></slot>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<div class="vblkjoeq">
|
||||
<div class="label" @click="focus"><slot name="label"></slot></div>
|
||||
<div class="input" :class="{ inline, disabled, focused }" @click.prevent="onClick" ref="container">
|
||||
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||
<select class="select" ref="inputEl"
|
||||
v-model="v"
|
||||
<div ref="container" class="input" :class="{ inline, disabled, focused }" @click.prevent="onClick">
|
||||
<div ref="prefixEl" class="prefix"><slot name="prefix"></slot></div>
|
||||
<select ref="inputEl" v-model="v"
|
||||
class="select"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
|
@ -15,11 +15,11 @@
|
|||
>
|
||||
<slot></slot>
|
||||
</select>
|
||||
<div class="suffix" ref="suffixEl"><i class="fas fa-chevron-down"></i></div>
|
||||
<div ref="suffixEl" class="suffix"><i class="fas fa-chevron-down"></i></div>
|
||||
</div>
|
||||
<div class="caption"><slot name="caption"></slot></div>
|
||||
|
||||
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
<MkButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
@click.prevent="toggle"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
ref="input"
|
||||
type="checkbox"
|
||||
:disabled="disabled"
|
||||
@keydown.enter="toggle"
|
||||
>
|
||||
<span class="button" v-tooltip="checked ? $ts.itsOn : $ts.itsOff">
|
||||
<span v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button">
|
||||
<span class="handle"></span>
|
||||
</span>
|
||||
<span class="label">
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<div class="label" @click="focus"><slot name="label"></slot></div>
|
||||
<div class="input" :class="{ disabled, focused, tall, pre }">
|
||||
<textarea ref="inputEl"
|
||||
:class="{ code, _monospace: code }"
|
||||
v-model="v"
|
||||
:class="{ code, _monospace: code }"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
<div class="caption"><slot name="caption"></slot></div>
|
||||
|
||||
<MkButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
<MkButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<span class="mk-acct">
|
||||
<span class="name">@{{ user.username }}</span>
|
||||
<span class="host" v-if="user.host || detail || $store.state.showFullAcct">@{{ user.host || host }}</span>
|
||||
<span v-if="user.host || detail || $store.state.showFullAcct" class="host">@{{ user.host || host }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div class="qiivuoyo" v-if="ad">
|
||||
<div class="main" :class="ad.place" v-if="!showMenu">
|
||||
<div v-if="ad" class="qiivuoyo">
|
||||
<div v-if="!showMenu" class="main" :class="ad.place">
|
||||
<a :href="ad.url" target="_blank">
|
||||
<img :src="ad.imageUrl">
|
||||
<button class="_button menu" @click.prevent.stop="toggleMenu"><span class="fas fa-info-circle"></span></button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="menu" v-else>
|
||||
<div v-else class="menu">
|
||||
<div class="body">
|
||||
<div>Ads by {{ host }}</div>
|
||||
<!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>-->
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<span class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
||||
<span v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :title="acct(user)" @click="onClick">
|
||||
<img class="inner" :src="url" decoding="async"/>
|
||||
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
|
||||
</span>
|
||||
<MkA class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||
<MkA v-else v-user-preview="disablePreview ? undefined : user.id" class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :to="userPage(user)" :title="acct(user)" :target="target">
|
||||
<img class="inner" :src="url" decoding="async"/>
|
||||
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
|
||||
</MkA>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div class="mjndxjcg">
|
||||
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/>
|
||||
<p><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</p>
|
||||
<MkButton @click="() => $emit('retry')" class="button">{{ $ts.retry }}</MkButton>
|
||||
<MkButton class="button" @click="() => $emit('retry')">{{ $ts.retry }}</MkButton>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
<template>
|
||||
<div class="fdidabkb" :class="{ slim: narrow, thin: thin_ }" :style="{ background: bg }" @click="onClick" ref="el">
|
||||
<div ref="el" class="fdidabkb" :class="{ slim: narrow, thin: thin_ }" :style="{ background: bg }" @click="onClick">
|
||||
<template v-if="info">
|
||||
<div class="titleContainer" @click="showTabsPopup" v-if="!hideTitle">
|
||||
<div v-if="!hideTitle" class="titleContainer" @click="showTabsPopup">
|
||||
<MkAvatar v-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/>
|
||||
<i v-else-if="info.icon" class="icon" :class="info.icon"></i>
|
||||
|
||||
<div class="title">
|
||||
<MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/>
|
||||
<div v-else-if="info.title" class="title">{{ info.title }}</div>
|
||||
<div class="subtitle" v-if="!narrow && info.subtitle">
|
||||
<div v-if="!narrow && info.subtitle" class="subtitle">
|
||||
{{ info.subtitle }}
|
||||
</div>
|
||||
<div class="subtitle activeTab" v-if="narrow && hasTabs">
|
||||
<div v-if="narrow && hasTabs" class="subtitle activeTab">
|
||||
{{ info.tabs.find(tab => tab.active)?.title }}
|
||||
<i class="chevron fas fa-chevron-down"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs" v-if="!narrow || hideTitle">
|
||||
<button class="tab _button" v-for="tab in info.tabs" :class="{ active: tab.active }" @click="tab.onClick" v-tooltip="tab.title">
|
||||
<div v-if="!narrow || hideTitle" class="tabs">
|
||||
<button v-for="tab in info.tabs" v-tooltip="tab.title" class="tab _button" :class="{ active: tab.active }" @click="tab.onClick">
|
||||
<i v-if="tab.icon" class="icon" :class="tab.icon"></i>
|
||||
<span v-if="!tab.iconOnly" class="title">{{ tab.title }}</span>
|
||||
</button>
|
||||
|
@ -27,11 +27,11 @@
|
|||
<div class="buttons right">
|
||||
<template v-if="info && info.actions && !narrow">
|
||||
<template v-for="action in info.actions">
|
||||
<MkButton class="fullButton" v-if="action.asFullButton" @click.stop="action.handler" primary><i :class="action.icon" style="margin-right: 6px;"></i>{{ action.text }}</MkButton>
|
||||
<button v-else class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag" v-tooltip="action.text"><i :class="action.icon"></i></button>
|
||||
<MkButton v-if="action.asFullButton" class="fullButton" primary @click.stop="action.handler"><i :class="action.icon" style="margin-right: 6px;"></i>{{ action.text }}</MkButton>
|
||||
<button v-else v-tooltip="action.text" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag"><i :class="action.icon"></i></button>
|
||||
</template>
|
||||
</template>
|
||||
<button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button>
|
||||
<button v-if="shouldShowMenu" v-tooltip="$ts.menu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag"><i class="fas fa-ellipsis-h"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
<template v-if="!self">
|
||||
<span class="schema">{{ schema }}//</span>
|
||||
<span class="hostname">{{ hostname }}</span>
|
||||
<span class="port" v-if="port != ''">:{{ port }}</span>
|
||||
<span v-if="port != ''" class="port">:{{ port }}</span>
|
||||
</template>
|
||||
<template v-if="pathname === '/' && self">
|
||||
<span class="self">{{ hostname }}</span>
|
||||
</template>
|
||||
<span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span>
|
||||
<span v-if="pathname != ''" class="pathname">{{ self ? pathname.substr(1) : pathname }}</span>
|
||||
<span class="query">{{ query }}</span>
|
||||
<span class="hash">{{ hash }}</span>
|
||||
<i v-if="target === '_blank'" class="fas fa-external-link-square-alt icon"></i>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="mk-google">
|
||||
<input type="search" v-model="query" :placeholder="q">
|
||||
<input v-model="query" type="search" :placeholder="q">
|
||||
<button @click="search"><i class="fas fa-search"></i> {{ $ts.search }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="xubzgfgb" :class="{ cover }" :title="title">
|
||||
<canvas ref="canvas" :width="size" :height="size" :title="title" v-if="!loaded"/>
|
||||
<canvas v-if="!loaded" ref="canvas" :width="size" :height="size" :title="title"/>
|
||||
<img v-if="src" :src="src" :title="title" :alt="alt" @load="onLoad"/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
<div class="szkkfdyq _popup">
|
||||
<div class="main">
|
||||
<template v-for="item in items">
|
||||
<button v-if="item.action" class="_button" @click="$event => { item.action($event); close(); }" v-click-anime>
|
||||
<button v-if="item.action" v-click-anime class="_button" @click="$event => { item.action($event); close(); }">
|
||||
<i class="icon" :class="item.icon"></i>
|
||||
<div class="text">{{ item.text }}</div>
|
||||
<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
</button>
|
||||
<MkA v-else :to="item.to" @click.passive="close()" v-click-anime>
|
||||
<MkA v-else v-click-anime :to="item.to" @click.passive="close()">
|
||||
<i class="icon" :class="item.icon"></i>
|
||||
<div class="text">{{ item.text }}</div>
|
||||
<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span>
|
||||
|
@ -16,15 +16,15 @@
|
|||
</template>
|
||||
</div>
|
||||
<div class="sub">
|
||||
<a href="https://misskey-hub.net/help.html" target="_blank" @click.passive="close()" v-click-anime>
|
||||
<a v-click-anime href="https://misskey-hub.net/help.html" target="_blank" @click.passive="close()">
|
||||
<i class="fas fa-question-circle icon"></i>
|
||||
<div class="text">{{ $ts.help }}</div>
|
||||
</a>
|
||||
<MkA to="/about" @click.passive="close()" v-click-anime>
|
||||
<MkA v-click-anime to="/about" @click.passive="close()">
|
||||
<i class="fas fa-info-circle icon"></i>
|
||||
<div class="text">{{ $t('aboutX', { x: instanceName }) }}</div>
|
||||
</MkA>
|
||||
<MkA to="/about-misskey" @click.passive="close()" v-click-anime>
|
||||
<MkA v-click-anime to="/about-misskey" @click.passive="close()">
|
||||
<img src="/static-assets/favicon.png" class="icon"/>
|
||||
<div class="text">{{ $ts.aboutMisskey }}</div>
|
||||
</MkA>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<component :is="self ? 'MkA' : 'a'" class="xlcxczvw _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
|
||||
:title="url"
|
||||
@mouseover="onMouseover"
|
||||
@mouseleave="onMouseleave"
|
||||
:title="url"
|
||||
>
|
||||
<slot></slot>
|
||||
<i v-if="target === '_blank'" class="fas fa-external-link-square-alt icon"></i>
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<template>
|
||||
<div class="mk-media-banner">
|
||||
<div class="sensitive" v-if="media.isSensitive && hide" @click="hide = false">
|
||||
<div v-if="media.isSensitive && hide" class="sensitive" @click="hide = false">
|
||||
<span class="icon"><i class="fas fa-exclamation-triangle"></i></span>
|
||||
<b>{{ $ts.sensitive }}</b>
|
||||
<span>{{ $ts.clickToShow }}</span>
|
||||
</div>
|
||||
<div class="audio" v-else-if="media.type.startsWith('audio') && media.type !== 'audio/midi'">
|
||||
<audio class="audio"
|
||||
<div v-else-if="media.type.startsWith('audio') && media.type !== 'audio/midi'" class="audio">
|
||||
<audio ref="audio"
|
||||
class="audio"
|
||||
:src="media.url"
|
||||
:title="media.name"
|
||||
controls
|
||||
ref="audio"
|
||||
@volumechange="volumechange"
|
||||
preload="metadata" />
|
||||
preload="metadata"
|
||||
@volumechange="volumechange" />
|
||||
</div>
|
||||
<a class="download" v-else
|
||||
<a v-else class="download"
|
||||
:href="media.url"
|
||||
:title="media.name"
|
||||
:download="media.name"
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
<Mfm v-if="title" class="title" :text="title"/>
|
||||
<span class="text-count" :class="{ over: remainingLength < 0 }">{{ remainingLength }}</span>
|
||||
</header>
|
||||
<textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
|
||||
<div class="buttons" v-if="(showOkButton || showCancelButton)">
|
||||
<MkButton inline @click="ok" primary :disabled="remainingLength < 0">{{ $ts.ok }}</MkButton>
|
||||
<textarea v-model="inputValue" autofocus :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
|
||||
<div v-if="(showOkButton || showCancelButton)" class="buttons">
|
||||
<MkButton inline primary :disabled="remainingLength < 0" @click="ok">{{ $ts.ok }}</MkButton>
|
||||
<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="qjewsnkg" v-if="hide" @click="hide = false">
|
||||
<div v-if="hide" class="qjewsnkg" @click="hide = false">
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
||||
<div class="text">
|
||||
<div>
|
||||
|
@ -8,13 +8,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gqnyydlz" :style="{ background: color }" v-else>
|
||||
<div v-else class="gqnyydlz" :style="{ background: color }">
|
||||
<a
|
||||
:href="image.url"
|
||||
:title="image.name"
|
||||
>
|
||||
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
|
||||
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
|
||||
<div v-if="image.type === 'image/gif'" class="gif">GIF</div>
|
||||
</a>
|
||||
<i class="fas fa-eye-slash" @click="hide = true"></i>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="hoawjimk">
|
||||
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :media="media" :key="media.id"/>
|
||||
<XBanner v-for="media in mediaList.filter(media => !previewable(media))" :key="media.id" :media="media"/>
|
||||
<div v-if="mediaList.filter(media => previewable(media)).length > 0" class="gird-container">
|
||||
<div :data-count="mediaList.filter(media => previewable(media)).length" ref="gallery">
|
||||
<div ref="gallery" :data-count="mediaList.filter(media => previewable(media)).length">
|
||||
<template v-for="media in mediaList">
|
||||
<XVideo :video="media" :key="media.id" v-if="media.type.startsWith('video')"/>
|
||||
<XImage class="image" :data-id="media.id" :image="media" :key="media.id" v-else-if="media.type.startsWith('image')" :raw="raw"/>
|
||||
<XVideo v-if="media.type.startsWith('video')" :key="media.id" :video="media"/>
|
||||
<XImage v-else-if="media.type.startsWith('image')" :key="media.id" class="image" :data-id="media.id" :image="media" :raw="raw"/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="hide" @click="hide = false">
|
||||
<div v-if="hide" class="icozogqfvdetwohsdglrbswgrejoxbdj" @click="hide = false">
|
||||
<div>
|
||||
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||
<span>{{ $ts.clickToShow }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kkjnbbplepmiyuadieoenjgutgcmtsvu" v-else>
|
||||
<div v-else class="kkjnbbplepmiyuadieoenjgutgcmtsvu">
|
||||
<video
|
||||
:poster="video.thumbnailUrl"
|
||||
:title="video.name"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<MkA v-if="url.startsWith('/')" class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" :style="{ background: bg }">
|
||||
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="ldlomzub" :class="{ isMe }" :to="url" :style="{ background: bg }">
|
||||
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
|
||||
<span class="main">
|
||||
<span class="username">@{{ username }}</span>
|
||||
<span class="host" v-if="(host != localHost) || $store.state.showFullAcct">@{{ toUnicode(host) }}</span>
|
||||
<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span>
|
||||
</span>
|
||||
</MkA>
|
||||
<a v-else class="ldlomzub" :href="url" target="_blank" rel="noopener" :style="{ background: bg }">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')">
|
||||
<div class="hrmcaedk _window _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
|
||||
<div class="header" @contextmenu="onContextmenu">
|
||||
<button v-if="history.length > 0" class="_button" @click="back()" v-tooltip="$ts.goBack"><i class="fas fa-arrow-left"></i></button>
|
||||
<button v-if="history.length > 0" v-tooltip="$ts.goBack" class="_button" @click="back()"><i class="fas fa-arrow-left"></i></button>
|
||||
<span v-else style="display: inline-block; width: 20px"></span>
|
||||
<span v-if="pageInfo" class="title">
|
||||
<i v-if="pageInfo.icon" class="icon" :class="pageInfo.icon"></i>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue