Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
72ed803c2a | |||
9ec0e59431 | |||
5328ed64f3 | |||
33e8d61d65 | |||
3584786387 | |||
34f662ead5 | |||
2d53481cf5 | |||
10fb029609 | |||
0281961f15 | |||
fede4eeb89 | |||
ab50d5ef20 | |||
f4e02d4a4c | |||
167640df8d | |||
fe01437aa4 | |||
037fce4d6a | |||
db8b824b84 | |||
b71f62535d | |||
e9a1e281b9 | |||
0144408500 | |||
7660839e40 | |||
d1ca851ebe | |||
35a281d443 | |||
c2690fff47 |
@ -1 +1 @@
|
|||||||
v14.15.0
|
v14.15.1
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM node:14.15.0-alpine AS base
|
FROM node:14.15.1-alpine AS base
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
@ -273,7 +273,6 @@ popularTags: "الوسوم الرائجة"
|
|||||||
userList: "القوائم"
|
userList: "القوائم"
|
||||||
about: "عن"
|
about: "عن"
|
||||||
aboutMisskey: "عن Misskey"
|
aboutMisskey: "عن Misskey"
|
||||||
patrons: "الداعمون"
|
|
||||||
administrator: "المدير"
|
administrator: "المدير"
|
||||||
token: "الرمز المميز"
|
token: "الرمز المميز"
|
||||||
twoStepAuthentication: "الإستيثاق بعاملَيْن"
|
twoStepAuthentication: "الإستيثاق بعاملَيْن"
|
||||||
|
@ -125,7 +125,9 @@ settingGuide: "Empfohlene Einstellung"
|
|||||||
cacheRemoteFiles: "Dateien von anderen Instanzen im Cache speichern"
|
cacheRemoteFiles: "Dateien von anderen Instanzen im Cache speichern"
|
||||||
cacheRemoteFilesDescription: "Wenn diese Einstellung deaktiviert ist, werden Dateien anderer Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz gespart, aber mehr Bandbreite verbraucht, da keine Vorschaubilder generiert werden."
|
cacheRemoteFilesDescription: "Wenn diese Einstellung deaktiviert ist, werden Dateien anderer Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz gespart, aber mehr Bandbreite verbraucht, da keine Vorschaubilder generiert werden."
|
||||||
flagAsBot: "Als Bot markieren"
|
flagAsBot: "Als Bot markieren"
|
||||||
|
flagAsBotDescription: "Wenn dieser Account durch ein Programm gesteuert wird, setze diesen Haken. Falls aktiviert, agiert es als Flag für andere Entwickler um endlose Kettenreaktionen mit anderen Bots zu verhindern und lässt Misskey's interne Systeme diesen Account als Bot behandeln."
|
||||||
flagAsCat: "Als Katze markieren"
|
flagAsCat: "Als Katze markieren"
|
||||||
|
flagAsCatDescription: "Setze diese Flag um dieses Benutzerkonto als Katze zu markieren."
|
||||||
autoAcceptFollowed: "Follow-Anfragen automatisch akzeptieren"
|
autoAcceptFollowed: "Follow-Anfragen automatisch akzeptieren"
|
||||||
addAcount: "Benutzerkonto hinzufügen"
|
addAcount: "Benutzerkonto hinzufügen"
|
||||||
loginFailed: "Login fehlgeschlagen"
|
loginFailed: "Login fehlgeschlagen"
|
||||||
@ -358,13 +360,6 @@ popularTags: "Beliebte Schlagwörter"
|
|||||||
userList: "Listen"
|
userList: "Listen"
|
||||||
about: "Über"
|
about: "Über"
|
||||||
aboutMisskey: "Über Misskey"
|
aboutMisskey: "Über Misskey"
|
||||||
aboutMisskeyText: "Misskey ist Open-Source-Software die von syuilo seit 2014 entwickelt wird."
|
|
||||||
misskeyMembers: "Misskey wird momentan von den unten aufgelisteten Mitgliedern weiterentwickelt und instand gehalten:"
|
|
||||||
misskeySource: "Der Quelltext ist hier verfügbar:"
|
|
||||||
misskeyTranslation: "Hilf dabei, Misskey zu übersetzen:"
|
|
||||||
misskeyDonate: "Spende an Misskey, um die Weiterentwicklung zu unterstützen:"
|
|
||||||
morePatrons: "Wir schätzen ebenso die Unterstützung vieler anderer hier nicht gelisteter Personen sehr. Danke! 🥰"
|
|
||||||
patrons: "UnterstützerInnen"
|
|
||||||
administrator: "Administrator"
|
administrator: "Administrator"
|
||||||
token: "Token"
|
token: "Token"
|
||||||
twoStepAuthentication: "Zwei-Faktor-Authentifizierung"
|
twoStepAuthentication: "Zwei-Faktor-Authentifizierung"
|
||||||
@ -439,6 +434,7 @@ useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen"
|
|||||||
youHaveNoGroups: "Keine Gruppen vorhanden"
|
youHaveNoGroups: "Keine Gruppen vorhanden"
|
||||||
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
|
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
|
||||||
noHistory: "Kein Verlauf"
|
noHistory: "Kein Verlauf"
|
||||||
|
signinHistory: "Anmeldungsverlauf"
|
||||||
disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren"
|
disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren"
|
||||||
doing: "In Bearbeitung"
|
doing: "In Bearbeitung"
|
||||||
category: "Kategorie"
|
category: "Kategorie"
|
||||||
@ -491,6 +487,7 @@ none: "Keine"
|
|||||||
showInPage: "In Seite anzeigen"
|
showInPage: "In Seite anzeigen"
|
||||||
popout: "Pop-Up"
|
popout: "Pop-Up"
|
||||||
volume: "Lautstärke"
|
volume: "Lautstärke"
|
||||||
|
masterVolume: "Gesamtlautstärke"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Wähle ein Emoji"
|
chooseEmoji: "Wähle ein Emoji"
|
||||||
unableToProcess: "Der Vorgang konnte nicht abgeschlossen werden."
|
unableToProcess: "Der Vorgang konnte nicht abgeschlossen werden."
|
||||||
@ -548,6 +545,9 @@ useBlurEffectForModal: "Weichzeichnungseffekt für Modals verwenden"
|
|||||||
useFullReactionPicker: "Vollständige Reaktionsauswahl nutzen"
|
useFullReactionPicker: "Vollständige Reaktionsauswahl nutzen"
|
||||||
width: "Breite"
|
width: "Breite"
|
||||||
height: "Höhe"
|
height: "Höhe"
|
||||||
|
large: "Groß"
|
||||||
|
medium: "Mittel"
|
||||||
|
small: "Klein"
|
||||||
generateAccessToken: "Zugriffstoken generieren"
|
generateAccessToken: "Zugriffstoken generieren"
|
||||||
permission: "Berechtigungen"
|
permission: "Berechtigungen"
|
||||||
enableAll: "Alle aktivieren"
|
enableAll: "Alle aktivieren"
|
||||||
@ -560,7 +560,8 @@ useStarForReactionFallback: "Verwende ★ falls das Reaktions-Emoji unbekannt is
|
|||||||
emailConfig: "Email-Server Konfiguration"
|
emailConfig: "Email-Server Konfiguration"
|
||||||
enableEmail: "Email-Versand aktivieren"
|
enableEmail: "Email-Versand aktivieren"
|
||||||
emailConfigInfo: "Zur Email-Bestätigung bei Registrierung und zum Zurücksetzen des Passworts verwendet"
|
emailConfigInfo: "Zur Email-Bestätigung bei Registrierung und zum Zurücksetzen des Passworts verwendet"
|
||||||
email: "Email-Adresse"
|
email: "Email"
|
||||||
|
emailAddress: "Email-Adresse"
|
||||||
smtpConfig: "SMTP-Server Konfiguration"
|
smtpConfig: "SMTP-Server Konfiguration"
|
||||||
smtpHost: "Host"
|
smtpHost: "Host"
|
||||||
smtpPort: "Port"
|
smtpPort: "Port"
|
||||||
@ -592,6 +593,7 @@ regenerateLoginTokenDescription: "Den bei Logins intern verwendeten Token regene
|
|||||||
setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren."
|
setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren."
|
||||||
fileIdOrUrl: "Datei-ID oder URL"
|
fileIdOrUrl: "Datei-ID oder URL"
|
||||||
chatOpenBehavior: "Verhalten des Chatfensters bei Öffnung"
|
chatOpenBehavior: "Verhalten des Chatfensters bei Öffnung"
|
||||||
|
behavior: "Verhalten"
|
||||||
sample: "Beispiel"
|
sample: "Beispiel"
|
||||||
abuseReports: "Melden"
|
abuseReports: "Melden"
|
||||||
reportAbuse: "Melden"
|
reportAbuse: "Melden"
|
||||||
@ -615,6 +617,41 @@ createNew: "Neu erstellen"
|
|||||||
optional: "Optional"
|
optional: "Optional"
|
||||||
createNewClip: "Neuen Clip erstellen"
|
createNewClip: "Neuen Clip erstellen"
|
||||||
public: "Öffentlich"
|
public: "Öffentlich"
|
||||||
|
i18nInfo: "Misskey wird durch freiwillige Helfer in viele verschiedene Sprachen übersetzt. Unter {link} kannst du mithelfen."
|
||||||
|
manageAccessTokens: "Zugriffstoken verwalten"
|
||||||
|
accountInfo: "Benutzerkonto-Informationen"
|
||||||
|
notesCount: "Anzahl von Notizen"
|
||||||
|
repliesCount: "Anzahl gesendeter Antworten"
|
||||||
|
renotesCount: "Anzahl gesendeter Renotes"
|
||||||
|
repliedCount: "Anzahl erhaltener Antworten"
|
||||||
|
renotedCount: "Anzahl erhaltener Renotes"
|
||||||
|
followingCount: "Anzahl gefolgter Benutzer"
|
||||||
|
followersCount: "Anzahl an Followern"
|
||||||
|
sentReactionsCount: "Anzahl gesendeter Reaktionen"
|
||||||
|
receivedReactionsCount: "Anzahl erhaltener Reaktionen"
|
||||||
|
pollVotesCount: "Anzahl beantworteter Umfragen"
|
||||||
|
pollVotedCount: "Anzahl erhaltener Umfrageantworten"
|
||||||
|
yes: "Ja"
|
||||||
|
no: "Nein"
|
||||||
|
driveFilesCount: "Anzahl von Drive-Dateien"
|
||||||
|
driveUsage: "Drive-Auslastung"
|
||||||
|
noCrawle: "Crawler-Indexierung ablehnen"
|
||||||
|
noCrawleDescription: "Suchmaschinen bitten, die eigene Profilseite, Notizen, Seiten usw. nicht zu indexieren"
|
||||||
|
lockedAccountInfo: "Auch wenn du Follow-Anfragen auf manuelle Bestätigung setzt, wird jeder deine Notizen öffentlich sehen können, sofern du die Notizsichtbarkeit nicht auf \"Nur Follower\" setzt."
|
||||||
|
alwaysMarkSensitive: "Immer als NSFW markieren"
|
||||||
|
loadRawImages: "Anstatt Vorschaubild immer volles Bild laden"
|
||||||
|
disableShowingAnimatedImages: "Animierte Bilder nicht abspielen"
|
||||||
|
verificationEmailSent: "Eine Verifizierungsnachricht wurde versendet. Besuche den dort enthaltenen Link, um die Verifizierung abzuschließen."
|
||||||
|
notSet: "Nicht konfiguriert"
|
||||||
|
emailVerified: "Email-Adresse bestätigt"
|
||||||
|
noteFavoritesCount: "Anzahl favorisierter Notizen"
|
||||||
|
pageLikesCount: "Anzahl der Seiten, die mir gefallen"
|
||||||
|
pageLikedCount: "Anzahl erhaltener \"Gefällt mir\" auf Seiten"
|
||||||
|
reversiCount: "Anzahl von Reversi-Runden"
|
||||||
|
_nsfw:
|
||||||
|
respect: "Als NSFW markierte Bilder verdecken"
|
||||||
|
ignore: "Als NSFW markierte Bilder nicht verdecken"
|
||||||
|
force: "Alle Medien verdecken"
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "MFM Spickzettel"
|
cheatSheet: "MFM Spickzettel"
|
||||||
intro: "MFM ist eine an vielen Stellen verwendbare und Misskey-exklusive Markup-Sprache. Hier kannst du eine Liste von verfügbarer MFM-Syntax anschauen."
|
intro: "MFM ist eine an vielen Stellen verwendbare und Misskey-exklusive Markup-Sprache. Hier kannst du eine Liste von verfügbarer MFM-Syntax anschauen."
|
||||||
@ -716,7 +753,7 @@ _channel:
|
|||||||
notesCount: "{n} Notizen"
|
notesCount: "{n} Notizen"
|
||||||
_sidebar:
|
_sidebar:
|
||||||
full: "Voll"
|
full: "Voll"
|
||||||
icon: "Symbol"
|
icon: "Symbole"
|
||||||
hide: "Ausblenden"
|
hide: "Ausblenden"
|
||||||
_wordMute:
|
_wordMute:
|
||||||
muteWords: "Wort stummschalten"
|
muteWords: "Wort stummschalten"
|
||||||
@ -733,6 +770,8 @@ _theme:
|
|||||||
manage: "Themaverwaltung"
|
manage: "Themaverwaltung"
|
||||||
code: "Themen-Code"
|
code: "Themen-Code"
|
||||||
installed: "{name} wurde installiert"
|
installed: "{name} wurde installiert"
|
||||||
|
installedThemes: "Installierte Themen"
|
||||||
|
builtinThemes: "Eingebaute Themen"
|
||||||
alreadyInstalled: "Dieses Thema ist bereits installiert"
|
alreadyInstalled: "Dieses Thema ist bereits installiert"
|
||||||
invalid: "Themenformat ist ungültig"
|
invalid: "Themenformat ist ungültig"
|
||||||
make: "Farbthema erstellen"
|
make: "Farbthema erstellen"
|
||||||
@ -806,6 +845,8 @@ _sfx:
|
|||||||
chatBg: "Nachrichten (Hintergrund)"
|
chatBg: "Nachrichten (Hintergrund)"
|
||||||
antenna: "Antennen"
|
antenna: "Antennen"
|
||||||
channel: "Kanalbenachrichtigung"
|
channel: "Kanalbenachrichtigung"
|
||||||
|
reversiPutBlack: "Reversi: Schwarz macht einen Zug"
|
||||||
|
reversiPutWhite: "Reversi: Weiß macht einen Zug"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Unbekannt"
|
unknown: "Unbekannt"
|
||||||
future: "Zukunft"
|
future: "Zukunft"
|
||||||
@ -971,7 +1012,9 @@ _profile:
|
|||||||
username: "Benutzername"
|
username: "Benutzername"
|
||||||
description: "Über mich"
|
description: "Über mich"
|
||||||
youCanIncludeHashtags: "Du kannst auch Hashtags in deiner Beschreibung verwenden."
|
youCanIncludeHashtags: "Du kannst auch Hashtags in deiner Beschreibung verwenden."
|
||||||
metadata: "Andere Informationen"
|
metadata: "Zusätzliche Informationen"
|
||||||
|
metadataEdit: "Zusätzliche Informationen bearbeiten"
|
||||||
|
metadataDescription: "Du kannst auf deinem Profil vier zusätzliche Informationsblöcke anzeigen lassen."
|
||||||
metadataLabel: "Name"
|
metadataLabel: "Name"
|
||||||
metadataContent: "Inhalt"
|
metadataContent: "Inhalt"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -125,7 +125,9 @@ settingGuide: "Suggested Configuration"
|
|||||||
cacheRemoteFiles: "Cache remote files"
|
cacheRemoteFiles: "Cache remote files"
|
||||||
cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote instance. Disabling this will decrease storage usage, but will increase traffic, because thumbnails will not be generated."
|
cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote instance. Disabling this will decrease storage usage, but will increase traffic, because thumbnails will not be generated."
|
||||||
flagAsBot: "This account is a bot"
|
flagAsBot: "This account is a bot"
|
||||||
|
flagAsBotDescription: "If this account is controlled by a program, set this option. If enabled, it will act as flag for other developers to prevent endless interaction chains with other bots and adjust Misskey's internal systems to treat this account as a bot."
|
||||||
flagAsCat: "This account is a cat"
|
flagAsCat: "This account is a cat"
|
||||||
|
flagAsCatDescription: "Toggle this flag on for this account to be marked as a cat."
|
||||||
autoAcceptFollowed: "Automatically approve follow requests from users you're following"
|
autoAcceptFollowed: "Automatically approve follow requests from users you're following"
|
||||||
addAcount: "Add Account"
|
addAcount: "Add Account"
|
||||||
loginFailed: "Failed to sign in"
|
loginFailed: "Failed to sign in"
|
||||||
@ -358,13 +360,6 @@ popularTags: "Trending Tags"
|
|||||||
userList: "Lists"
|
userList: "Lists"
|
||||||
about: "About"
|
about: "About"
|
||||||
aboutMisskey: "About Misskey"
|
aboutMisskey: "About Misskey"
|
||||||
aboutMisskeyText: "Misskey is an open-source software developed by syuilo since 2014."
|
|
||||||
misskeyMembers: "It is currently developed and maintained by the members listed below:"
|
|
||||||
misskeySource: "Source code is available here:"
|
|
||||||
misskeyTranslation: "Help us with your contribution to translate Misskey:"
|
|
||||||
misskeyDonate: "Help us to keep improving the software by donating here:"
|
|
||||||
morePatrons: "We really appreciate the support of many other helpers not listed here. Thank you! 🥰"
|
|
||||||
patrons: "Backers"
|
|
||||||
administrator: "Admin"
|
administrator: "Admin"
|
||||||
token: "Token"
|
token: "Token"
|
||||||
twoStepAuthentication: "Two-factor authentication"
|
twoStepAuthentication: "Two-factor authentication"
|
||||||
@ -439,6 +434,7 @@ useOsNativeEmojis: "Use OS native Emojis"
|
|||||||
youHaveNoGroups: "You have no groups"
|
youHaveNoGroups: "You have no groups"
|
||||||
joinOrCreateGroup: "Get invited to join the groups or you can create your own group."
|
joinOrCreateGroup: "Get invited to join the groups or you can create your own group."
|
||||||
noHistory: "No history items"
|
noHistory: "No history items"
|
||||||
|
signinHistory: "Login history"
|
||||||
disableAnimatedMfm: "Disable MFM with animation"
|
disableAnimatedMfm: "Disable MFM with animation"
|
||||||
doing: "On my way"
|
doing: "On my way"
|
||||||
category: "Category"
|
category: "Category"
|
||||||
@ -491,6 +487,7 @@ none: "None"
|
|||||||
showInPage: "Show in page"
|
showInPage: "Show in page"
|
||||||
popout: "Pop-out"
|
popout: "Pop-out"
|
||||||
volume: "Volume"
|
volume: "Volume"
|
||||||
|
masterVolume: "Master volume"
|
||||||
details: "Details"
|
details: "Details"
|
||||||
chooseEmoji: "Choose an emoji"
|
chooseEmoji: "Choose an emoji"
|
||||||
unableToProcess: "The operation could not be completed."
|
unableToProcess: "The operation could not be completed."
|
||||||
@ -548,6 +545,9 @@ useBlurEffectForModal: "Use blur effect for modals"
|
|||||||
useFullReactionPicker: "Use full-size reaction picker"
|
useFullReactionPicker: "Use full-size reaction picker"
|
||||||
width: "Width"
|
width: "Width"
|
||||||
height: "Height"
|
height: "Height"
|
||||||
|
large: "Big"
|
||||||
|
medium: "Medium"
|
||||||
|
small: "Small"
|
||||||
generateAccessToken: "Generate access token"
|
generateAccessToken: "Generate access token"
|
||||||
permission: "Permissions"
|
permission: "Permissions"
|
||||||
enableAll: "Enable all"
|
enableAll: "Enable all"
|
||||||
@ -560,7 +560,8 @@ useStarForReactionFallback: "Use ★ as fallback if the reaction emoji is unknow
|
|||||||
emailConfig: "Email server configuration"
|
emailConfig: "Email server configuration"
|
||||||
enableEmail: "Enable email distribution"
|
enableEmail: "Enable email distribution"
|
||||||
emailConfigInfo: "Used to confirm your email during sign-up and if you forget your password"
|
emailConfigInfo: "Used to confirm your email during sign-up and if you forget your password"
|
||||||
email: "Email Address"
|
email: "Email"
|
||||||
|
emailAddress: "Email address"
|
||||||
smtpConfig: "SMTP Server configuration"
|
smtpConfig: "SMTP Server configuration"
|
||||||
smtpHost: "Host"
|
smtpHost: "Host"
|
||||||
smtpPort: "Port"
|
smtpPort: "Port"
|
||||||
@ -592,6 +593,7 @@ regenerateLoginTokenDescription: "Regenerate the token used internally during lo
|
|||||||
setMultipleBySeparatingWithSpace: "You can set multiple by separating them with spaces."
|
setMultipleBySeparatingWithSpace: "You can set multiple by separating them with spaces."
|
||||||
fileIdOrUrl: "File-ID or URL"
|
fileIdOrUrl: "File-ID or URL"
|
||||||
chatOpenBehavior: "Behavior of the chat window when opened"
|
chatOpenBehavior: "Behavior of the chat window when opened"
|
||||||
|
behavior: "Behavior"
|
||||||
sample: "Sample"
|
sample: "Sample"
|
||||||
abuseReports: "Reports"
|
abuseReports: "Reports"
|
||||||
reportAbuse: "Report"
|
reportAbuse: "Report"
|
||||||
@ -615,6 +617,41 @@ createNew: "Create new"
|
|||||||
optional: "Optional"
|
optional: "Optional"
|
||||||
createNewClip: "Create new clip"
|
createNewClip: "Create new clip"
|
||||||
public: "Public"
|
public: "Public"
|
||||||
|
i18nInfo: "Misskey is being translated into various languages by volunteers. You can help at {link}."
|
||||||
|
manageAccessTokens: "Manage access tokens"
|
||||||
|
accountInfo: "Account Info"
|
||||||
|
notesCount: "Amount of notes"
|
||||||
|
repliesCount: "Amount of replies sent"
|
||||||
|
renotesCount: "Amount of renotes sent"
|
||||||
|
repliedCount: "Amount of replies received"
|
||||||
|
renotedCount: "Amount of renotes received"
|
||||||
|
followingCount: "Amount of followed accounts"
|
||||||
|
followersCount: "Amount of followers"
|
||||||
|
sentReactionsCount: "Amount of sent reactions"
|
||||||
|
receivedReactionsCount: "Amount of received reactions"
|
||||||
|
pollVotesCount: "Amount of sent poll votes"
|
||||||
|
pollVotedCount: "Amount of received poll votes"
|
||||||
|
yes: "Yes"
|
||||||
|
no: "No"
|
||||||
|
driveFilesCount: "Amount of drive files"
|
||||||
|
driveUsage: "Drive space usage"
|
||||||
|
noCrawle: "Reject crawler indexing"
|
||||||
|
noCrawleDescription: "Ask search engines not to index your profile page, notes, Pages, etc"
|
||||||
|
lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", your notes are visible to anyone even if you require followers to be manually approved."
|
||||||
|
alwaysMarkSensitive: "Mark NSFW by default"
|
||||||
|
loadRawImages: "Display image attachments fully instead of thumbnails"
|
||||||
|
disableShowingAnimatedImages: "Don't play animated images"
|
||||||
|
verificationEmailSent: "A verification email has been sent. Please access the included link to complete verification."
|
||||||
|
notSet: "Not set"
|
||||||
|
emailVerified: "Email has been verified"
|
||||||
|
noteFavoritesCount: "Amount of favorite notes"
|
||||||
|
pageLikesCount: "Amount of received Page likes"
|
||||||
|
pageLikedCount: "Amount of liked Pages"
|
||||||
|
reversiCount: "Number of Reversi matches"
|
||||||
|
_nsfw:
|
||||||
|
respect: "Hide NSFW media"
|
||||||
|
ignore: "Don't hide NSFW media"
|
||||||
|
force: "Hide all media"
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "MFM Cheatsheet"
|
cheatSheet: "MFM Cheatsheet"
|
||||||
intro: "MFM is a Misskey-exclusive markup language that can be used in many places. Here you can view a list of all available MFM syntax."
|
intro: "MFM is a Misskey-exclusive markup language that can be used in many places. Here you can view a list of all available MFM syntax."
|
||||||
@ -716,7 +753,7 @@ _channel:
|
|||||||
notesCount: "{n} Notes"
|
notesCount: "{n} Notes"
|
||||||
_sidebar:
|
_sidebar:
|
||||||
full: "Full"
|
full: "Full"
|
||||||
icon: "Avatar"
|
icon: "Icons"
|
||||||
hide: "Hide"
|
hide: "Hide"
|
||||||
_wordMute:
|
_wordMute:
|
||||||
muteWords: "Word to mute"
|
muteWords: "Word to mute"
|
||||||
@ -733,6 +770,8 @@ _theme:
|
|||||||
manage: "Themes manager"
|
manage: "Themes manager"
|
||||||
code: "Theme code"
|
code: "Theme code"
|
||||||
installed: "{name} has been installed"
|
installed: "{name} has been installed"
|
||||||
|
installedThemes: "Installed themes"
|
||||||
|
builtinThemes: "Built-in themes"
|
||||||
alreadyInstalled: "The theme is already installed"
|
alreadyInstalled: "The theme is already installed"
|
||||||
invalid: "Theme format is invalid"
|
invalid: "Theme format is invalid"
|
||||||
make: "Make a theme"
|
make: "Make a theme"
|
||||||
@ -806,6 +845,8 @@ _sfx:
|
|||||||
chatBg: "Messaging (Background)"
|
chatBg: "Messaging (Background)"
|
||||||
antenna: "Antenna Reception"
|
antenna: "Antenna Reception"
|
||||||
channel: "Channel notifications"
|
channel: "Channel notifications"
|
||||||
|
reversiPutBlack: "Reversi: Black makes a move"
|
||||||
|
reversiPutWhite: "Reversi: White makes a move"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Unknown"
|
unknown: "Unknown"
|
||||||
future: "Future"
|
future: "Future"
|
||||||
@ -971,7 +1012,9 @@ _profile:
|
|||||||
username: "Username"
|
username: "Username"
|
||||||
description: "Bio"
|
description: "Bio"
|
||||||
youCanIncludeHashtags: "You can also include hashtags in your bio."
|
youCanIncludeHashtags: "You can also include hashtags in your bio."
|
||||||
metadata: "Other information"
|
metadata: "Additional Information"
|
||||||
|
metadataEdit: "Edit additional Information"
|
||||||
|
metadataDescription: "You can display up to four additional information sections in your profile."
|
||||||
metadataLabel: "Label"
|
metadataLabel: "Label"
|
||||||
metadataContent: "Content"
|
metadataContent: "Content"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -354,13 +354,6 @@ popularTags: "Etiquetas populares"
|
|||||||
userList: "Lista"
|
userList: "Lista"
|
||||||
about: "Información"
|
about: "Información"
|
||||||
aboutMisskey: "Sobre Misskey"
|
aboutMisskey: "Sobre Misskey"
|
||||||
aboutMisskeyText: "Misskey es un software de código abierto, desarrollado por syuilo desde el 2014"
|
|
||||||
misskeyMembers: "Es creado y mantenido por los miembros aquí listados:"
|
|
||||||
misskeySource: "El código fuente está disponible aquí:"
|
|
||||||
misskeyTranslation: "Ayúdanos con tu contribución para traducir Misskey:"
|
|
||||||
misskeyDonate: "Puedes contribuir al desarrollo de Misskey donando aquí:"
|
|
||||||
morePatrons: "Muchas más personas nos apoyan. Muchas gracias🥰"
|
|
||||||
patrons: "Patrocinadores"
|
|
||||||
administrator: "Administrador"
|
administrator: "Administrador"
|
||||||
token: "Token"
|
token: "Token"
|
||||||
twoStepAuthentication: "Autenticación de dos factores"
|
twoStepAuthentication: "Autenticación de dos factores"
|
||||||
@ -556,7 +549,6 @@ useStarForReactionFallback: "En caso de que los emojis de reacciones no sean cla
|
|||||||
emailConfig: "Configuración del servidor de correos"
|
emailConfig: "Configuración del servidor de correos"
|
||||||
enableEmail: "Activar el envío de correos electrónicos"
|
enableEmail: "Activar el envío de correos electrónicos"
|
||||||
emailConfigInfo: "Usar en caso de validación de correo electrónico y pedido de contraseña"
|
emailConfigInfo: "Usar en caso de validación de correo electrónico y pedido de contraseña"
|
||||||
email: "Correo electrónico"
|
|
||||||
smtpConfig: "Configuración del servidor SMTP"
|
smtpConfig: "Configuración del servidor SMTP"
|
||||||
smtpHost: "Host"
|
smtpHost: "Host"
|
||||||
smtpPort: "Puerto"
|
smtpPort: "Puerto"
|
||||||
@ -932,7 +924,6 @@ _profile:
|
|||||||
username: "Nombre de usuario"
|
username: "Nombre de usuario"
|
||||||
description: "Descripción"
|
description: "Descripción"
|
||||||
youCanIncludeHashtags: "Puedes añadir hashtags"
|
youCanIncludeHashtags: "Puedes añadir hashtags"
|
||||||
metadata: "Información adicional"
|
|
||||||
metadataLabel: "Etiqueta"
|
metadataLabel: "Etiqueta"
|
||||||
metadataContent: "Contenido"
|
metadataContent: "Contenido"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -353,13 +353,6 @@ popularTags: "Mots-clés populaires"
|
|||||||
userList: "Listes"
|
userList: "Listes"
|
||||||
about: "Informations"
|
about: "Informations"
|
||||||
aboutMisskey: "À propos de Misskey"
|
aboutMisskey: "À propos de Misskey"
|
||||||
aboutMisskeyText: "Misskey est un logiciel libre et ouvert, développé par syuilo depuis 2014."
|
|
||||||
misskeyMembers: "Il est développé et maintenu par les membres listés ci-dessous :"
|
|
||||||
misskeySource: "Le code source est disponible ici:"
|
|
||||||
misskeyTranslation: "Aidez-nous en contribuant à traduire Misskey :"
|
|
||||||
misskeyDonate: "Vous pouvez contribuer au développement de Misskey en faisant un don ici:"
|
|
||||||
morePatrons: "Nous apprécions vraiment le soutien de nombreuses autres personnes non mentionnées ici. Merci à toutes et à tous ! 🥰"
|
|
||||||
patrons: "Supporteurs"
|
|
||||||
administrator: "Administrateur"
|
administrator: "Administrateur"
|
||||||
token: "Jeton"
|
token: "Jeton"
|
||||||
twoStepAuthentication: "Authentification à deux facteurs"
|
twoStepAuthentication: "Authentification à deux facteurs"
|
||||||
@ -552,7 +545,6 @@ useStarForReactionFallback: "Utiliser ★ comme alternative si l’émoji de ré
|
|||||||
emailConfig: "Configuration du serveur email"
|
emailConfig: "Configuration du serveur email"
|
||||||
enableEmail: "Activer la distribution de courriel"
|
enableEmail: "Activer la distribution de courriel"
|
||||||
emailConfigInfo: "Utilisé pour confirmer votre adresse de courriel et la réinitialisation de votre mot de passe en cas d’oubli."
|
emailConfigInfo: "Utilisé pour confirmer votre adresse de courriel et la réinitialisation de votre mot de passe en cas d’oubli."
|
||||||
email: "Adresse de courrier électronique"
|
|
||||||
smtpConfig: "Paramètres du serveur SMTP"
|
smtpConfig: "Paramètres du serveur SMTP"
|
||||||
smtpHost: "Hôte"
|
smtpHost: "Hôte"
|
||||||
smtpPort: "Port"
|
smtpPort: "Port"
|
||||||
@ -823,7 +815,6 @@ _profile:
|
|||||||
username: "Nom d’utilisateur·rice"
|
username: "Nom d’utilisateur·rice"
|
||||||
description: "À propos de moi"
|
description: "À propos de moi"
|
||||||
youCanIncludeHashtags: "Vous pouvez également inclure des hashtags."
|
youCanIncludeHashtags: "Vous pouvez également inclure des hashtags."
|
||||||
metadata: "Informations complémentaires"
|
|
||||||
metadataLabel: "Étiquette"
|
metadataLabel: "Étiquette"
|
||||||
metadataContent: "Contenu"
|
metadataContent: "Contenu"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -125,7 +125,9 @@ settingGuide: "おすすめ設定"
|
|||||||
cacheRemoteFiles: "リモートのファイルをキャッシュする"
|
cacheRemoteFiles: "リモートのファイルをキャッシュする"
|
||||||
cacheRemoteFilesDescription: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクするようになります。サーバーのストレージを節約できますが、サムネイルが生成されないので通信量が増加します。"
|
cacheRemoteFilesDescription: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクするようになります。サーバーのストレージを節約できますが、サムネイルが生成されないので通信量が増加します。"
|
||||||
flagAsBot: "Botとして設定"
|
flagAsBot: "Botとして設定"
|
||||||
|
flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。"
|
||||||
flagAsCat: "Catとして設定"
|
flagAsCat: "Catとして設定"
|
||||||
|
flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。"
|
||||||
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
|
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
|
||||||
addAcount: "アカウント追加"
|
addAcount: "アカウント追加"
|
||||||
loginFailed: "ログインに失敗しました"
|
loginFailed: "ログインに失敗しました"
|
||||||
@ -358,13 +360,6 @@ popularTags: "人気のタグ"
|
|||||||
userList: "リスト"
|
userList: "リスト"
|
||||||
about: "情報"
|
about: "情報"
|
||||||
aboutMisskey: "Misskeyについて"
|
aboutMisskey: "Misskeyについて"
|
||||||
aboutMisskeyText: "Misskeyはsyuiloによって2014年から開発されている、オープンソースのソフトウェアです。"
|
|
||||||
misskeyMembers: "現在以下のメンバーによって開発・メンテナンスされています:"
|
|
||||||
misskeySource: "ソースコードはここで公開されています:"
|
|
||||||
misskeyTranslation: "Misskeyの翻訳にご協力をお願いします:"
|
|
||||||
misskeyDonate: "Misskeyに寄付をして開発をサポートできます:"
|
|
||||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
|
|
||||||
patrons: "支援者"
|
|
||||||
administrator: "管理者"
|
administrator: "管理者"
|
||||||
token: "トークン"
|
token: "トークン"
|
||||||
twoStepAuthentication: "二段階認証"
|
twoStepAuthentication: "二段階認証"
|
||||||
@ -439,6 +434,7 @@ useOsNativeEmojis: "OSネイティブの絵文字を使用"
|
|||||||
youHaveNoGroups: "グループがありません"
|
youHaveNoGroups: "グループがありません"
|
||||||
joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。"
|
joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。"
|
||||||
noHistory: "履歴はありません"
|
noHistory: "履歴はありません"
|
||||||
|
signinHistory: "ログイン履歴"
|
||||||
disableAnimatedMfm: "動きのあるMFMを無効にする"
|
disableAnimatedMfm: "動きのあるMFMを無効にする"
|
||||||
doing: "やっています"
|
doing: "やっています"
|
||||||
category: "カテゴリ"
|
category: "カテゴリ"
|
||||||
@ -491,6 +487,7 @@ none: "なし"
|
|||||||
showInPage: "ページで表示"
|
showInPage: "ページで表示"
|
||||||
popout: "ポップアウト"
|
popout: "ポップアウト"
|
||||||
volume: "音量"
|
volume: "音量"
|
||||||
|
masterVolume: "マスター音量"
|
||||||
details: "詳細"
|
details: "詳細"
|
||||||
chooseEmoji: "絵文字を選択"
|
chooseEmoji: "絵文字を選択"
|
||||||
unableToProcess: "操作を完了できません"
|
unableToProcess: "操作を完了できません"
|
||||||
@ -563,7 +560,8 @@ useStarForReactionFallback: "リアクション絵文字が不明な場合、代
|
|||||||
emailConfig: "メールサーバー設定"
|
emailConfig: "メールサーバー設定"
|
||||||
enableEmail: "メール配信機能を有効化する"
|
enableEmail: "メール配信機能を有効化する"
|
||||||
emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います"
|
emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います"
|
||||||
email: "メールアドレス"
|
email: "メール"
|
||||||
|
emailAddress: "メールアドレス"
|
||||||
smtpConfig: "SMTP サーバーの設定"
|
smtpConfig: "SMTP サーバーの設定"
|
||||||
smtpHost: "ホスト"
|
smtpHost: "ホスト"
|
||||||
smtpPort: "ポート"
|
smtpPort: "ポート"
|
||||||
@ -595,6 +593,7 @@ regenerateLoginTokenDescription: "ログインに使用される内部トーク
|
|||||||
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
|
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
|
||||||
fileIdOrUrl: "ファイルIDまたはURL"
|
fileIdOrUrl: "ファイルIDまたはURL"
|
||||||
chatOpenBehavior: "チャットを開くときの動作"
|
chatOpenBehavior: "チャットを開くときの動作"
|
||||||
|
behavior: "動作"
|
||||||
sample: "サンプル"
|
sample: "サンプル"
|
||||||
abuseReports: "通報"
|
abuseReports: "通報"
|
||||||
reportAbuse: "通報"
|
reportAbuse: "通報"
|
||||||
@ -618,6 +617,54 @@ createNew: "新規作成"
|
|||||||
optional: "任意"
|
optional: "任意"
|
||||||
createNewClip: "新しいクリップを作成"
|
createNewClip: "新しいクリップを作成"
|
||||||
public: "パブリック"
|
public: "パブリック"
|
||||||
|
i18nInfo: "Misskeyは有志によって様々な言語に翻訳されています。{link}で翻訳に協力できます。"
|
||||||
|
manageAccessTokens: "アクセストークンの管理"
|
||||||
|
accountInfo: "アカウント情報"
|
||||||
|
notesCount: "ノートの数"
|
||||||
|
repliesCount: "返信した数"
|
||||||
|
renotesCount: "Renoteした数"
|
||||||
|
repliedCount: "返信された数"
|
||||||
|
renotedCount: "Renoteされた数"
|
||||||
|
followingCount: "フォロー数"
|
||||||
|
followersCount: "フォロワー数"
|
||||||
|
sentReactionsCount: "リアクションした数"
|
||||||
|
receivedReactionsCount: "リアクションされた数"
|
||||||
|
pollVotesCount: "アンケートに投票した数"
|
||||||
|
pollVotedCount: "アンケートに投票された数"
|
||||||
|
yes: "はい"
|
||||||
|
no: "いいえ"
|
||||||
|
driveFilesCount: "ドライブのファイル数"
|
||||||
|
driveUsage: "ドライブ使用量"
|
||||||
|
noCrawle: "クローラーによるインデックスを拒否"
|
||||||
|
noCrawleDescription: "検索エンジンにあなたのユーザーページ、ノート、Pagesなどのコンテンツを登録(インデックス)しないよう要請します。"
|
||||||
|
lockedAccountInfo: "フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。"
|
||||||
|
alwaysMarkSensitive: "デフォルトでメディアを閲覧注意にする"
|
||||||
|
loadRawImages: "添付画像のサムネイルをオリジナル画質にする"
|
||||||
|
disableShowingAnimatedImages: "アニメーション画像を再生しない"
|
||||||
|
verificationEmailSent: "確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。"
|
||||||
|
notSet: "未設定"
|
||||||
|
emailVerified: "メールアドレスが確認されました"
|
||||||
|
noteFavoritesCount: "お気に入りノートの数"
|
||||||
|
pageLikesCount: "Pageにいいねした数"
|
||||||
|
pageLikedCount: "Pageにいいねされた数"
|
||||||
|
reversiCount: "リバーシの対局数"
|
||||||
|
contact: "連絡先"
|
||||||
|
useSystemFont: "システムのデフォルトのフォントを使う"
|
||||||
|
|
||||||
|
_aboutMisskey:
|
||||||
|
about: "Misskeyはsyuiloによって2014年から開発されている、オープンソースのソフトウェアです。"
|
||||||
|
contributors: "主なコントリビューター"
|
||||||
|
allContributors: "全てのコントリビューター"
|
||||||
|
source: "ソースコード"
|
||||||
|
translation: "Misskeyを翻訳"
|
||||||
|
donate: "Misskeyに寄付"
|
||||||
|
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
|
||||||
|
patrons: "支援者"
|
||||||
|
|
||||||
|
_nsfw:
|
||||||
|
respect: "閲覧注意のメディアは隠す"
|
||||||
|
ignore: "閲覧注意のメディアを隠さない"
|
||||||
|
force: "常にメディアを隠す"
|
||||||
|
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "MFMチートシート"
|
cheatSheet: "MFMチートシート"
|
||||||
@ -744,6 +791,8 @@ _theme:
|
|||||||
manage: "テーマの管理"
|
manage: "テーマの管理"
|
||||||
code: "テーマコード"
|
code: "テーマコード"
|
||||||
installed: "{name}をインストールしました"
|
installed: "{name}をインストールしました"
|
||||||
|
installedThemes: "インストールされたテーマ"
|
||||||
|
builtinThemes: "標準のテーマ"
|
||||||
alreadyInstalled: "そのテーマは既にインストールされています"
|
alreadyInstalled: "そのテーマは既にインストールされています"
|
||||||
invalid: "テーマの形式が間違っています"
|
invalid: "テーマの形式が間違っています"
|
||||||
make: "テーマを作る"
|
make: "テーマを作る"
|
||||||
@ -819,6 +868,8 @@ _sfx:
|
|||||||
chatBg: "チャット(バックグラウンド)"
|
chatBg: "チャット(バックグラウンド)"
|
||||||
antenna: "アンテナ受信"
|
antenna: "アンテナ受信"
|
||||||
channel: "チャンネル通知"
|
channel: "チャンネル通知"
|
||||||
|
reversiPutBlack: "リバーシ: 黒が打ったとき"
|
||||||
|
reversiPutWhite: "リバーシ: 白が打ったとき"
|
||||||
|
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "謎"
|
unknown: "謎"
|
||||||
@ -998,7 +1049,9 @@ _profile:
|
|||||||
username: "ユーザー名"
|
username: "ユーザー名"
|
||||||
description: "自己紹介"
|
description: "自己紹介"
|
||||||
youCanIncludeHashtags: "ハッシュタグを含めることができます。"
|
youCanIncludeHashtags: "ハッシュタグを含めることができます。"
|
||||||
metadata: "補足情報"
|
metadata: "追加情報"
|
||||||
|
metadataEdit: "追加情報を編集"
|
||||||
|
metadataDescription: "プロフィールに表として4つまでの追加情報を表示することができます。"
|
||||||
metadataLabel: "ラベル"
|
metadataLabel: "ラベル"
|
||||||
metadataContent: "内容"
|
metadataContent: "内容"
|
||||||
|
|
||||||
|
@ -354,13 +354,6 @@ popularTags: "人気のタグ"
|
|||||||
userList: "リスト"
|
userList: "リスト"
|
||||||
about: "情報"
|
about: "情報"
|
||||||
aboutMisskey: "Misskeyってなんや?"
|
aboutMisskey: "Misskeyってなんや?"
|
||||||
aboutMisskeyText: "Misskeyはsyuiloいう人が2014年からずっと作ってはる、オープンソースなソフトウェアや。"
|
|
||||||
misskeyMembers: "今んとここんだけのメンバーが作って、メンテナンスしてはる:"
|
|
||||||
misskeySource: "ソースコードはこっから見てな:"
|
|
||||||
misskeyTranslation: "Misskeyの翻訳手伝うてくれへん?:"
|
|
||||||
misskeyDonate: "Misskeyにお金あげたら開発のサポートになるで:"
|
|
||||||
morePatrons: "他にもぎょうさんの人からサポートしてもろてんねん。ほんまおおきに🥰"
|
|
||||||
patrons: "支援者"
|
|
||||||
administrator: "管理者"
|
administrator: "管理者"
|
||||||
token: "トークン"
|
token: "トークン"
|
||||||
twoStepAuthentication: "二段階認証"
|
twoStepAuthentication: "二段階認証"
|
||||||
|
@ -16,6 +16,9 @@ noNotes: "노트가 없습니다"
|
|||||||
noNotifications: "표시할 알림이 없습니다"
|
noNotifications: "표시할 알림이 없습니다"
|
||||||
instance: "인스턴스"
|
instance: "인스턴스"
|
||||||
settings: "설정"
|
settings: "설정"
|
||||||
|
basicSettings: "기본 설정"
|
||||||
|
otherSettings: "기타 설정"
|
||||||
|
openInWindow: "창으로 열기"
|
||||||
profile: "프로필"
|
profile: "프로필"
|
||||||
timeline: "타임라인"
|
timeline: "타임라인"
|
||||||
noAccountDescription: "자기소개가 없습니다"
|
noAccountDescription: "자기소개가 없습니다"
|
||||||
@ -40,6 +43,7 @@ deleteAndEditConfirm: "이 노트를 삭제한 뒤 다시 편집하시겠습니
|
|||||||
addToList: "리스트에 추가"
|
addToList: "리스트에 추가"
|
||||||
sendMessage: "메시지 보내기"
|
sendMessage: "메시지 보내기"
|
||||||
copyUsername: "유저명 복사"
|
copyUsername: "유저명 복사"
|
||||||
|
searchUser: "사용자 검색"
|
||||||
reply: "답글"
|
reply: "답글"
|
||||||
loadMore: "더 보기"
|
loadMore: "더 보기"
|
||||||
youGotNewFollower: "새로운 팔로워가 있습니다"
|
youGotNewFollower: "새로운 팔로워가 있습니다"
|
||||||
@ -66,7 +70,11 @@ followers: "팔로워"
|
|||||||
followsYou: "당신을 팔로우합니다"
|
followsYou: "당신을 팔로우합니다"
|
||||||
createList: "리스트 만들기"
|
createList: "리스트 만들기"
|
||||||
manageLists: "리스트 관리"
|
manageLists: "리스트 관리"
|
||||||
|
error: "오류"
|
||||||
|
somethingHappened: "오류가 발생했습니다"
|
||||||
retry: "다시 시도"
|
retry: "다시 시도"
|
||||||
|
pageLoadError: "페이지를 불러오지 못했습니다."
|
||||||
|
pageLoadErrorDescription: "네트워크 연결 또는 브라우저 캐시로 인해 발생했을 가능성이 높습니다. 캐시를 삭제하거나, 잠시 후 다시 시도해 주세요."
|
||||||
enterListName: "리스트 이름을 입력"
|
enterListName: "리스트 이름을 입력"
|
||||||
privacy: "프라이버시"
|
privacy: "프라이버시"
|
||||||
makeFollowManuallyApprove: "팔로우를 수동으로 승인"
|
makeFollowManuallyApprove: "팔로우를 수동으로 승인"
|
||||||
@ -87,6 +95,7 @@ sensitive: "열람주의"
|
|||||||
add: "추가"
|
add: "추가"
|
||||||
reaction: "리액션"
|
reaction: "리액션"
|
||||||
reactionSettingDescription: "리액션 선택 상자에 표시할 리액션을 설정합니다."
|
reactionSettingDescription: "리액션 선택 상자에 표시할 리액션을 설정합니다."
|
||||||
|
reactionSettingDescription2: "드래그하여 순서를 바꿉니다. 클릭하면 삭제됩니다."
|
||||||
rememberNoteVisibility: "공개 범위를 기억하기"
|
rememberNoteVisibility: "공개 범위를 기억하기"
|
||||||
attachCancel: "첨부 취소"
|
attachCancel: "첨부 취소"
|
||||||
markAsSensitive: "열람주의로 설정"
|
markAsSensitive: "열람주의로 설정"
|
||||||
@ -105,6 +114,8 @@ unsuspendConfirm: "이 계정의 정지를 해제하시겠습니까?"
|
|||||||
selectList: "리스트 선택"
|
selectList: "리스트 선택"
|
||||||
selectAntenna: "안테나 선택"
|
selectAntenna: "안테나 선택"
|
||||||
selectWidget: "위젯 선택"
|
selectWidget: "위젯 선택"
|
||||||
|
editWidgets: "위젯 편집"
|
||||||
|
editWidgetsExit: "편집 종료"
|
||||||
customEmojis: "커스텀 이모지"
|
customEmojis: "커스텀 이모지"
|
||||||
emoji: "이모지"
|
emoji: "이모지"
|
||||||
emojiName: "이모지 이름"
|
emojiName: "이모지 이름"
|
||||||
@ -114,6 +125,7 @@ settingGuide: "추천 설정"
|
|||||||
cacheRemoteFiles: "리모트 파일을 캐시"
|
cacheRemoteFiles: "리모트 파일을 캐시"
|
||||||
cacheRemoteFilesDescription: "이 설정을 해지하면 리모트 파일을 캐시하지 않고 해당 파일을 직접 링크하게 됩니다. 그에 따라 서버의 저장 공간을 절약할 수 있지만, 썸네일이 생성되지 않기 때문에 통신량이 증가합니다."
|
cacheRemoteFilesDescription: "이 설정을 해지하면 리모트 파일을 캐시하지 않고 해당 파일을 직접 링크하게 됩니다. 그에 따라 서버의 저장 공간을 절약할 수 있지만, 썸네일이 생성되지 않기 때문에 통신량이 증가합니다."
|
||||||
flagAsBot: "나는 봇입니다"
|
flagAsBot: "나는 봇입니다"
|
||||||
|
flagAsBotDescription: "이 계정을 자동화된 수단으로 운용할 경우에 활성화해 주세요. 이 플래그를 활성화하면, 다른 봇이 이를 참고하여 봇 끼리의 무한 연쇄 반응을 회피하거나, 이 계정의 시스템 상에서의 취급이 Bot 운영에 최적화되는 등의 변화가 생깁니다."
|
||||||
flagAsCat: "나는 고양이다냥"
|
flagAsCat: "나는 고양이다냥"
|
||||||
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
|
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
|
||||||
addAcount: "계정 추가"
|
addAcount: "계정 추가"
|
||||||
@ -205,6 +217,7 @@ remove: "삭제"
|
|||||||
removed: "삭제하였습니다"
|
removed: "삭제하였습니다"
|
||||||
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
||||||
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
||||||
|
resetAreYouSure: "초기화 하시겠습니까?"
|
||||||
saved: "저장하였습니다"
|
saved: "저장하였습니다"
|
||||||
messaging: "대화"
|
messaging: "대화"
|
||||||
upload: "업로드"
|
upload: "업로드"
|
||||||
@ -263,6 +276,7 @@ rename: "이름 변경"
|
|||||||
avatar: "아바타"
|
avatar: "아바타"
|
||||||
banner: "배너"
|
banner: "배너"
|
||||||
nsfw: "열람주의"
|
nsfw: "열람주의"
|
||||||
|
whenServerDisconnected: "서버와의 접속이 끊겼을 때"
|
||||||
disconnectedFromServer: "서버와의 연결이 끊어졌습니다"
|
disconnectedFromServer: "서버와의 연결이 끊어졌습니다"
|
||||||
reload: "새로고침"
|
reload: "새로고침"
|
||||||
doNothing: "무시하기"
|
doNothing: "무시하기"
|
||||||
@ -303,6 +317,8 @@ bannerUrl: "배너 이미지 URL"
|
|||||||
basicInfo: "기본 정보"
|
basicInfo: "기본 정보"
|
||||||
pinnedUsers: "고정된 유저"
|
pinnedUsers: "고정된 유저"
|
||||||
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
|
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
|
||||||
|
pinnedPages: "고정한 페이지"
|
||||||
|
pinnedPagesDescription: "인스턴스의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다."
|
||||||
hcaptcha: "hCaptcha"
|
hcaptcha: "hCaptcha"
|
||||||
enableHcaptcha: "hCaptcha 활성화"
|
enableHcaptcha: "hCaptcha 활성화"
|
||||||
hcaptchaSiteKey: "사이트 키"
|
hcaptchaSiteKey: "사이트 키"
|
||||||
@ -343,13 +359,6 @@ popularTags: "인기 태그"
|
|||||||
userList: "리스트"
|
userList: "리스트"
|
||||||
about: "정보"
|
about: "정보"
|
||||||
aboutMisskey: "Misskey에 대하여"
|
aboutMisskey: "Misskey에 대하여"
|
||||||
aboutMisskeyText: "Misskey는 syuilo에 의해서 2014년부터 개발되어 온 오픈소스 소프트웨어 입니다."
|
|
||||||
misskeyMembers: "현재는 아래 멤버들에 의해 개발 및 유지보수 되고 있습니다:"
|
|
||||||
misskeySource: "소스코드는 여기에 공개되어 있습니다:"
|
|
||||||
misskeyTranslation: "Misskey의 번역을 함께해 주시길 부탁드립니다:"
|
|
||||||
misskeyDonate: "Misskey에 기부하심으로써 개발에 도움을 주실 수 있습니다:"
|
|
||||||
morePatrons: "이 외에도 다른 많은 분들이 도움을 주시고 계십니다. 감사합니다🥰"
|
|
||||||
patrons: "후원자들"
|
|
||||||
administrator: "관리자"
|
administrator: "관리자"
|
||||||
token: "토큰"
|
token: "토큰"
|
||||||
twoStepAuthentication: "2단계 인증"
|
twoStepAuthentication: "2단계 인증"
|
||||||
@ -441,6 +450,7 @@ remote: "리모트"
|
|||||||
total: "합계"
|
total: "합계"
|
||||||
weekOverWeekChanges: "지난주보다"
|
weekOverWeekChanges: "지난주보다"
|
||||||
dayOverDayChanges: "어제보다"
|
dayOverDayChanges: "어제보다"
|
||||||
|
clientSettings: "클라이언트 설정"
|
||||||
accountSettings: "계정 설정"
|
accountSettings: "계정 설정"
|
||||||
promotion: "프로모션"
|
promotion: "프로모션"
|
||||||
promote: "프로모션하기"
|
promote: "프로모션하기"
|
||||||
@ -463,6 +473,7 @@ objectStorageUseSSL: "SSL 사용"
|
|||||||
objectStorageUseSSLDesc: "API 호출시 HTTPS 를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
objectStorageUseSSLDesc: "API 호출시 HTTPS 를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
||||||
objectStorageUseProxy: "연결에 프록시를 사용"
|
objectStorageUseProxy: "연결에 프록시를 사용"
|
||||||
objectStorageUseProxyDesc: "오브젝트 스토리지 API 호출시 프록시를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
objectStorageUseProxyDesc: "오브젝트 스토리지 API 호출시 프록시를 사용하지 않는 경우 OFF 로 설정해 주세요"
|
||||||
|
objectStorageSetPublicRead: "업로드할 때 'public-read'를 설정하기"
|
||||||
serverLogs: "서버 로그"
|
serverLogs: "서버 로그"
|
||||||
deleteAll: "모두 삭제"
|
deleteAll: "모두 삭제"
|
||||||
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
|
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
|
||||||
@ -470,6 +481,8 @@ newNoteRecived: "새 노트가 있습니다"
|
|||||||
sounds: "소리"
|
sounds: "소리"
|
||||||
listen: "듣기"
|
listen: "듣기"
|
||||||
none: "없음"
|
none: "없음"
|
||||||
|
showInPage: "페이지로 보기"
|
||||||
|
popout: "새 창으로 열기"
|
||||||
volume: "음량"
|
volume: "음량"
|
||||||
details: "자세히"
|
details: "자세히"
|
||||||
chooseEmoji: "이모지 선택"
|
chooseEmoji: "이모지 선택"
|
||||||
@ -526,16 +539,20 @@ deck: "덱"
|
|||||||
undeck: "덱 해제"
|
undeck: "덱 해제"
|
||||||
width: "폭"
|
width: "폭"
|
||||||
height: "높이"
|
height: "높이"
|
||||||
|
large: "크게"
|
||||||
|
medium: "보통"
|
||||||
|
small: "작게"
|
||||||
generateAccessToken: "액세스 토큰 생성"
|
generateAccessToken: "액세스 토큰 생성"
|
||||||
permission: "권한"
|
permission: "권한"
|
||||||
enableAll: "전체 선택"
|
enableAll: "전체 선택"
|
||||||
disableAll: "전체 해제"
|
disableAll: "전체 해제"
|
||||||
tokenRequested: "계정 접근 허용"
|
tokenRequested: "계정 접근 허용"
|
||||||
|
pluginTokenRequestedDescription: "이 플러그인은 여기서 설정한 권한을 사용할 수 있게 됩니다."
|
||||||
|
notificationType: "알림 유형"
|
||||||
edit: "편집"
|
edit: "편집"
|
||||||
useStarForReactionFallback: "알 수 없는 리액션 이모지 대신 ★ 사용"
|
useStarForReactionFallback: "알 수 없는 리액션 이모지 대신 ★ 사용"
|
||||||
emailConfig: "메일 서버 설정"
|
emailConfig: "메일 서버 설정"
|
||||||
emailConfigInfo: "가입 시 메일 주소 확인이나 비밀번호 초기화 시에 사용합니다."
|
emailConfigInfo: "가입 시 메일 주소 확인이나 비밀번호 초기화 시에 사용합니다."
|
||||||
email: "메일 주소"
|
|
||||||
smtpConfig: "SMTP 서버 설정"
|
smtpConfig: "SMTP 서버 설정"
|
||||||
smtpHost: "호스트"
|
smtpHost: "호스트"
|
||||||
smtpPort: "포트"
|
smtpPort: "포트"
|
||||||
@ -544,24 +561,93 @@ smtpPass: "비밀번호"
|
|||||||
emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다."
|
emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다."
|
||||||
smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용"
|
smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용"
|
||||||
smtpSecureInfo: "STARTTLS 사용 시에는 해제합니다."
|
smtpSecureInfo: "STARTTLS 사용 시에는 해제합니다."
|
||||||
|
testEmail: "이메일 전송 테스트"
|
||||||
wordMute: "단어 뮤트"
|
wordMute: "단어 뮤트"
|
||||||
makeActive: "활성화"
|
makeActive: "활성화"
|
||||||
|
display: "표시"
|
||||||
copy: "복사"
|
copy: "복사"
|
||||||
|
overview: "요약"
|
||||||
logs: "로그"
|
logs: "로그"
|
||||||
|
delayed: "지연"
|
||||||
database: "데이터베이스"
|
database: "데이터베이스"
|
||||||
channel: "채널"
|
channel: "채널"
|
||||||
|
create: "생성"
|
||||||
|
notificationSetting: "알림 설정"
|
||||||
|
notificationSettingDesc: "표시할 알림의 종류를 선택해 주세요."
|
||||||
|
useGlobalSettingDesc: "활성화하면 계정의 알림 설정이 적용되니다. 비활성화하면 개별적으로 설정할 수 있게 됩니다."
|
||||||
|
other: "기타"
|
||||||
|
regenerateLoginToken: "로그인 토큰을 재생성"
|
||||||
|
regenerateLoginTokenDescription: "로그인할 때 사용되는 내부 토큰을 재생성합니다. 일반적으로 이 작업을 실행할 필요는 없습니다. 이 기능을 사용하면 이 계정으로 로그인한 모든 기기에서 로그아웃됩니다."
|
||||||
|
setMultipleBySeparatingWithSpace: "공백으로 구분하여 여러 개 설정할 수 있습니다."
|
||||||
|
fileIdOrUrl: "파일 ID 또는 URL"
|
||||||
|
chatOpenBehavior: "대화를 열 때의 동작"
|
||||||
|
sample: "예시"
|
||||||
|
abuseReports: "신고"
|
||||||
|
reportAbuse: "신고"
|
||||||
|
reportAbuseOf: "{name}을 신고하기"
|
||||||
|
fillAbuseReportDescription: "신고하려는 이유를 자세히 알려주세요. 특정 게시물을 신고할 때에는 게시물의 URL도 포함해 주세요."
|
||||||
|
abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다."
|
||||||
|
send: "전송"
|
||||||
random: "랜덤"
|
random: "랜덤"
|
||||||
|
switchUi: "UI 전환"
|
||||||
|
desktop: "데스크탑"
|
||||||
|
clip: "클립"
|
||||||
|
createNew: "새로 만들기"
|
||||||
|
optional: "옵션"
|
||||||
|
createNewClip: "새 클립 만들기"
|
||||||
public: "공개"
|
public: "공개"
|
||||||
_mfm:
|
_mfm:
|
||||||
|
cheatSheet: "MFM 도움말"
|
||||||
|
intro: "MFM는 Misskey의 다양한 곳에서 사용할 수 있는 전용 마크업 언어입니다. 여기에서는 MFM에서 사용할 수 있는 구문을 확인할 수 있습니다."
|
||||||
mention: "멘션"
|
mention: "멘션"
|
||||||
|
mentionDescription: "골뱅이표(@) 뒤에 사용자명을 넣어 특정 유저를 나타낼 수 있습니다."
|
||||||
hashtag: "해시태그"
|
hashtag: "해시태그"
|
||||||
|
hashtagDescription: "샵 또는 우물정자(#)를 앞에 붙여서 해시태그를 나타낼 수 있습니다."
|
||||||
|
url: "URL"
|
||||||
|
urlDescription: "URL을 나타낼 수 있습니다."
|
||||||
link: "링크"
|
link: "링크"
|
||||||
|
boldDescription: "문자를 굵게 강조합니다."
|
||||||
|
smallDescription: "내용을 작고 연하게 보이게 합니다."
|
||||||
center: "가운데 정렬"
|
center: "가운데 정렬"
|
||||||
|
centerDescription: "내용을 가운데 정렬로 보이게 합니다."
|
||||||
|
inlineMathDescription: "수식(KaTeX)를 인라인으로 보이게 합니다."
|
||||||
|
blockMathDescription: "여러 줄의 수식(KaTeX)를 블록으로 보이게 합니다."
|
||||||
quote: "인용"
|
quote: "인용"
|
||||||
emoji: "커스텀 이모지"
|
emoji: "커스텀 이모지"
|
||||||
|
emojiDescription: "커스텀 이모지의 이름을 쌍점(:)으로 감싸서 커스텀 이모지를 사용합니다."
|
||||||
search: "검색"
|
search: "검색"
|
||||||
|
searchDescription: "주어진 키워드가 입력된 검색창을 보이게 합니다."
|
||||||
_reversi:
|
_reversi:
|
||||||
|
reversi: "리버시"
|
||||||
|
gameSettings: "대국 설정"
|
||||||
|
chooseBoard: "보드 선택"
|
||||||
|
blackOrWhite: "선공/후공"
|
||||||
|
blackIs: "{name}님이 흑(선공)"
|
||||||
|
rules: "규칙"
|
||||||
|
botSettings: "Bot 설정"
|
||||||
|
thisGameIsStartedSoon: "잠시 후에 대국이 시작됩니다"
|
||||||
|
waitingForOther: "상대의 준비가 완료될 때까지 기다리고 있습니다"
|
||||||
|
waitingForMe: "당신의 준비 완료를 기다리고 있습니다"
|
||||||
|
myTurn: "당신의 차례입니다"
|
||||||
|
turnOf: "{name}님의 차례입니다"
|
||||||
|
pastTurnOf: "{name}님의 차례"
|
||||||
|
surrender: "기권"
|
||||||
|
surrendered: "기권에 의해"
|
||||||
|
drawn: "무승부"
|
||||||
|
won: "{name}님의 승리"
|
||||||
total: "합계"
|
total: "합계"
|
||||||
|
turnCount: "{count}턴 째"
|
||||||
|
myGames: "내 대국"
|
||||||
|
allGames: "모두의 대국"
|
||||||
|
ended: "종료"
|
||||||
|
playing: "지금 대국 중"
|
||||||
|
isLlotheo: "돌이 적은 사람이 승리 (llotheo)"
|
||||||
|
loopedMap: "루프 지도"
|
||||||
|
canPutEverywhere: "어디에나 놓을 수 있음"
|
||||||
|
_instanceTicker:
|
||||||
|
none: "보이지 않음"
|
||||||
|
remote: "리모트 유저에게만 보이기"
|
||||||
|
always: "항상 보이기"
|
||||||
_channel:
|
_channel:
|
||||||
create: "채널 생성"
|
create: "채널 생성"
|
||||||
setBanner: "배너 설정"
|
setBanner: "배너 설정"
|
||||||
@ -571,10 +657,11 @@ _channel:
|
|||||||
usersCount: "{n}명 참여 중"
|
usersCount: "{n}명 참여 중"
|
||||||
notesCount: "{n}노트"
|
notesCount: "{n}노트"
|
||||||
_sidebar:
|
_sidebar:
|
||||||
icon: "아바타"
|
icon: "아이콘"
|
||||||
hide: "숨기기"
|
hide: "숨기기"
|
||||||
_wordMute:
|
_wordMute:
|
||||||
muteWords: "뮤트할 단어"
|
muteWords: "뮤트할 단어"
|
||||||
|
muteWordsDescription: "공백으로 구분하는 경우 AND, 줄바꿈으로 구분하는 경우 OR로 지정됩니다。"
|
||||||
mutedNotes: "뮤트된 노트"
|
mutedNotes: "뮤트된 노트"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "테마 찾아보기"
|
explore: "테마 찾아보기"
|
||||||
@ -772,7 +859,6 @@ _profile:
|
|||||||
username: "유저명"
|
username: "유저명"
|
||||||
description: "자기소개"
|
description: "자기소개"
|
||||||
youCanIncludeHashtags: "해시 태그를 포함할 수 있습니다."
|
youCanIncludeHashtags: "해시 태그를 포함할 수 있습니다."
|
||||||
metadata: "추가 정보"
|
|
||||||
metadataLabel: "라벨"
|
metadataLabel: "라벨"
|
||||||
metadataContent: "내용"
|
metadataContent: "내용"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
@ -946,6 +1032,8 @@ _pages:
|
|||||||
id: "캔버스 ID"
|
id: "캔버스 ID"
|
||||||
width: "폭"
|
width: "폭"
|
||||||
height: "높이"
|
height: "높이"
|
||||||
|
_note:
|
||||||
|
detailed: "세부 정보 보기"
|
||||||
switch: "스위치"
|
switch: "스위치"
|
||||||
_switch:
|
_switch:
|
||||||
name: "변수명"
|
name: "변수명"
|
||||||
|
@ -125,7 +125,9 @@ settingGuide: "Рекомендуемые настройки"
|
|||||||
cacheRemoteFiles: "Кешировать внешние файлы"
|
cacheRemoteFiles: "Кешировать внешние файлы"
|
||||||
cacheRemoteFilesDescription: "Когда эта настройка отключена, файлы с других сайтов будут загружаться прямо оттуда. Это сэкономит место на сервере, но увеличит трафик, так как не будут создаваться эскизы."
|
cacheRemoteFilesDescription: "Когда эта настройка отключена, файлы с других сайтов будут загружаться прямо оттуда. Это сэкономит место на сервере, но увеличит трафик, так как не будут создаваться эскизы."
|
||||||
flagAsBot: "Аккаунт бота"
|
flagAsBot: "Аккаунт бота"
|
||||||
|
flagAsBotDescription: "Включите, если этот аккаунт управляется программой. Это позволит системе Misskey учитывать это, а также поможет разработчикам других ботов предотвратить бесконечные циклы взаимодействия."
|
||||||
flagAsCat: "Аккаунт кота"
|
flagAsCat: "Аккаунт кота"
|
||||||
|
flagAsCatDescription: "Включите, и этот аккаунт будет помечен как кошачий."
|
||||||
autoAcceptFollowed: "Принимать подписчиков автоматически"
|
autoAcceptFollowed: "Принимать подписчиков автоматически"
|
||||||
addAcount: "Добавить аккаунт"
|
addAcount: "Добавить аккаунт"
|
||||||
loginFailed: "Неудачная попытка входа"
|
loginFailed: "Неудачная попытка входа"
|
||||||
@ -206,7 +208,7 @@ newPassword: "Новый пароль"
|
|||||||
newPasswordRetype: "Новый пароль (ещё раз)"
|
newPasswordRetype: "Новый пароль (ещё раз)"
|
||||||
attachFile: "Прикрепить файлы"
|
attachFile: "Прикрепить файлы"
|
||||||
more: "Ещё!"
|
more: "Ещё!"
|
||||||
featured: "Подборка"
|
featured: "Горячее"
|
||||||
usernameOrUserId: "Имя или идентификатор пользователя"
|
usernameOrUserId: "Имя или идентификатор пользователя"
|
||||||
noSuchUser: "Таких пользователей не найдено"
|
noSuchUser: "Таких пользователей не найдено"
|
||||||
lookup: "Запрос"
|
lookup: "Запрос"
|
||||||
@ -358,13 +360,6 @@ popularTags: "Популярные теги"
|
|||||||
userList: "Списки"
|
userList: "Списки"
|
||||||
about: "Описание"
|
about: "Описание"
|
||||||
aboutMisskey: "О Misskey"
|
aboutMisskey: "О Misskey"
|
||||||
aboutMisskeyText: "Misskey - это программное обеспечение с открытым исходным кодом, разрабатываемое syuilo с 2014 года."
|
|
||||||
misskeyMembers: "В настоящее время он разрабатывается и поддерживается следующими участниками:"
|
|
||||||
misskeySource: "Исходный код доступен здесь:"
|
|
||||||
misskeyTranslation: "Помогите нам перевести Misskey:"
|
|
||||||
misskeyDonate: "Вы можете поддержать развитие, пожертвовав Misskey:"
|
|
||||||
morePatrons: "Есть много других, кто поддержал нас. Спасибо 🥰."
|
|
||||||
patrons: "Поддержавшие"
|
|
||||||
administrator: "Администратор"
|
administrator: "Администратор"
|
||||||
token: "Токен"
|
token: "Токен"
|
||||||
twoStepAuthentication: "Двухфакторная аутентификация"
|
twoStepAuthentication: "Двухфакторная аутентификация"
|
||||||
@ -439,6 +434,7 @@ useOsNativeEmojis: "Использовать эмодзи операционно
|
|||||||
youHaveNoGroups: "У вас нет ни одной группы"
|
youHaveNoGroups: "У вас нет ни одной группы"
|
||||||
joinOrCreateGroup: "Получайте приглашения в группы или создавайте свои собственные"
|
joinOrCreateGroup: "Получайте приглашения в группы или создавайте свои собственные"
|
||||||
noHistory: "История пока пуста"
|
noHistory: "История пока пуста"
|
||||||
|
signinHistory: "Журнал посещений"
|
||||||
disableAnimatedMfm: "Отключение анимированной разметки MFM"
|
disableAnimatedMfm: "Отключение анимированной разметки MFM"
|
||||||
doing: "В процессе"
|
doing: "В процессе"
|
||||||
category: "Категория"
|
category: "Категория"
|
||||||
@ -491,6 +487,7 @@ none: "Ничего"
|
|||||||
showInPage: "Показать страницу"
|
showInPage: "Показать страницу"
|
||||||
popout: "Развернуть"
|
popout: "Развернуть"
|
||||||
volume: "Громкость"
|
volume: "Громкость"
|
||||||
|
masterVolume: "Основная регулировка громкости"
|
||||||
details: "Подробнее"
|
details: "Подробнее"
|
||||||
chooseEmoji: "Выберите эмодзи"
|
chooseEmoji: "Выберите эмодзи"
|
||||||
unableToProcess: "Не удаётся завершить операцию"
|
unableToProcess: "Не удаётся завершить операцию"
|
||||||
@ -548,6 +545,9 @@ useBlurEffectForModal: "Размывка под формой поверх все
|
|||||||
useFullReactionPicker: "Полнофункциональный выбор реакций"
|
useFullReactionPicker: "Полнофункциональный выбор реакций"
|
||||||
width: "Ширина"
|
width: "Ширина"
|
||||||
height: "Высота"
|
height: "Высота"
|
||||||
|
large: "Крупно"
|
||||||
|
medium: "Средне"
|
||||||
|
small: "Мелко"
|
||||||
generateAccessToken: "Создать токен доступа"
|
generateAccessToken: "Создать токен доступа"
|
||||||
permission: "Разрешения"
|
permission: "Разрешения"
|
||||||
enableAll: "Включить все"
|
enableAll: "Включить все"
|
||||||
@ -560,7 +560,8 @@ useStarForReactionFallback: "Ставить ★ в качестве реакци
|
|||||||
emailConfig: "Настройки почтового сервера"
|
emailConfig: "Настройки почтового сервера"
|
||||||
enableEmail: "Включить обмен электронной почтой"
|
enableEmail: "Включить обмен электронной почтой"
|
||||||
emailConfigInfo: "Используется для подтверждения адреса электронной почты и сброса пароля."
|
emailConfigInfo: "Используется для подтверждения адреса электронной почты и сброса пароля."
|
||||||
email: "Адрес электронной почты"
|
email: "Электронная почта"
|
||||||
|
emailAddress: "Адрес электронной почты"
|
||||||
smtpConfig: "Конфигурация SMTP-сервера"
|
smtpConfig: "Конфигурация SMTP-сервера"
|
||||||
smtpHost: "Хост"
|
smtpHost: "Хост"
|
||||||
smtpPort: "Порт"
|
smtpPort: "Порт"
|
||||||
@ -592,6 +593,7 @@ regenerateLoginTokenDescription: "Создаёт новый токен, испо
|
|||||||
setMultipleBySeparatingWithSpace: "Можно написать несколько через пробел"
|
setMultipleBySeparatingWithSpace: "Можно написать несколько через пробел"
|
||||||
fileIdOrUrl: "Идентификатор файла или ссылка"
|
fileIdOrUrl: "Идентификатор файла или ссылка"
|
||||||
chatOpenBehavior: "Поведение окна чата при открытии"
|
chatOpenBehavior: "Поведение окна чата при открытии"
|
||||||
|
behavior: "Поведение"
|
||||||
sample: "Пример"
|
sample: "Пример"
|
||||||
abuseReports: "Жалобы"
|
abuseReports: "Жалобы"
|
||||||
reportAbuse: "Жалоба"
|
reportAbuse: "Жалоба"
|
||||||
@ -615,6 +617,41 @@ createNew: "Новый документ"
|
|||||||
optional: "Необязательно"
|
optional: "Необязательно"
|
||||||
createNewClip: "Новая памятка"
|
createNewClip: "Новая памятка"
|
||||||
public: "Общедоступно"
|
public: "Общедоступно"
|
||||||
|
i18nInfo: "Misskey переводят на разные языки добровольцы со всего света. Ваша помощь тоже пригодится здесь: {link}."
|
||||||
|
manageAccessTokens: "Управление токенами доступа"
|
||||||
|
accountInfo: "Сведения об учётной записи"
|
||||||
|
notesCount: "Количество заметок"
|
||||||
|
repliesCount: "Сколько раз пользователь кому-то ответил"
|
||||||
|
renotesCount: "Сколько раз пользователь передал чужие заметки"
|
||||||
|
repliedCount: "Сколько раз ответили пользователю"
|
||||||
|
renotedCount: "Сколько раз передавали заметки пользователя"
|
||||||
|
followingCount: "Количество подписок"
|
||||||
|
followersCount: "Количество подписавшихся"
|
||||||
|
sentReactionsCount: "Сколько раз пользователь отреагировал"
|
||||||
|
receivedReactionsCount: "Сколько раз отреагировали на заметки пользователя"
|
||||||
|
pollVotesCount: "Сколько раз участвовал в опросах"
|
||||||
|
pollVotedCount: "Сколько раз участвовали в опросах пользователя"
|
||||||
|
yes: "Да"
|
||||||
|
no: "Нет"
|
||||||
|
driveFilesCount: "Количество файлов на диске"
|
||||||
|
driveUsage: "Сколько места занято на диске"
|
||||||
|
noCrawle: "Паукам вход воспрещён"
|
||||||
|
noCrawleDescription: "Просьба поисковым системам не ходить по вашему профилю, по заметкам, страницам и не индексировать их."
|
||||||
|
lockedAccountInfo: "Даже если вы вручную подтверждаете подписки, кто угодно может читать ваши заметки, если вы не отмечаете их «для подписчиков»."
|
||||||
|
alwaysMarkSensitive: "Отмечать файлы как «содержимое не для всех» по умолчанию"
|
||||||
|
loadRawImages: "Сразу показывать изображения в полном размере"
|
||||||
|
disableShowingAnimatedImages: "Не проигрывать анимацию"
|
||||||
|
verificationEmailSent: "Вам отправлено письмо для подтверждения. Пройдите, пожалуйста, по ссылке из письма, чтобы завершить проверку."
|
||||||
|
notSet: "Не настроено"
|
||||||
|
emailVerified: "Адрес электронной почты подтверждён."
|
||||||
|
noteFavoritesCount: "Количество добавленного в избранное"
|
||||||
|
pageLikesCount: "Количество понравившихся страниц"
|
||||||
|
pageLikedCount: "Количество страниц, понравившихся другим"
|
||||||
|
reversiCount: "Количество сыгранных игр в реверси"
|
||||||
|
_nsfw:
|
||||||
|
respect: "Скрывать содержимое не для всех"
|
||||||
|
ignore: "Показывать содержимое не для всех"
|
||||||
|
force: "Скрывать вообще все файлы"
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "Подсказка по разметке MFM"
|
cheatSheet: "Подсказка по разметке MFM"
|
||||||
intro: "MFM — язык оформления текста, придуманный специально для Misskey, который здесь можно много где использовать. На этой странице собраны и кратко изложены способы его применения."
|
intro: "MFM — язык оформления текста, придуманный специально для Misskey, который здесь можно много где использовать. На этой странице собраны и кратко изложены способы его применения."
|
||||||
@ -709,9 +746,9 @@ _channel:
|
|||||||
edit: "Редактировать канал"
|
edit: "Редактировать канал"
|
||||||
setBanner: "Установить баннер"
|
setBanner: "Установить баннер"
|
||||||
removeBanner: "Удалить баннер"
|
removeBanner: "Удалить баннер"
|
||||||
featured: "Из подборки"
|
featured: "Актуальные"
|
||||||
owned: "Владелец"
|
owned: "Собственные"
|
||||||
following: "Читаю"
|
following: "Подписки"
|
||||||
usersCount: "Участников: {n}"
|
usersCount: "Участников: {n}"
|
||||||
notesCount: "Заметок: {n}"
|
notesCount: "Заметок: {n}"
|
||||||
_sidebar:
|
_sidebar:
|
||||||
@ -733,6 +770,8 @@ _theme:
|
|||||||
manage: "Менеджер тем"
|
manage: "Менеджер тем"
|
||||||
code: "Код темы"
|
code: "Код темы"
|
||||||
installed: "Тема «{name}» установлена."
|
installed: "Тема «{name}» установлена."
|
||||||
|
installedThemes: "Установленные темы"
|
||||||
|
builtinThemes: "Встроенные темы"
|
||||||
alreadyInstalled: "Тема уже установлена."
|
alreadyInstalled: "Тема уже установлена."
|
||||||
invalid: "Формат темы некорректный."
|
invalid: "Формат темы некорректный."
|
||||||
make: "Создать тему"
|
make: "Создать тему"
|
||||||
@ -806,6 +845,8 @@ _sfx:
|
|||||||
chatBg: "Сообщения (фон)"
|
chatBg: "Сообщения (фон)"
|
||||||
antenna: "Антенна"
|
antenna: "Антенна"
|
||||||
channel: "Канал"
|
channel: "Канал"
|
||||||
|
reversiPutBlack: "Реверси — ход чёрных"
|
||||||
|
reversiPutWhite: "Реверси — ход белых"
|
||||||
_ago:
|
_ago:
|
||||||
unknown: "Когда-то"
|
unknown: "Когда-то"
|
||||||
future: "Из будущего"
|
future: "Из будущего"
|
||||||
@ -948,13 +989,13 @@ _visibility:
|
|||||||
public: "Общедоступно"
|
public: "Общедоступно"
|
||||||
publicDescription: "Открыто для всех"
|
publicDescription: "Открыто для всех"
|
||||||
home: "Домашняя"
|
home: "Домашняя"
|
||||||
homeDescription: "Не появится в общих лентах (локальной и глобальной)"
|
homeDescription: "Не для общих лент"
|
||||||
followers: "Для подписчиков"
|
followers: "Для подписчиков"
|
||||||
followersDescription: "Увидят только ваши подписчики"
|
followersDescription: "Только вашим подписчикам"
|
||||||
specified: "Личное"
|
specified: "Личное"
|
||||||
specifiedDescription: "Только для тех, кого укажете"
|
specifiedDescription: "Тем, кого укажете"
|
||||||
localOnly: "Локально"
|
localOnly: "Локально"
|
||||||
localOnlyDescription: "Увидят только пользователи этого сайта"
|
localOnlyDescription: "Только для этого сайта"
|
||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Ответ на заметку..."
|
replyPlaceholder: "Ответ на заметку..."
|
||||||
quotePlaceholder: "Пояснение к цитате..."
|
quotePlaceholder: "Пояснение к цитате..."
|
||||||
@ -971,7 +1012,9 @@ _profile:
|
|||||||
username: "Имя пользователя"
|
username: "Имя пользователя"
|
||||||
description: "О себе"
|
description: "О себе"
|
||||||
youCanIncludeHashtags: "Можете использовать здесь хэштеги"
|
youCanIncludeHashtags: "Можете использовать здесь хэштеги"
|
||||||
metadata: "Всякое"
|
metadata: "Дополнительные сведения"
|
||||||
|
metadataEdit: "Редактировать дополнительные сведения"
|
||||||
|
metadataDescription: "Можно добавить до четырёх дополнительных граф в профиль."
|
||||||
metadataLabel: "Метка"
|
metadataLabel: "Метка"
|
||||||
metadataContent: "Содержимое"
|
metadataContent: "Содержимое"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
_lang_: "Українська"
|
_lang_: "Українська"
|
||||||
|
introMisskey: "Ласкаво просимо! Misskey - децентралізована служба мікроблогів з відкритим кодом.\nСтворюйте \"нотатки\", щоб поділитися тим, що відбувається, і розповісти всім про себе 📡\nЗа допомогою \"реакцій\" ви також можете швидко висловити свої почуття щодо нотаток інших 👍\nДавайте досліджувати новий світ 🚀"
|
||||||
monthAndDay: "{month}/{day}"
|
monthAndDay: "{month}/{day}"
|
||||||
search: "Пошук"
|
search: "Пошук"
|
||||||
notifications: "Сповіщення"
|
notifications: "Сповіщення"
|
||||||
@ -11,7 +12,7 @@ gotIt: "Зрозуміло!"
|
|||||||
cancel: "Скасувати"
|
cancel: "Скасувати"
|
||||||
enterUsername: "Введіть ім'я користувача"
|
enterUsername: "Введіть ім'я користувача"
|
||||||
renotedBy: "Поширено {user}"
|
renotedBy: "Поширено {user}"
|
||||||
noNotes: "Немає дописів"
|
noNotes: "Немає нотаток"
|
||||||
noNotifications: "Немає сповіщень"
|
noNotifications: "Немає сповіщень"
|
||||||
instance: "Інстанс"
|
instance: "Інстанс"
|
||||||
settings: "Налаштування"
|
settings: "Налаштування"
|
||||||
@ -38,15 +39,16 @@ copyContent: "Скопіювати контент"
|
|||||||
copyLink: "Скопіювати посилання"
|
copyLink: "Скопіювати посилання"
|
||||||
delete: "Видалити"
|
delete: "Видалити"
|
||||||
deleteAndEdit: "Видалити й редагувати"
|
deleteAndEdit: "Видалити й редагувати"
|
||||||
|
deleteAndEditConfirm: "Ви впевнені, що хочете видалити цю нотатку та відредагувати її? Ви втратите всі реакції, поширення та відповіді на неї."
|
||||||
addToList: "Додати до списку"
|
addToList: "Додати до списку"
|
||||||
sendMessage: "Надіслати повідомлення"
|
sendMessage: "Надіслати повідомлення"
|
||||||
copyUsername: "Скопіювати ім’я користувача"
|
copyUsername: "Скопіювати ім’я користувача"
|
||||||
searchUser: "Пошук користувачів"
|
searchUser: "Пошук користувачів"
|
||||||
reply: "Відповісти"
|
reply: "Відповісти"
|
||||||
loadMore: "Показати більше"
|
loadMore: "Показати більше"
|
||||||
youGotNewFollower: "У вас новий підписник"
|
youGotNewFollower: "Новий підписник"
|
||||||
receiveFollowRequest: "Отримано запит на підписку"
|
receiveFollowRequest: "Отримано запит на підписку"
|
||||||
followRequestAccepted: "Запит на підписку прийнято"
|
followRequestAccepted: "Підписка прийнята"
|
||||||
mention: "Згадка"
|
mention: "Згадка"
|
||||||
mentions: "Згадки"
|
mentions: "Згадки"
|
||||||
directNotes: "Прямі повідомлення"
|
directNotes: "Прямі повідомлення"
|
||||||
@ -55,11 +57,14 @@ import: "Імпорт"
|
|||||||
export: "Експорт"
|
export: "Експорт"
|
||||||
files: "Файли"
|
files: "Файли"
|
||||||
download: "Завантажити"
|
download: "Завантажити"
|
||||||
|
driveFileDeleteConfirm: "Ви впевнені, що хочете видалити файл {name}? Нотатки із цим файлом також буде видалено."
|
||||||
unfollowConfirm: "Ви впевнені, що хочете відписатися від {name}?"
|
unfollowConfirm: "Ви впевнені, що хочете відписатися від {name}?"
|
||||||
|
exportRequested: "Ви запросили експорт. Це може зайняти деякий час. Після завершення експорту отриманий файл буде додано на диск."
|
||||||
|
importRequested: "Ви запросили імпорт. Це може зайняти деякий час."
|
||||||
lists: "Списки"
|
lists: "Списки"
|
||||||
noLists: "Немає списків"
|
noLists: "Немає списків"
|
||||||
note: "Дописи"
|
note: "Нотатки"
|
||||||
notes: "Дописи"
|
notes: "Нотатки"
|
||||||
following: "Підписки"
|
following: "Підписки"
|
||||||
followers: "Підписники"
|
followers: "Підписники"
|
||||||
followsYou: "Підписаний(-а) на вас"
|
followsYou: "Підписаний(-а) на вас"
|
||||||
@ -69,10 +74,11 @@ error: "Помилка"
|
|||||||
somethingHappened: "Щось пішло не так"
|
somethingHappened: "Щось пішло не так"
|
||||||
retry: "Спробувати знову"
|
retry: "Спробувати знову"
|
||||||
pageLoadError: "Помилка при завантаженні сторінки"
|
pageLoadError: "Помилка при завантаженні сторінки"
|
||||||
|
pageLoadErrorDescription: "Зазвичай це пов’язано з помилками мережі або кешем браузера. Очистіть кеш або почекайте трохи й спробуйте ще раз."
|
||||||
enterListName: "Введіть назву списку"
|
enterListName: "Введіть назву списку"
|
||||||
privacy: "Приватність"
|
privacy: "Приватність"
|
||||||
makeFollowManuallyApprove: "Підтверджувати підписників уручну"
|
makeFollowManuallyApprove: "Підтверджувати підписників уручну"
|
||||||
defaultNoteVisibility: "Видимість допису за замовчуванням"
|
defaultNoteVisibility: "Видимість за замовчуванням"
|
||||||
follow: "Підписка"
|
follow: "Підписка"
|
||||||
followRequest: "Запит на підписку"
|
followRequest: "Запит на підписку"
|
||||||
followRequests: "Запити на підписку"
|
followRequests: "Запити на підписку"
|
||||||
@ -82,13 +88,15 @@ enterEmoji: "Введіть емодзі"
|
|||||||
renote: "Поширити"
|
renote: "Поширити"
|
||||||
unrenote: "Відміна поширення"
|
unrenote: "Відміна поширення"
|
||||||
quote: "Цитата"
|
quote: "Цитата"
|
||||||
pinnedNote: "Закріплений допис"
|
pinnedNote: "Закріплена нотатка"
|
||||||
you: "Ви"
|
you: "Ви"
|
||||||
clickToShow: "Натисніть для перегляду"
|
clickToShow: "Натисніть для перегляду"
|
||||||
sensitive: "NSFW"
|
sensitive: "NSFW"
|
||||||
add: "Додати"
|
add: "Додати"
|
||||||
reaction: "Реакції"
|
reaction: "Реакції"
|
||||||
rememberNoteVisibility: "Пам’ятати видимість дописів"
|
reactionSettingDescription: "Виберіть свої улюблені реакції, які хочете закріпити в селекторі реакцій."
|
||||||
|
reactionSettingDescription2: "Перетягніть для реорганізації, натисніть для видалення."
|
||||||
|
rememberNoteVisibility: "Пам’ятати параметри видимісті"
|
||||||
attachCancel: "Видалити вкладення"
|
attachCancel: "Видалити вкладення"
|
||||||
markAsSensitive: "Позначити як NSFW"
|
markAsSensitive: "Позначити як NSFW"
|
||||||
unmarkAsSensitive: "Зняти позначку NSFW"
|
unmarkAsSensitive: "Зняти позначку NSFW"
|
||||||
@ -115,6 +123,7 @@ emojiUrl: "URL емодзі"
|
|||||||
addEmoji: "Додати емодзі"
|
addEmoji: "Додати емодзі"
|
||||||
settingGuide: "Рекомендована конфігурація"
|
settingGuide: "Рекомендована конфігурація"
|
||||||
cacheRemoteFiles: "Кешувати дані з інших інстансів"
|
cacheRemoteFiles: "Кешувати дані з інших інстансів"
|
||||||
|
cacheRemoteFilesDescription: "Якщо кешування вимкнено, віддалені файли завантажуються безпосередньо з віддаленого інстансу. Це зменшує використання сховища, але збільшує трафік, оскільки не генеруются ескізи."
|
||||||
flagAsBot: "Акаунт бота"
|
flagAsBot: "Акаунт бота"
|
||||||
flagAsCat: "Акаунт кота"
|
flagAsCat: "Акаунт кота"
|
||||||
autoAcceptFollowed: "Автоматично приймати запити на підписку від користувачів, на яких ви підписані"
|
autoAcceptFollowed: "Автоматично приймати запити на підписку від користувачів, на яких ви підписані"
|
||||||
@ -125,7 +134,7 @@ general: "Загальне"
|
|||||||
wallpaper: "Шпалери"
|
wallpaper: "Шпалери"
|
||||||
setWallpaper: "Встановити шпалери"
|
setWallpaper: "Встановити шпалери"
|
||||||
removeWallpaper: "Прибрати шпалери"
|
removeWallpaper: "Прибрати шпалери"
|
||||||
searchWith: "Шукати з {q}"
|
searchWith: "Пошук: {q}"
|
||||||
youHaveNoLists: "У вас немає списків"
|
youHaveNoLists: "У вас немає списків"
|
||||||
followConfirm: "Підписатися на {name}?"
|
followConfirm: "Підписатися на {name}?"
|
||||||
proxyAccount: "Проксі-акаунт"
|
proxyAccount: "Проксі-акаунт"
|
||||||
@ -159,16 +168,19 @@ instanceInfo: "Про цей інстанс"
|
|||||||
statistics: "Статистика"
|
statistics: "Статистика"
|
||||||
clearQueue: "Очистити чергу"
|
clearQueue: "Очистити чергу"
|
||||||
clearQueueConfirmTitle: "Ви впевнені, що хочете очистити чергу?"
|
clearQueueConfirmTitle: "Ви впевнені, що хочете очистити чергу?"
|
||||||
|
clearQueueConfirmText: "Будь-які невідправлені нотатки, що залишилися в черзі, не будуть передані. Зазвичай ця операція НЕ потрібна."
|
||||||
clearCachedFiles: "Очистити кеш"
|
clearCachedFiles: "Очистити кеш"
|
||||||
clearCachedFilesConfirm: "Ви впевнені, що хочете видалити всі кешовані файли?"
|
clearCachedFilesConfirm: "Ви впевнені, що хочете видалити всі кешовані файли?"
|
||||||
blockedInstances: "Заблоковані інстанси"
|
blockedInstances: "Заблоковані інстанси"
|
||||||
|
blockedInstancesDescription: "Вкажіть інстанси, які потрібно заблокувати. Перелічені інстанси більше не зможуть спілкуватися з цим інстансом."
|
||||||
muteAndBlock: "Ігнор і блокування"
|
muteAndBlock: "Ігнор і блокування"
|
||||||
mutedUsers: "Ігноровані користувачі"
|
mutedUsers: "Ігноровані користувачі"
|
||||||
blockedUsers: "Заблоковані користувачі"
|
blockedUsers: "Заблоковані користувачі"
|
||||||
noUsers: "Немає користувачів"
|
noUsers: "Немає користувачів"
|
||||||
editProfile: "Редагувати профіль"
|
editProfile: "Редагувати профіль"
|
||||||
noteDeleteConfirm: "Ви дійсно хочете видалити цей допис?"
|
noteDeleteConfirm: "Ви дійсно хочете видалити цю нотатку?"
|
||||||
pinLimitExceeded: "Більше дописів не можна закріпити"
|
pinLimitExceeded: "Більше нотаток не можна закріпити"
|
||||||
|
intro: "Встановлення Misskey завершено! Будь ласка, створіть акаунт адміністратора."
|
||||||
done: "Готово"
|
done: "Готово"
|
||||||
processing: "Обробка"
|
processing: "Обробка"
|
||||||
preview: "Передогляд"
|
preview: "Передогляд"
|
||||||
@ -178,32 +190,52 @@ noJobs: "Немає завдань"
|
|||||||
federating: "Федерується"
|
federating: "Федерується"
|
||||||
blocked: "Заблоковано"
|
blocked: "Заблоковано"
|
||||||
suspended: "Призупинено"
|
suspended: "Призупинено"
|
||||||
|
all: "Всі"
|
||||||
|
subscribing: "Підписка"
|
||||||
|
publishing: "Публікація"
|
||||||
notResponding: "Не відповідає"
|
notResponding: "Не відповідає"
|
||||||
|
instanceFollowing: "Підписка на інстанс"
|
||||||
|
instanceFollowers: "Підписники інстансу"
|
||||||
|
instanceUsers: "Користувачі цього інстансу"
|
||||||
changePassword: "Змінити пароль"
|
changePassword: "Змінити пароль"
|
||||||
security: "Безпека"
|
security: "Безпека"
|
||||||
|
retypedNotMatch: "Введені дані не збігаються."
|
||||||
currentPassword: "Поточний пароль"
|
currentPassword: "Поточний пароль"
|
||||||
newPassword: "Новий пароль"
|
newPassword: "Новий пароль"
|
||||||
newPasswordRetype: "Новий пароль (повторно)"
|
newPasswordRetype: "Новий пароль (повторно)"
|
||||||
attachFile: "Вкласти файл"
|
attachFile: "Вкласти файл"
|
||||||
more: "Бiльше!"
|
more: "Бiльше!"
|
||||||
featured: "Виділено"
|
featured: "Популярні"
|
||||||
|
usernameOrUserId: "Ім'я або ID користувача"
|
||||||
noSuchUser: "Користувача не знайдено"
|
noSuchUser: "Користувача не знайдено"
|
||||||
lookup: "Пошук"
|
lookup: "Пошук"
|
||||||
announcements: "Оголошення"
|
announcements: "Оголошення"
|
||||||
imageUrl: "URL зображення"
|
imageUrl: "URL зображення"
|
||||||
remove: "Видалити"
|
remove: "Видалити"
|
||||||
removed: "Видалено"
|
removed: "Видалено"
|
||||||
|
removeAreYouSure: "Ви впевнені, що хочете видалити \"{x}\"?"
|
||||||
|
deleteAreYouSure: "Ви впевнені, що хочете видалити \"{x}\"?"
|
||||||
|
resetAreYouSure: "Дійсно ресет?"
|
||||||
saved: "Збережено"
|
saved: "Збережено"
|
||||||
messaging: "Чати"
|
messaging: "Чати"
|
||||||
upload: "Завантажити"
|
upload: "Завантажити"
|
||||||
fromDrive: "З диска"
|
fromDrive: "З диска"
|
||||||
fromUrl: "З URL"
|
fromUrl: "З URL"
|
||||||
uploadFromUrl: "Завантажити з URL"
|
uploadFromUrl: "Завантажити з URL"
|
||||||
|
uploadFromUrlDescription: "URL-адреса файлу для завантаження"
|
||||||
|
uploadFromUrlRequested: "Обрано завантаження"
|
||||||
|
uploadFromUrlMayTakeTime: "Завантаження може зайняти деякий час."
|
||||||
explore: "Огляд"
|
explore: "Огляд"
|
||||||
games: "Ігри Misskey"
|
games: "Ігри Misskey"
|
||||||
|
messageRead: "Прочитано"
|
||||||
noMoreHistory: "Подальшої історії немає"
|
noMoreHistory: "Подальшої історії немає"
|
||||||
|
startMessaging: "Розпочати діалог"
|
||||||
|
nUsersRead: "Прочитали {n}"
|
||||||
|
agreeTo: "Я погоджуюсь з {0}"
|
||||||
|
tos: "Умови використання"
|
||||||
start: "Розпочати"
|
start: "Розпочати"
|
||||||
home: "Домівка"
|
home: "Домівка"
|
||||||
|
remoteUserCaution: "Інформація може бути неповною, оскільки це віддалений користувач."
|
||||||
activity: "Активність"
|
activity: "Активність"
|
||||||
images: "Зображення"
|
images: "Зображення"
|
||||||
birthday: "День народження"
|
birthday: "День народження"
|
||||||
@ -217,6 +249,7 @@ light: "Світла"
|
|||||||
dark: "Темна"
|
dark: "Темна"
|
||||||
lightThemes: "Світлі теми"
|
lightThemes: "Світлі теми"
|
||||||
darkThemes: "Темні теми"
|
darkThemes: "Темні теми"
|
||||||
|
syncDeviceDarkMode: "Синхронізувати темний режим із налаштуваннями вашого пристрою"
|
||||||
drive: "Диск"
|
drive: "Диск"
|
||||||
fileName: "Ім'я файлу"
|
fileName: "Ім'я файлу"
|
||||||
selectFile: "Вибрати файл"
|
selectFile: "Вибрати файл"
|
||||||
@ -234,13 +267,15 @@ emptyFolder: "Тека порожня"
|
|||||||
unableToDelete: "Видалення неможливе"
|
unableToDelete: "Видалення неможливе"
|
||||||
inputNewFileName: "Введіть ім'я нового файлу"
|
inputNewFileName: "Введіть ім'я нового файлу"
|
||||||
inputNewFolderName: "Введіть ім'я нової теки"
|
inputNewFolderName: "Введіть ім'я нової теки"
|
||||||
|
circularReferenceFolder: "Ви намагаєтесь перемістити папку в її підпапку."
|
||||||
hasChildFilesOrFolders: "Ця тека не порожня і не може бути видалена"
|
hasChildFilesOrFolders: "Ця тека не порожня і не може бути видалена"
|
||||||
copyUrl: "Копіювати URL"
|
copyUrl: "Копіювати URL"
|
||||||
rename: "Перейменувати"
|
rename: "Перейменувати"
|
||||||
avatar: "Аватар"
|
avatar: "Аватар"
|
||||||
banner: "Банер"
|
banner: "Банер"
|
||||||
nsfw: "NSFW"
|
nsfw: "NSFW"
|
||||||
disconnectedFromServer: "Підключення до сервера було перервано"
|
whenServerDisconnected: "Коли зв’язок із сервером втрачено"
|
||||||
|
disconnectedFromServer: "Зв’язок із сервером було перервано"
|
||||||
reload: "Оновити"
|
reload: "Оновити"
|
||||||
doNothing: "Нічого не робити"
|
doNothing: "Нічого не робити"
|
||||||
reloadConfirm: "Перезавантажити стрічку?"
|
reloadConfirm: "Перезавантажити стрічку?"
|
||||||
@ -265,14 +300,20 @@ connectSerice: "Під’єднати"
|
|||||||
disconnectSerice: "Відключитися"
|
disconnectSerice: "Відключитися"
|
||||||
enableLocalTimeline: "Увімкнути локальну стрічку"
|
enableLocalTimeline: "Увімкнути локальну стрічку"
|
||||||
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
||||||
|
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
|
||||||
registration: "Реєстрація"
|
registration: "Реєстрація"
|
||||||
enableRegistration: "Дозволити реєстрацію"
|
enableRegistration: "Дозволити реєстрацію"
|
||||||
invite: "Запрошення"
|
invite: "Запросити"
|
||||||
proxyRemoteFiles: "Проксувати файли з інших інстансів"
|
proxyRemoteFiles: "Проксувати файли з інших інстансів"
|
||||||
|
driveCapacityPerLocalAccount: "Об'єм диска на одного локального користувача"
|
||||||
|
driveCapacityPerRemoteAccount: "Об'єм диска на одного віддаленого користувача"
|
||||||
|
inMb: "В мегабайтах"
|
||||||
iconUrl: "URL аватара"
|
iconUrl: "URL аватара"
|
||||||
bannerUrl: "URL банера"
|
bannerUrl: "URL банера"
|
||||||
basicInfo: "Основна інформація"
|
basicInfo: "Основна інформація"
|
||||||
pinnedUsers: "Закріплені користувачі"
|
pinnedUsers: "Закріплені користувачі"
|
||||||
|
pinnedPages: "Закріплені сторінки"
|
||||||
|
pinnedPagesDescription: "Введіть шляхи сторінок, які ви бажаєте закріпити на головній сторінці цього інстанса, розділені новими рядками."
|
||||||
hcaptcha: "hCaptcha"
|
hcaptcha: "hCaptcha"
|
||||||
enableHcaptcha: "Увімкнути hCaptcha"
|
enableHcaptcha: "Увімкнути hCaptcha"
|
||||||
hcaptchaSiteKey: "Ключ сайту"
|
hcaptchaSiteKey: "Ключ сайту"
|
||||||
@ -287,10 +328,15 @@ name: "Ім'я"
|
|||||||
antennaSource: "Джерело антени"
|
antennaSource: "Джерело антени"
|
||||||
antennaKeywords: "Ключові слова антени"
|
antennaKeywords: "Ключові слова антени"
|
||||||
antennaExcludeKeywords: "Винятки"
|
antennaExcludeKeywords: "Винятки"
|
||||||
|
notifyAntenna: "Сповіщати про нові нотатки"
|
||||||
|
withFileAntenna: "Тільки нотатки з вкладеними файлами"
|
||||||
serviceworker: "ServiceWorker"
|
serviceworker: "ServiceWorker"
|
||||||
enableServiceworker: "Ввімкнути ServiceWorker"
|
enableServiceworker: "Ввімкнути ServiceWorker"
|
||||||
caseSensitive: "З урахуванням регістру"
|
caseSensitive: "З урахуванням регістру"
|
||||||
notesAndReplies: "Дописи та відповіді"
|
withReplies: "Включаючи відповіді"
|
||||||
|
connectedTo: "Наступні акаунти під'єднані"
|
||||||
|
notesAndReplies: "Нотатки та відповіді"
|
||||||
|
withFiles: "Файли"
|
||||||
popularUsers: "Популярні користувачі"
|
popularUsers: "Популярні користувачі"
|
||||||
recentlyUpdatedUsers: "Нещодавно активні користувачі"
|
recentlyUpdatedUsers: "Нещодавно активні користувачі"
|
||||||
recentlyRegisteredUsers: "Нещодавно зареєстровані користувачі"
|
recentlyRegisteredUsers: "Нещодавно зареєстровані користувачі"
|
||||||
@ -305,6 +351,7 @@ administrator: "Адмін"
|
|||||||
token: "Токен"
|
token: "Токен"
|
||||||
twoStepAuthentication: "Двохфакторна аутентифікація"
|
twoStepAuthentication: "Двохфакторна аутентифікація"
|
||||||
moderator: "Модератор"
|
moderator: "Модератор"
|
||||||
|
nUsersMentioned: "Згадали: {n}"
|
||||||
securityKey: "Ключ захисту"
|
securityKey: "Ключ захисту"
|
||||||
securityKeyName: "Назва ключа"
|
securityKeyName: "Назва ключа"
|
||||||
registerSecurityKey: "Зареєструвати ключ захисту"
|
registerSecurityKey: "Зареєструвати ключ захисту"
|
||||||
@ -313,9 +360,15 @@ unregister: "Скасувати реєстрацію"
|
|||||||
passwordLessLogin: "Налаштувати вхід без пароля"
|
passwordLessLogin: "Налаштувати вхід без пароля"
|
||||||
resetPassword: "Скинути пароль"
|
resetPassword: "Скинути пароль"
|
||||||
newPasswordIs: "Новий пароль: {password}"
|
newPasswordIs: "Новий пароль: {password}"
|
||||||
|
reduceUiAnimation: "Зменшити анімацію інтерфейсу"
|
||||||
share: "Поділитись"
|
share: "Поділитись"
|
||||||
notFound: "Не знайдено"
|
notFound: "Не знайдено"
|
||||||
|
notFoundDescription: "Сторінка за вказаною адресою не знайдена."
|
||||||
|
uploadFolder: "Місце для завантаження за замовчуванням"
|
||||||
cacheClear: "Очистити кеш"
|
cacheClear: "Очистити кеш"
|
||||||
|
markAsReadAllNotifications: "Позначити всі сповіщення як прочитані"
|
||||||
|
markAsReadAllUnreadNotes: "Позначити всі нотатки як прочитані"
|
||||||
|
markAsReadAllTalkMessages: "Позначити всі повідомлення як прочитані"
|
||||||
help: "Допомога"
|
help: "Допомога"
|
||||||
inputMessageHere: "Введіть повідомлення тут"
|
inputMessageHere: "Введіть повідомлення тут"
|
||||||
close: "Закрити"
|
close: "Закрити"
|
||||||
@ -323,18 +376,21 @@ group: "Група"
|
|||||||
groups: "Групи"
|
groups: "Групи"
|
||||||
createGroup: "Створити групу"
|
createGroup: "Створити групу"
|
||||||
ownedGroups: "Власні групи"
|
ownedGroups: "Власні групи"
|
||||||
invites: "Запрошення"
|
joinedGroups: "Членство в групах"
|
||||||
|
invites: "Запросити"
|
||||||
groupName: "Назва групи"
|
groupName: "Назва групи"
|
||||||
|
members: "Учасники"
|
||||||
transfer: "Передача"
|
transfer: "Передача"
|
||||||
messagingWithUser: "Чат з користувачами"
|
messagingWithUser: "Чат з користувачами"
|
||||||
messagingWithGroup: "Чат з групою"
|
messagingWithGroup: "Чат з групою"
|
||||||
title: "Тема"
|
title: "Тема"
|
||||||
text: "Текст"
|
text: "Текст"
|
||||||
|
enable: "Увімкнути"
|
||||||
next: "Далі"
|
next: "Далі"
|
||||||
retype: "Введіть ще раз"
|
retype: "Введіть ще раз"
|
||||||
noteOf: "Допис {user}"
|
noteOf: "Нотатка {user}"
|
||||||
inviteToGroup: "Запрошення до групи"
|
inviteToGroup: "Запрошення до групи"
|
||||||
maxNoteTextLength: "Максимальна довжина допису"
|
maxNoteTextLength: "Максимальна довжина нотатки"
|
||||||
quoteAttached: "Цитата"
|
quoteAttached: "Цитата"
|
||||||
quoteQuestion: "Ви хочете додати цитату?"
|
quoteQuestion: "Ви хочете додати цитату?"
|
||||||
noMessagesYet: "Ще немає повідомлень"
|
noMessagesYet: "Ще немає повідомлень"
|
||||||
@ -350,15 +406,21 @@ usernameInvalidFormat: "літери, цифри та _ є прийнятним
|
|||||||
tooShort: "Занадто короткий"
|
tooShort: "Занадто короткий"
|
||||||
tooLong: "Занадто довгий"
|
tooLong: "Занадто довгий"
|
||||||
weakPassword: "Слабкий пароль"
|
weakPassword: "Слабкий пароль"
|
||||||
|
normalPassword: "Достатній пароль"
|
||||||
strongPassword: "Міцний пароль"
|
strongPassword: "Міцний пароль"
|
||||||
passwordMatched: "Все вірно"
|
passwordMatched: "Все вірно"
|
||||||
passwordNotMatched: "Паролі не співпадають"
|
passwordNotMatched: "Паролі не співпадають"
|
||||||
signinWith: "Увійти за допомогою {x}"
|
signinWith: "Увійти за допомогою {x}"
|
||||||
|
signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi."
|
||||||
|
tapSecurityKey: "Торкніться ключа безпеки"
|
||||||
|
or: "або"
|
||||||
uiLanguage: "Мова інтерфейсу"
|
uiLanguage: "Мова інтерфейсу"
|
||||||
|
groupInvited: "Запрошення до групи"
|
||||||
aboutX: "Про {x}"
|
aboutX: "Про {x}"
|
||||||
useOsNativeEmojis: "Використовувати емодзі ОС"
|
useOsNativeEmojis: "Використовувати емодзі ОС"
|
||||||
youHaveNoGroups: "Немає груп"
|
youHaveNoGroups: "Немає груп"
|
||||||
noHistory: "Історія порожня"
|
noHistory: "Історія порожня"
|
||||||
|
signinHistory: "Історія входів"
|
||||||
disableAnimatedMfm: "Відключити анімації MFM"
|
disableAnimatedMfm: "Відключити анімації MFM"
|
||||||
doing: "Виконується"
|
doing: "Виконується"
|
||||||
category: "Категорія"
|
category: "Категорія"
|
||||||
@ -369,20 +431,22 @@ existingAcount: "Існуючий акаунт"
|
|||||||
regenerate: "Оновити"
|
regenerate: "Оновити"
|
||||||
fontSize: "Розмір шрифту"
|
fontSize: "Розмір шрифту"
|
||||||
noFollowRequests: "Немає запитів на підписку"
|
noFollowRequests: "Немає запитів на підписку"
|
||||||
|
openImageInNewTab: "Відкрити зображення в новій вкладці"
|
||||||
dashboard: "Панель приладів"
|
dashboard: "Панель приладів"
|
||||||
local: "Локальні"
|
local: "Локальні"
|
||||||
remote: "Віддалені"
|
remote: "Віддалені"
|
||||||
total: "Всього"
|
total: "Всього"
|
||||||
weekOverWeekChanges: "За тиждень"
|
weekOverWeekChanges: "Тиждень"
|
||||||
dayOverDayChanges: "За добу"
|
dayOverDayChanges: "Доба"
|
||||||
appearance: "Вигляд"
|
appearance: "Вигляд"
|
||||||
clientSettings: "Налаштування клієнта"
|
clientSettings: "Налаштування клієнта"
|
||||||
accountSettings: "Налаштування акаунта"
|
accountSettings: "Налаштування акаунта"
|
||||||
promotion: "Просування"
|
promotion: "Виділене"
|
||||||
promote: "Просунути"
|
promote: "Виділити"
|
||||||
numberOfDays: "Кількість днів"
|
numberOfDays: "Кількість днів"
|
||||||
hideThisNote: "Сховати цей допис"
|
hideThisNote: "Сховати цю нотатку"
|
||||||
showFeaturedNotesInTimeline: "Показувати рекомендовані дописи у стрічці"
|
showFeaturedNotesInTimeline: "Показувати популярні нотатки у стрічці"
|
||||||
|
objectStorage: "Object Storage"
|
||||||
objectStorageBaseUrl: "Base URL"
|
objectStorageBaseUrl: "Base URL"
|
||||||
objectStorageBucket: "Bucket"
|
objectStorageBucket: "Bucket"
|
||||||
objectStoragePrefix: "Prefix"
|
objectStoragePrefix: "Prefix"
|
||||||
@ -390,16 +454,19 @@ objectStorageEndpoint: "Endpoint"
|
|||||||
objectStorageRegion: "Region"
|
objectStorageRegion: "Region"
|
||||||
objectStorageUseSSL: "Використовувати SSL"
|
objectStorageUseSSL: "Використовувати SSL"
|
||||||
objectStorageUseProxy: "Використовувати Proxy"
|
objectStorageUseProxy: "Використовувати Proxy"
|
||||||
|
serverLogs: "Журнал сервера"
|
||||||
deleteAll: "Видалити все"
|
deleteAll: "Видалити все"
|
||||||
newNoteRecived: "Є нові дописи"
|
newNoteRecived: "Є нові нотатки"
|
||||||
sounds: "Звуки"
|
sounds: "Звуки"
|
||||||
listen: "Слухати"
|
listen: "Слухати"
|
||||||
none: "Відсутній"
|
none: "Відсутній"
|
||||||
showInPage: "Показати на сторінці"
|
showInPage: "Показати на сторінці"
|
||||||
popout: "Розгорнути"
|
popout: "Від'єднати"
|
||||||
volume: "Гучність"
|
volume: "Гучність"
|
||||||
|
masterVolume: "Загальна гучність"
|
||||||
details: "Детальніше"
|
details: "Детальніше"
|
||||||
chooseEmoji: "Виберіть емодзі"
|
chooseEmoji: "Виберіть емодзі"
|
||||||
|
unableToProcess: "Не вдається завершити операцію"
|
||||||
recentUsed: "Нещодавні"
|
recentUsed: "Нещодавні"
|
||||||
install: "Встановити"
|
install: "Встановити"
|
||||||
uninstall: "Видалити"
|
uninstall: "Видалити"
|
||||||
@ -414,65 +481,209 @@ descendingOrder: "За спаданням"
|
|||||||
scratchpad: "Чернетка"
|
scratchpad: "Чернетка"
|
||||||
output: "Вихід"
|
output: "Вихід"
|
||||||
script: "Скрипт"
|
script: "Скрипт"
|
||||||
|
disablePagesScript: "Вимкнути AiScript на Сторінках"
|
||||||
|
updateRemoteUser: "Оновити інформацію про віддаленого користувача"
|
||||||
deleteAllFiles: "Видалити всі файли"
|
deleteAllFiles: "Видалити всі файли"
|
||||||
deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?"
|
deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?"
|
||||||
removeAllFollowing: "Скасувати всі підписки"
|
removeAllFollowing: "Скасувати всі підписки"
|
||||||
|
removeAllFollowingDescription: "Скасувати підписку на всі акаунти з {host}. Будь ласка, робіть це, якщо інстанс більше не існує."
|
||||||
sidebar: "Бокова панель"
|
sidebar: "Бокова панель"
|
||||||
|
divider: "Розділювач"
|
||||||
addItem: "Додати елемент"
|
addItem: "Додати елемент"
|
||||||
rooms: "Кімнати"
|
rooms: "Кімнати"
|
||||||
relays: "Ретранслятори"
|
relays: "Ретранслятори"
|
||||||
addRelay: "Додати ретранслятор"
|
addRelay: "Додати ретранслятор"
|
||||||
|
inboxUrl: "Inbox URL"
|
||||||
addedRelays: "Додані ретранслятори"
|
addedRelays: "Додані ретранслятори"
|
||||||
deletedNote: "Допис видалено"
|
serviceworkerInfo: "Повинен бути ввімкнений для push-сповіщень."
|
||||||
|
deletedNote: "Видалена нотатка"
|
||||||
|
enableInfiniteScroll: "Увімкнути нескінченну прокрутку"
|
||||||
visibility: "Видимість"
|
visibility: "Видимість"
|
||||||
poll: "Опитування"
|
poll: "Опитування"
|
||||||
|
useCw: "Приховати вміст"
|
||||||
|
enablePlayer: "Відкрити відеоплеєр"
|
||||||
|
disablePlayer: "Закрити відеоплеєр"
|
||||||
expandTweet: "Розгорнути твіт"
|
expandTweet: "Розгорнути твіт"
|
||||||
themeEditor: "Редактор тем"
|
themeEditor: "Редактор тем"
|
||||||
description: "Опис"
|
description: "Опис"
|
||||||
author: "Автор"
|
author: "Автор"
|
||||||
manage: "Управління"
|
manage: "Управління"
|
||||||
plugins: "Плагіни"
|
plugins: "Плагіни"
|
||||||
|
deck: "Дек"
|
||||||
|
undeck: "Залишити Дек"
|
||||||
|
useBlurEffectForModal: "Ефект розмиття під модальними діалогами"
|
||||||
|
useFullReactionPicker: "Повнорозмірний селектор реакцій"
|
||||||
|
width: "Ширина"
|
||||||
|
height: "Висота"
|
||||||
|
large: "Крупний"
|
||||||
|
medium: "Середній"
|
||||||
|
small: "Маленький"
|
||||||
generateAccessToken: "Згенерувати токен доступу"
|
generateAccessToken: "Згенерувати токен доступу"
|
||||||
permission: "Права"
|
permission: "Права"
|
||||||
enableAll: "Ввімкути все"
|
enableAll: "Увімкнути все"
|
||||||
disableAll: "Вимкнути все"
|
disableAll: "Вимкнути все"
|
||||||
tokenRequested: "Надати доступ до акаунту"
|
tokenRequested: "Надати доступ до акаунту"
|
||||||
notificationType: "Тип сповіщення"
|
notificationType: "Тип сповіщення"
|
||||||
edit: "Редагувати"
|
edit: "Редагувати"
|
||||||
useStarForReactionFallback: "Використовувати ★ як запасний варіант, якщо емодзі реакції невідомий"
|
useStarForReactionFallback: "Використовувати ★ як запасний варіант, якщо емодзі реакції невідомий"
|
||||||
emailConfig: "Налаштування email сервера"
|
emailConfig: "Налаштування email сервера"
|
||||||
email: "E-mail адреса"
|
|
||||||
smtpHost: "Хост"
|
smtpHost: "Хост"
|
||||||
smtpPort: "Порт"
|
smtpPort: "Порт"
|
||||||
smtpUser: "Ім'я користувача"
|
smtpUser: "Ім'я користувача"
|
||||||
smtpPass: "Пароль"
|
smtpPass: "Пароль"
|
||||||
testEmail: "Тестовий email"
|
testEmail: "Тестовий email"
|
||||||
wordMute: "Ігнор слів"
|
wordMute: "Ігнор слів"
|
||||||
|
makeActive: "Активувати"
|
||||||
copy: "Скопіювати"
|
copy: "Скопіювати"
|
||||||
metrics: "Показники"
|
metrics: "Показники"
|
||||||
|
overview: "Огляд"
|
||||||
|
logs: "Журнал"
|
||||||
|
delayed: "Затримка"
|
||||||
database: "База даних"
|
database: "База даних"
|
||||||
channel: "Канал"
|
channel: "Канали"
|
||||||
|
create: "Створити"
|
||||||
|
notificationSetting: "Параметри сповіщень"
|
||||||
|
notificationSettingDesc: "Виберіть типи сповіщень для відображення"
|
||||||
|
useGlobalSetting: "Застосувати глобальнi параметри"
|
||||||
|
other: "Інше"
|
||||||
regenerateLoginToken: "Оновити Login Token"
|
regenerateLoginToken: "Оновити Login Token"
|
||||||
|
sample: "Приклад"
|
||||||
|
reportAbuse: "Поскаржитись"
|
||||||
|
reportAbuseOf: "Поскаржитись на {name}"
|
||||||
|
send: "Відправити"
|
||||||
|
abuseMarkAsResolved: "Позначити скаргу як вирішену"
|
||||||
|
openInNewTab: "Відкрити в новій вкладці"
|
||||||
|
waitingFor: "Чекаємо на {x}"
|
||||||
|
random: "Випадковий"
|
||||||
|
system: "Система"
|
||||||
|
switchUi: "Інтерфейс"
|
||||||
|
desktop: "Десктоп"
|
||||||
|
clip: "Добірка"
|
||||||
|
public: "Публічний"
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: " Довідка MFM"
|
cheatSheet: " Довідка MFM"
|
||||||
|
intro: "MFM це ексклюзивна мова розмітки тексту в Misskey, яку можна використовувати в багатьох місцях. Тут ви можете переглянути приклади її синтаксису."
|
||||||
mention: "Згадка"
|
mention: "Згадка"
|
||||||
|
hashtag: "Хештеґ"
|
||||||
|
url: "URL"
|
||||||
|
link: "Посилання"
|
||||||
|
linkDescription: "Окремі частини тексту можуть містити посилання"
|
||||||
|
bold: "Жирний шрифт"
|
||||||
|
boldDescription: "Виділяє літери, роблячи їх товще"
|
||||||
|
small: "Дрібний шрифт"
|
||||||
|
smallDescription: "Робить текст маленьким і тонким"
|
||||||
|
center: "По центру"
|
||||||
|
centerDescription: "Показує вміст у центрі"
|
||||||
|
inlineCode: "Код (у рядку)"
|
||||||
|
inlineCodeDescription: "Показує фрагмент тексту у рядку як програмний код"
|
||||||
|
blockCode: "Код (блок)"
|
||||||
|
blockCodeDescription: "Показує кілька рядків тексту як блок програмного кода"
|
||||||
|
inlineMath: "Формула (у рядку)"
|
||||||
|
blockMath: "Формули (блок)"
|
||||||
quote: "Цитата"
|
quote: "Цитата"
|
||||||
emoji: "Кастомні емоджі"
|
emoji: "Кастомні емоджі"
|
||||||
search: "Пошук"
|
search: "Пошук"
|
||||||
|
searchDescription: "Відображає вікно пошуку з попередньо введеним текстом"
|
||||||
|
flipDescription: "Віддзеркалює вміст по горизонталі або вертикалі"
|
||||||
|
jelly: "Анімація (желе)"
|
||||||
|
jellyDescription: "Створює желеподібну анімацію"
|
||||||
|
tada: "Анімація (Тада!)"
|
||||||
|
tadaDescription: "Створює анімацію з відчуттям \"Тада!\""
|
||||||
|
jump: "Анімація (стрибки)"
|
||||||
|
jumpDescription: "Показує стрибаючу анімацію"
|
||||||
|
bounce: "Анімація (пружина)"
|
||||||
|
shake: "Анімація (Shake)"
|
||||||
|
twitch: "Анімація (Twitch)"
|
||||||
|
spin: "Анімація (Spin)"
|
||||||
_reversi:
|
_reversi:
|
||||||
|
reversi: "Реверсі"
|
||||||
|
gameSettings: "Налаштування гри"
|
||||||
|
chooseBoard: "Вибір дошки"
|
||||||
|
blackOrWhite: "Чорні / Білі"
|
||||||
|
blackIs: "{name} грає чорними"
|
||||||
|
rules: "Правила"
|
||||||
|
thisGameIsStartedSoon: "Гра розпочнеться через кілька секунд"
|
||||||
|
waitingForOther: "Чекаємо на хід суперника"
|
||||||
|
waitingForMe: "Чекаємо на ваш хід"
|
||||||
|
waitingBoth: "Приготуйтесь"
|
||||||
|
ready: "Готовність"
|
||||||
|
cancelReady: "Скасувати готовність"
|
||||||
|
opponentTurn: "Хід суперника"
|
||||||
|
myTurn: "Ваш хід"
|
||||||
|
turnOf: "Хід {name}"
|
||||||
|
pastTurnOf: "Хід {name}"
|
||||||
|
surrender: "Здатися"
|
||||||
|
drawn: "Нічия"
|
||||||
|
won: "Перемога {name}"
|
||||||
|
black: "Чорні"
|
||||||
|
white: "Білі"
|
||||||
total: "Всього"
|
total: "Всього"
|
||||||
|
turnCount: "Хід {count}"
|
||||||
|
myGames: "Мої ігри"
|
||||||
|
allGames: "Усі ігри"
|
||||||
|
ended: "Завершено"
|
||||||
|
_instanceTicker:
|
||||||
|
none: "Не відображати"
|
||||||
|
remote: "Відображати для віддалених користувачів"
|
||||||
|
always: "Відображати завжди"
|
||||||
|
_serverDisconnectedBehavior:
|
||||||
|
reload: "Автоматично перезавантажити"
|
||||||
|
dialog: "Показати діалогове вікно"
|
||||||
|
quiet: "Показати ненав’язливе попередження"
|
||||||
|
_channel:
|
||||||
|
create: "Створити канал"
|
||||||
|
edit: "Редагувати канал"
|
||||||
|
setBanner: "Встановити банер"
|
||||||
|
removeBanner: "Видалити банер"
|
||||||
|
featured: "Тренди"
|
||||||
_sidebar:
|
_sidebar:
|
||||||
icon: "Аватар"
|
icon: "Аватар"
|
||||||
_theme:
|
_theme:
|
||||||
keys:
|
keys:
|
||||||
|
accent: "Акцент"
|
||||||
|
bg: "Фон"
|
||||||
|
fg: "Текст"
|
||||||
|
focus: "Фокус"
|
||||||
|
indicator: "Індикатор"
|
||||||
|
panel: "Панель"
|
||||||
|
shadow: "Тінь"
|
||||||
|
header: "Заголовок"
|
||||||
|
navBg: "Фон бокової панелі"
|
||||||
|
navFg: "Текст бокової панелі"
|
||||||
|
navHoverFg: "Текст бокової панелі (під курсором)"
|
||||||
|
navActive: "Текст бокової панелі (активне)"
|
||||||
|
navIndicator: "Індикатор бокової панелі"
|
||||||
|
link: "Посилання"
|
||||||
|
hashtag: "Хештеґ"
|
||||||
mention: "Згадка"
|
mention: "Згадка"
|
||||||
|
mentionMe: "Згадки (мене)"
|
||||||
renote: "Поширити"
|
renote: "Поширити"
|
||||||
|
divider: "Розділювач"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Дописи"
|
note: "Нотатки"
|
||||||
notification: "Сповіщення"
|
notification: "Сповіщення"
|
||||||
chat: "Чати"
|
chat: "Чати"
|
||||||
|
_ago:
|
||||||
|
unknown: "Невідомо"
|
||||||
|
future: "Майбутнє"
|
||||||
|
justNow: "Щойно"
|
||||||
|
secondsAgo: "{n}с тому"
|
||||||
|
minutesAgo: "{n}х тому"
|
||||||
|
hoursAgo: "{n}г тому"
|
||||||
|
daysAgo: "{n}д тому"
|
||||||
|
weeksAgo: "{n} тиж. тому"
|
||||||
|
monthsAgo: "{n} міс. тому"
|
||||||
|
yearsAgo: "{n} р. тому"
|
||||||
|
_time:
|
||||||
|
second: "с"
|
||||||
|
minute: "х"
|
||||||
|
hour: "г"
|
||||||
|
day: "д"
|
||||||
|
_tutorial:
|
||||||
|
title: "Як користуватись Misskey"
|
||||||
|
step1_1: "Ласкаво просимо!"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
homeTimeline: "Дописи тих, на кого ви підписані"
|
homeTimeline: "Нотатки тих, на кого ви підписані"
|
||||||
_widgets:
|
_widgets:
|
||||||
notifications: "Сповіщення"
|
notifications: "Сповіщення"
|
||||||
timeline: "Стрічка"
|
timeline: "Стрічка"
|
||||||
@ -480,12 +691,14 @@ _widgets:
|
|||||||
federation: "Федіверс"
|
federation: "Федіверс"
|
||||||
_cw:
|
_cw:
|
||||||
show: "Показати більше"
|
show: "Показати більше"
|
||||||
|
_poll:
|
||||||
|
deadlineTime: "г"
|
||||||
_visibility:
|
_visibility:
|
||||||
home: "Домівка"
|
home: "Домівка"
|
||||||
followers: "Підписники"
|
followers: "Підписники"
|
||||||
localOnly: "Лише локально"
|
localOnly: "Лише локально"
|
||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Відповідь на допис..."
|
replyPlaceholder: "Відповідь на цю нотатку..."
|
||||||
_profile:
|
_profile:
|
||||||
name: "Ім'я"
|
name: "Ім'я"
|
||||||
username: "Ім'я користувача"
|
username: "Ім'я користувача"
|
||||||
@ -502,6 +715,7 @@ _rooms:
|
|||||||
_furnitures:
|
_furnitures:
|
||||||
monitor: "Монітор"
|
monitor: "Монітор"
|
||||||
_pages:
|
_pages:
|
||||||
|
featured: "Популярні"
|
||||||
blocks:
|
blocks:
|
||||||
image: "Зображення"
|
image: "Зображення"
|
||||||
script:
|
script:
|
||||||
@ -529,8 +743,9 @@ _relayStatus:
|
|||||||
accepted: "Затверджено"
|
accepted: "Затверджено"
|
||||||
rejected: "Відхилено"
|
rejected: "Відхилено"
|
||||||
_notification:
|
_notification:
|
||||||
youRenoted: "{name} поширив(ла) ваш допис"
|
youRenoted: "{name} поширив(ла) вашу нотатку"
|
||||||
youWereFollowed: "Новий підписник"
|
youWereFollowed: "Новий підписник"
|
||||||
|
youWereInvitedToGroup: "Запрошення до групи"
|
||||||
_types:
|
_types:
|
||||||
follow: "Підписки"
|
follow: "Підписки"
|
||||||
mention: "Згадка"
|
mention: "Згадка"
|
||||||
|
@ -125,7 +125,9 @@ settingGuide: "推荐配置"
|
|||||||
cacheRemoteFiles: "远程文件缓存"
|
cacheRemoteFiles: "远程文件缓存"
|
||||||
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
||||||
flagAsBot: "这个账户是Bot"
|
flagAsBot: "这个账户是Bot"
|
||||||
|
flagAsBotDescription: "如果此帐户由程序控制,请启用此项。启用后,此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为,并让Misskey的内部系统将此帐户识别为机器人。"
|
||||||
flagAsCat: "这个账户是Cat"
|
flagAsCat: "这个账户是Cat"
|
||||||
|
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。"
|
||||||
autoAcceptFollowed: "自动允许关注"
|
autoAcceptFollowed: "自动允许关注"
|
||||||
addAcount: "添加账户"
|
addAcount: "添加账户"
|
||||||
loginFailed: "登录失败"
|
loginFailed: "登录失败"
|
||||||
@ -358,13 +360,6 @@ popularTags: "热门标签"
|
|||||||
userList: "列表"
|
userList: "列表"
|
||||||
about: "关于"
|
about: "关于"
|
||||||
aboutMisskey: "关于 Misskey"
|
aboutMisskey: "关于 Misskey"
|
||||||
aboutMisskeyText: "Misskey是由syuilo于2014年开发的开源软件。"
|
|
||||||
misskeyMembers: "现在由以下成员进行开发和维护:"
|
|
||||||
misskeySource: "源代码在这里公开:"
|
|
||||||
misskeyTranslation: "与我们一同进行Misskey的翻译工作:"
|
|
||||||
misskeyDonate: "可以向 Misskey 进行捐款以支持开发:"
|
|
||||||
morePatrons: "还有很多其他的人也在支持我们,非常感谢🥰"
|
|
||||||
patrons: "支持者"
|
|
||||||
administrator: "管理员"
|
administrator: "管理员"
|
||||||
token: "令牌"
|
token: "令牌"
|
||||||
twoStepAuthentication: "两步验证"
|
twoStepAuthentication: "两步验证"
|
||||||
@ -439,6 +434,7 @@ useOsNativeEmojis: "使用OS原生表情符号"
|
|||||||
youHaveNoGroups: "没有群组"
|
youHaveNoGroups: "没有群组"
|
||||||
joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
|
joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
|
||||||
noHistory: "没有历史记录"
|
noHistory: "没有历史记录"
|
||||||
|
signinHistory: "登录历史"
|
||||||
disableAnimatedMfm: "禁用MFM动画"
|
disableAnimatedMfm: "禁用MFM动画"
|
||||||
doing: "正在进行"
|
doing: "正在进行"
|
||||||
category: "类别"
|
category: "类别"
|
||||||
@ -491,6 +487,7 @@ none: "空"
|
|||||||
showInPage: "在页面中显示"
|
showInPage: "在页面中显示"
|
||||||
popout: "弹窗"
|
popout: "弹窗"
|
||||||
volume: "音量"
|
volume: "音量"
|
||||||
|
masterVolume: "主音量"
|
||||||
details: "详情"
|
details: "详情"
|
||||||
chooseEmoji: "选择表情符号"
|
chooseEmoji: "选择表情符号"
|
||||||
unableToProcess: "操作无法完成"
|
unableToProcess: "操作无法完成"
|
||||||
@ -548,6 +545,9 @@ useBlurEffectForModal: "模态框使用模糊效果"
|
|||||||
useFullReactionPicker: "使用全功能的回应工具栏"
|
useFullReactionPicker: "使用全功能的回应工具栏"
|
||||||
width: "宽度"
|
width: "宽度"
|
||||||
height: "高度"
|
height: "高度"
|
||||||
|
large: "大"
|
||||||
|
medium: "中"
|
||||||
|
small: "小"
|
||||||
generateAccessToken: "生成访问令牌"
|
generateAccessToken: "生成访问令牌"
|
||||||
permission: "权限"
|
permission: "权限"
|
||||||
enableAll: "启用全部"
|
enableAll: "启用全部"
|
||||||
@ -560,7 +560,8 @@ useStarForReactionFallback: "如果回应的是未知表情符号,则使用★
|
|||||||
emailConfig: "邮件服务器设置"
|
emailConfig: "邮件服务器设置"
|
||||||
enableEmail: "启用发送邮件功能"
|
enableEmail: "启用发送邮件功能"
|
||||||
emailConfigInfo: "用于确认电子邮件和密码重置"
|
emailConfigInfo: "用于确认电子邮件和密码重置"
|
||||||
email: "邮件地址"
|
email: "邮箱"
|
||||||
|
emailAddress: "电子邮件地址"
|
||||||
smtpConfig: "SMTP服务器设置"
|
smtpConfig: "SMTP服务器设置"
|
||||||
smtpHost: "主机名"
|
smtpHost: "主机名"
|
||||||
smtpPort: "端口"
|
smtpPort: "端口"
|
||||||
@ -592,6 +593,7 @@ regenerateLoginTokenDescription: "重新生成用于登录的内部令牌。通
|
|||||||
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。"
|
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。"
|
||||||
fileIdOrUrl: "文件ID或者URL"
|
fileIdOrUrl: "文件ID或者URL"
|
||||||
chatOpenBehavior: "聊天窗口打开时的行为"
|
chatOpenBehavior: "聊天窗口打开时的行为"
|
||||||
|
behavior: "行为"
|
||||||
sample: "示例"
|
sample: "示例"
|
||||||
abuseReports: "举报"
|
abuseReports: "举报"
|
||||||
reportAbuse: "举报"
|
reportAbuse: "举报"
|
||||||
@ -615,6 +617,41 @@ createNew: "新建"
|
|||||||
optional: "可选"
|
optional: "可选"
|
||||||
createNewClip: "新建片段"
|
createNewClip: "新建片段"
|
||||||
public: "公开"
|
public: "公开"
|
||||||
|
i18nInfo: "Misskey已经被志愿者们翻译到了各种语言。如果你也有兴趣,可以来{link}帮助翻译。"
|
||||||
|
manageAccessTokens: "管理 Access Tokens"
|
||||||
|
accountInfo: "帐户信息"
|
||||||
|
notesCount: "贴文数量"
|
||||||
|
repliesCount: "回复数量"
|
||||||
|
renotesCount: "转贴数量"
|
||||||
|
repliedCount: "回复数"
|
||||||
|
renotedCount: "转发数"
|
||||||
|
followingCount: "正在关注数量"
|
||||||
|
followersCount: "关注者数量"
|
||||||
|
sentReactionsCount: "发送反应数"
|
||||||
|
receivedReactionsCount: "收到反应数"
|
||||||
|
pollVotesCount: "发起投票数"
|
||||||
|
pollVotedCount: "已投票数"
|
||||||
|
yes: "确定"
|
||||||
|
no: "取消"
|
||||||
|
driveFilesCount: "磁盘文件数"
|
||||||
|
driveUsage: "磁盘空间用量"
|
||||||
|
noCrawle: "拒绝搜索器的索引"
|
||||||
|
noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。"
|
||||||
|
lockedAccountInfo: "即使通过了关注请求,只要您不将帖子可见范围设置成“关注者”,任何人都可以看到您的帖子。"
|
||||||
|
alwaysMarkSensitive: "浏览默认媒体文件时请谨慎"
|
||||||
|
loadRawImages: "添加附件图像的缩略图时使用原始图像质量"
|
||||||
|
disableShowingAnimatedImages: "不播放动画"
|
||||||
|
verificationEmailSent: "已发送确认电子邮件。请访问电子邮件中的链接以完成设置。"
|
||||||
|
notSet: "未设置"
|
||||||
|
emailVerified: "电子邮件地址已验证"
|
||||||
|
noteFavoritesCount: "收藏的帖子数"
|
||||||
|
pageLikesCount: "页面点赞次数"
|
||||||
|
pageLikedCount: "页面被点赞次数"
|
||||||
|
reversiCount: "黑白棋对战次数"
|
||||||
|
_nsfw:
|
||||||
|
respect: "隐藏NSFW内容"
|
||||||
|
ignore: "不隐藏NSFW内容"
|
||||||
|
force: "总是隐藏内容"
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "MFM代码速查表"
|
cheatSheet: "MFM代码速查表"
|
||||||
intro: "MFM是一种在Misskey中的各个位置使用的专用标记语言。在这里您可以看到MFM中可用的语法列表。"
|
intro: "MFM是一种在Misskey中的各个位置使用的专用标记语言。在这里您可以看到MFM中可用的语法列表。"
|
||||||
@ -733,6 +770,8 @@ _theme:
|
|||||||
manage: "主题管理"
|
manage: "主题管理"
|
||||||
code: "主题代码"
|
code: "主题代码"
|
||||||
installed: "{name} 已安装"
|
installed: "{name} 已安装"
|
||||||
|
installedThemes: "已安装的主题"
|
||||||
|
builtinThemes: "标准主题"
|
||||||
alreadyInstalled: "此主题已经安装"
|
alreadyInstalled: "此主题已经安装"
|
||||||
invalid: "主题格式错误"
|
invalid: "主题格式错误"
|
||||||
make: "制作主题"
|
make: "制作主题"
|
||||||
@ -971,7 +1010,9 @@ _profile:
|
|||||||
username: "用户名"
|
username: "用户名"
|
||||||
description: "个人简介"
|
description: "个人简介"
|
||||||
youCanIncludeHashtags: "您可以包含一个哈希标签。"
|
youCanIncludeHashtags: "您可以包含一个哈希标签。"
|
||||||
metadata: "额外信息"
|
metadata: "附加信息"
|
||||||
|
metadataEdit: "附加信息编辑"
|
||||||
|
metadataDescription: "最多可以在个人资料中以表格形式显示四条其他信息。"
|
||||||
metadataLabel: "标签"
|
metadataLabel: "标签"
|
||||||
metadataContent: "内容"
|
metadataContent: "内容"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -351,13 +351,6 @@ popularTags: "熱門標籤"
|
|||||||
userList: "清單"
|
userList: "清單"
|
||||||
about: "資訊"
|
about: "資訊"
|
||||||
aboutMisskey: "關於 Misskey"
|
aboutMisskey: "關於 Misskey"
|
||||||
aboutMisskeyText: "Misskey是由syuilo於2014年開發的開放源代碼軟件。"
|
|
||||||
misskeyMembers: "現在由以下成員開發及維護:"
|
|
||||||
misskeySource: "源代碼在這裡公開:"
|
|
||||||
misskeyTranslation: "幫助我們為Misskey的翻譯工作出一分力:"
|
|
||||||
misskeyDonate: "向Misskey捐款以支援我們開發工作:"
|
|
||||||
morePatrons: "感激你們的支持、 幫助。 🥰"
|
|
||||||
patrons: "贊助者"
|
|
||||||
administrator: "管理員"
|
administrator: "管理員"
|
||||||
token: "令牌"
|
token: "令牌"
|
||||||
twoStepAuthentication: "雙重身份驗證"
|
twoStepAuthentication: "雙重身份驗證"
|
||||||
@ -531,7 +524,6 @@ useStarForReactionFallback: "以★代替未知的表情符號"
|
|||||||
emailConfig: "電子郵件伺服器設定"
|
emailConfig: "電子郵件伺服器設定"
|
||||||
enableEmail: "啟用發送電郵功能"
|
enableEmail: "啟用發送電郵功能"
|
||||||
emailConfigInfo: "用於確認電郵地址及密碼重置"
|
emailConfigInfo: "用於確認電郵地址及密碼重置"
|
||||||
email: "電郵地址"
|
|
||||||
smtpConfig: "SMTP伺服器設定"
|
smtpConfig: "SMTP伺服器設定"
|
||||||
smtpHost: "主機"
|
smtpHost: "主機"
|
||||||
smtpPort: "端口"
|
smtpPort: "端口"
|
||||||
@ -773,7 +765,6 @@ _profile:
|
|||||||
username: "使用者名稱"
|
username: "使用者名稱"
|
||||||
description: "關於我"
|
description: "關於我"
|
||||||
youCanIncludeHashtags: "你也可以在「關於我」中加上 #tag"
|
youCanIncludeHashtags: "你也可以在「關於我」中加上 #tag"
|
||||||
metadata: "更多資訊"
|
|
||||||
metadataLabel: "標籤"
|
metadataLabel: "標籤"
|
||||||
metadataContent: "内容"
|
metadataContent: "内容"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
|
@ -4,7 +4,7 @@ export class instancePinnedPages1605585339718 implements MigrationInterface {
|
|||||||
name = 'instancePinnedPages1605585339718'
|
name = 'instancePinnedPages1605585339718'
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query(`ALTER TABLE "meta" ADD "pinnedPages" character varying(512) array NOT NULL DEFAULT '{"/announcements", "/featured", "/channels", "/pages", "/explore", "/games/reversi", "/about-misskey"}'::varchar[]`);
|
await queryRunner.query(`ALTER TABLE "meta" ADD "pinnedPages" character varying(512) array NOT NULL DEFAULT '{"/featured", "/channels", "/explore", "/pages", "/about-misskey"}'::varchar[]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
16
migration/1605965516823-instance-images.ts
Normal file
16
migration/1605965516823-instance-images.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class instanceImages1605965516823 implements MigrationInterface {
|
||||||
|
name = 'instanceImages1605965516823'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "backgroundImageUrl" character varying(512)`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" ADD "logoImageUrl" character varying(512)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "logoImageUrl"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "backgroundImageUrl"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
migration/1606191203881-no-crawle.ts
Normal file
16
migration/1606191203881-no-crawle.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class noCrawle1606191203881 implements MigrationInterface {
|
||||||
|
name = 'noCrawle1606191203881'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD "noCrawle" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user_profile"."noCrawle" IS 'Whether reject index by crawler.'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "user_profile"."noCrawle" IS 'Whether reject index by crawler.'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "noCrawle"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
package.json
11
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||||
"version": "12.59.0",
|
"version": "12.60.1",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -104,7 +104,7 @@
|
|||||||
"@types/websocket": "1.0.1",
|
"@types/websocket": "1.0.1",
|
||||||
"@types/ws": "7.2.7",
|
"@types/ws": "7.2.7",
|
||||||
"@typescript-eslint/parser": "4.6.1",
|
"@typescript-eslint/parser": "4.6.1",
|
||||||
"@vue/compiler-sfc": "3.0.2",
|
"@vue/compiler-sfc": "3.0.3",
|
||||||
"abort-controller": "3.0.0",
|
"abort-controller": "3.0.0",
|
||||||
"apexcharts": "3.22.1",
|
"apexcharts": "3.22.1",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
@ -239,20 +239,19 @@
|
|||||||
"url-loader": "4.1.1",
|
"url-loader": "4.1.1",
|
||||||
"uuid": "8.3.1",
|
"uuid": "8.3.1",
|
||||||
"v-debounce": "0.1.2",
|
"v-debounce": "0.1.2",
|
||||||
"vue": "3.0.2",
|
"vue": "3.0.3",
|
||||||
"vue-color": "2.7.1",
|
"vue-color": "2.7.1",
|
||||||
"vue-draggable-next": "1.0.8",
|
"vue-draggable-next": "1.0.8",
|
||||||
"vue-i18n": "9.0.0-beta.7",
|
"vue-i18n": "9.0.0-beta.7",
|
||||||
"vue-json-pretty": "1.7.1",
|
"vue-json-pretty": "1.7.1",
|
||||||
"vue-loader": "16.0.0-beta.8",
|
"vue-loader": "16.0.0",
|
||||||
"vue-prism-editor": "1.2.2",
|
"vue-prism-editor": "1.2.2",
|
||||||
"vue-router": "4.0.0-rc.2",
|
"vue-router": "4.0.0-rc.2",
|
||||||
"vue-style-loader": "4.1.2",
|
"vue-style-loader": "4.1.2",
|
||||||
"vue-template-compiler": "2.6.12",
|
|
||||||
"vuex": "4.0.0-rc.1",
|
"vuex": "4.0.0-rc.1",
|
||||||
"vuex-persistedstate": "3.1.0",
|
"vuex-persistedstate": "3.1.0",
|
||||||
"web-push": "3.4.4",
|
"web-push": "3.4.4",
|
||||||
"webpack": "5.5.0",
|
"webpack": "5.8.0",
|
||||||
"webpack-cli": "4.2.0",
|
"webpack-cli": "4.2.0",
|
||||||
"websocket": "1.0.32",
|
"websocket": "1.0.32",
|
||||||
"ws": "7.3.1",
|
"ws": "7.3.1",
|
||||||
|
5
src/client/@types/vue.d.ts
vendored
5
src/client/@types/vue.d.ts
vendored
@ -1,4 +1,5 @@
|
|||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import Vue from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
export default Vue;
|
const component: ReturnType<typeof defineComponent>;
|
||||||
|
export default component;
|
||||||
}
|
}
|
||||||
|
BIN
src/client/assets/sounds/syuilo/kick.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/kick.mp3
Normal file
Binary file not shown.
BIN
src/client/assets/sounds/syuilo/snare.mp3
Normal file
BIN
src/client/assets/sounds/syuilo/snare.mp3
Normal file
Binary file not shown.
34
src/client/cold-storage.ts
Normal file
34
src/client/cold-storage.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 常にメモリにロードしておく必要がないような設定情報を保管するストレージ
|
||||||
|
|
||||||
|
const PREFIX = 'miux:';
|
||||||
|
|
||||||
|
export const defaultDeviceSettings = {
|
||||||
|
sound_masterVolume: 0.3,
|
||||||
|
sound_note: { type: 'syuilo/down', volume: 1 },
|
||||||
|
sound_noteMy: { type: 'syuilo/up', volume: 1 },
|
||||||
|
sound_notification: { type: 'syuilo/pope2', volume: 1 },
|
||||||
|
sound_chat: { type: 'syuilo/pope1', volume: 1 },
|
||||||
|
sound_chatBg: { type: 'syuilo/waon', volume: 1 },
|
||||||
|
sound_antenna: { type: 'syuilo/triple', volume: 1 },
|
||||||
|
sound_channel: { type: 'syuilo/square-pico', volume: 1 },
|
||||||
|
sound_reversiPutBlack: { type: 'syuilo/kick', volume: 0.3 },
|
||||||
|
sound_reversiPutWhite: { type: 'syuilo/snare', volume: 0.3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
export const device = {
|
||||||
|
get<T extends keyof typeof defaultDeviceSettings>(key: T): typeof defaultDeviceSettings[T] {
|
||||||
|
// TODO: indexedDBにする
|
||||||
|
// ただしその際はnullチェックではなくキー存在チェックにしないとダメ
|
||||||
|
// (indexedDBはnullを保存できるため、ユーザーが意図してnullを格納した可能性がある)
|
||||||
|
const value = localStorage.getItem(PREFIX + key);
|
||||||
|
if (value == null) {
|
||||||
|
return defaultDeviceSettings[key];
|
||||||
|
} else {
|
||||||
|
return JSON.parse(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set(key: keyof typeof defaultDeviceSettings, value: any): any {
|
||||||
|
localStorage.setItem(PREFIX + key, JSON.stringify(value));
|
||||||
|
},
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<XModalWindow ref="dialog"
|
<XModalWindow ref="dialog"
|
||||||
:width="400"
|
:width="450"
|
||||||
:can-close="false"
|
:can-close="false"
|
||||||
:with-ok-button="true"
|
:with-ok-button="true"
|
||||||
:ok-button-disabled="false"
|
:ok-button-disabled="false"
|
||||||
@ -12,42 +12,61 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</template>
|
</template>
|
||||||
<div class="xkpnjxcv _section">
|
<FormBase class="xkpnjxcv">
|
||||||
<label v-for="item in Object.keys(form).filter(item => !form[item].hidden)" :key="item">
|
<template v-for="item in Object.keys(form).filter(item => !form[item].hidden)">
|
||||||
<MkInput v-if="form[item].type === 'number'" v-model:value="values[item]" type="number" :step="form[item].step || 1">
|
<FormInput v-if="form[item].type === 'number'" v-model:value="values[item]" type="number" :step="form[item].step || 1">
|
||||||
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
||||||
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
</MkInput>
|
</FormInput>
|
||||||
<MkInput v-else-if="form[item].type === 'string' && !form[item].multiline" v-model:value="values[item]" type="text">
|
<FormInput v-else-if="form[item].type === 'string' && !form[item].multiline" v-model:value="values[item]" type="text">
|
||||||
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
||||||
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
</MkInput>
|
</FormInput>
|
||||||
<MkTextarea v-else-if="form[item].type === 'string' && form[item].multiline" v-model:value="values[item]">
|
<FormTextarea v-else-if="form[item].type === 'string' && form[item].multiline" v-model:value="values[item]">
|
||||||
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
<span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span>
|
||||||
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
</MkTextarea>
|
</FormTextarea>
|
||||||
<MkSwitch v-else-if="form[item].type === 'boolean'" v-model:value="values[item]">
|
<FormSwitch v-else-if="form[item].type === 'boolean'" v-model:value="values[item]">
|
||||||
<span v-text="form[item].label || item"></span>
|
<span v-text="form[item].label || item"></span>
|
||||||
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
</MkSwitch>
|
</FormSwitch>
|
||||||
</label>
|
<FormSelect v-else-if="form[item].type === 'enum'" v-model:value="values[item]">
|
||||||
</div>
|
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $t('optional') }})</span></template>
|
||||||
|
<option v-for="item in form[item].enum" :value="item.value" :key="item.value">{{ item.label }}</option>
|
||||||
|
</FormSelect>
|
||||||
|
<FormRange v-else-if="form[item].type === 'range'" v-model:value="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"> ({{ $t('optional') }})</span></template>
|
||||||
|
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||||
|
</FormRange>
|
||||||
|
<FormButton v-else-if="form[item].type === 'button'" @click="form[item].action($event, values)">
|
||||||
|
<span v-text="form[item].content || item"></span>
|
||||||
|
</FormButton>
|
||||||
|
</template>
|
||||||
|
</FormBase>
|
||||||
</XModalWindow>
|
</XModalWindow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XModalWindow from '@/components/ui/modal-window.vue';
|
import XModalWindow from '@/components/ui/modal-window.vue';
|
||||||
import MkInput from './ui/input.vue';
|
import FormBase from './form/base.vue';
|
||||||
import MkTextarea from './ui/textarea.vue';
|
import FormInput from './form/input.vue';
|
||||||
import MkSwitch from './ui/switch.vue';
|
import FormTextarea from './form/textarea.vue';
|
||||||
|
import FormSwitch from './form/switch.vue';
|
||||||
|
import FormSelect from './form/select.vue';
|
||||||
|
import FormRange from './form/range.vue';
|
||||||
|
import FormButton from './form/button.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XModalWindow,
|
XModalWindow,
|
||||||
MkInput,
|
FormBase,
|
||||||
MkTextarea,
|
FormInput,
|
||||||
MkSwitch,
|
FormTextarea,
|
||||||
|
FormSwitch,
|
||||||
|
FormSelect,
|
||||||
|
FormRange,
|
||||||
|
FormButton,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -95,12 +114,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.xkpnjxcv {
|
.xkpnjxcv {
|
||||||
> label {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
&:not(:last-child) {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
56
src/client/components/form/base.vue
Normal file
56
src/client/components/form/base.vue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<div class="rbusrurv" :class="{ wide: forceWide }" v-size="{ max: [400] }">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
forceWide: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.rbusrurv {
|
||||||
|
line-height: 1.4em;
|
||||||
|
background: var(--bg);
|
||||||
|
padding: 32px;
|
||||||
|
|
||||||
|
&:not(.wide).max-width_400px {
|
||||||
|
padding: 32px 0;
|
||||||
|
|
||||||
|
> ::v-deep(*) {
|
||||||
|
._formPanel {
|
||||||
|
border: solid 0.5px var(--divider);
|
||||||
|
border-radius: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
._form_group {
|
||||||
|
> * {
|
||||||
|
&:not(:first-child) {
|
||||||
|
&._formPanel, ._formPanel {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
&._formPanel, ._formPanel {
|
||||||
|
border-bottom: solid 0.5px var(--divider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
81
src/client/components/form/button.vue
Normal file
81
src/client/components/form/button.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div class="yzpgjkxe _formItem">
|
||||||
|
<div class="_formLabel"><slot name="label"></slot></div>
|
||||||
|
<button class="main _button _formPanel _formClickable" :class="{ center, primary, danger }">
|
||||||
|
<slot></slot>
|
||||||
|
<div class="suffix">
|
||||||
|
<slot name="suffix"></slot>
|
||||||
|
<div class="icon">
|
||||||
|
<slot name="suffixIcon"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
primary: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
danger: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
center: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.yzpgjkxe {
|
||||||
|
> .main {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 14px 16px;
|
||||||
|
text-align: left;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.center {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: #ff2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .suffix {
|
||||||
|
display: inline-flex;
|
||||||
|
margin-left: auto;
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
34
src/client/components/form/form.scss
Normal file
34
src/client/components/form/form.scss
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
._formPanel {
|
||||||
|
background: var(--panel);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
|
||||||
|
&._formClickable {
|
||||||
|
&:hover {
|
||||||
|
background: var(--panelHighlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
._formLabel {
|
||||||
|
font-size: 80%;
|
||||||
|
padding: 0 16px 8px 16px;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
._formCaption {
|
||||||
|
font-size: 80%;
|
||||||
|
padding: 8px 16px 0 16px;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
._formItem {
|
||||||
|
& + ._formItem {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
}
|
42
src/client/components/form/group.vue
Normal file
42
src/client/components/form/group.vue
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vrtktovg _formItem" v-size="{ max: [500] }">
|
||||||
|
<div class="_formLabel"><slot name="label"></slot></div>
|
||||||
|
<div class="main _form_group">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
<div class="_formCaption"><slot name="caption"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.vrtktovg {
|
||||||
|
> .main {
|
||||||
|
> ::v-deep(*) {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
&._formPanel, ._formPanel {
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
&._formPanel, ._formPanel {
|
||||||
|
border-bottom: solid 0.5px var(--divider);
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
306
src/client/components/form/input.vue
Normal file
306
src/client/components/form/input.vue
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ztzhwixg _formItem" :class="{ inline, disabled }">
|
||||||
|
<div class="_formLabel"><slot></slot></div>
|
||||||
|
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||||
|
<div class="input _formPanel">
|
||||||
|
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||||
|
<input v-if="debounce" ref="inputEl"
|
||||||
|
v-debounce="500"
|
||||||
|
:type="type"
|
||||||
|
v-model.lazy="v"
|
||||||
|
:disabled="disabled"
|
||||||
|
:required="required"
|
||||||
|
:readonly="readonly"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:pattern="pattern"
|
||||||
|
:autocomplete="autocomplete"
|
||||||
|
:spellcheck="spellcheck"
|
||||||
|
:step="step"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
@keydown="onKeydown($event)"
|
||||||
|
@input="onInput"
|
||||||
|
:list="id"
|
||||||
|
>
|
||||||
|
<input v-else ref="inputEl"
|
||||||
|
:type="type"
|
||||||
|
v-model="v"
|
||||||
|
:disabled="disabled"
|
||||||
|
:required="required"
|
||||||
|
:readonly="readonly"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:pattern="pattern"
|
||||||
|
:autocomplete="autocomplete"
|
||||||
|
:spellcheck="spellcheck"
|
||||||
|
:step="step"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
@keydown="onKeydown($event)"
|
||||||
|
@input="onInput"
|
||||||
|
:list="id"
|
||||||
|
>
|
||||||
|
<datalist :id="id" v-if="datalist">
|
||||||
|
<option v-for="data in datalist" :value="data"/>
|
||||||
|
</datalist>
|
||||||
|
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
|
||||||
|
</div>
|
||||||
|
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $t('save') }}</button>
|
||||||
|
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
||||||
|
import debounce from 'v-debounce';
|
||||||
|
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
directives: {
|
||||||
|
debounce
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
autofocus: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
autocomplete: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
spellcheck: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
debounce: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
datalist: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
inline: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
save: {
|
||||||
|
type: Function,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['change', 'keydown', 'enter'],
|
||||||
|
setup(props, context) {
|
||||||
|
const { value, type, autofocus } = toRefs(props);
|
||||||
|
const v = ref(value.value);
|
||||||
|
const id = Math.random().toString(); // TODO: uuid?
|
||||||
|
const focused = ref(false);
|
||||||
|
const changed = ref(false);
|
||||||
|
const invalid = ref(false);
|
||||||
|
const filled = computed(() => v.value !== '' && v.value != null);
|
||||||
|
const inputEl = ref(null);
|
||||||
|
const prefixEl = ref(null);
|
||||||
|
const suffixEl = ref(null);
|
||||||
|
|
||||||
|
const focus = () => inputEl.value.focus();
|
||||||
|
const onInput = (ev) => {
|
||||||
|
changed.value = true;
|
||||||
|
context.emit('change', ev);
|
||||||
|
};
|
||||||
|
const onKeydown = (ev: KeyboardEvent) => {
|
||||||
|
context.emit('keydown', ev);
|
||||||
|
|
||||||
|
if (ev.code === 'Enter') {
|
||||||
|
context.emit('enter');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(value, newValue => {
|
||||||
|
v.value = newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(v, newValue => {
|
||||||
|
if (type?.value === 'number') {
|
||||||
|
context.emit('update:value', parseFloat(newValue));
|
||||||
|
} else {
|
||||||
|
context.emit('update:value', newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid.value = inputEl.value.validity.badInput;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (autofocus.value) {
|
||||||
|
focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// このコンポーネントが作成された時、非表示状態である場合がある
|
||||||
|
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
|
||||||
|
const clock = setInterval(() => {
|
||||||
|
if (prefixEl.value) {
|
||||||
|
if (prefixEl.value.offsetWidth) {
|
||||||
|
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (suffixEl.value) {
|
||||||
|
if (suffixEl.value.offsetWidth) {
|
||||||
|
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(clock);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
v,
|
||||||
|
focused,
|
||||||
|
invalid,
|
||||||
|
changed,
|
||||||
|
filled,
|
||||||
|
inputEl,
|
||||||
|
prefixEl,
|
||||||
|
suffixEl,
|
||||||
|
focus,
|
||||||
|
onInput,
|
||||||
|
onKeydown,
|
||||||
|
faExclamationCircle,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ztzhwixg {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 24px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 32px;
|
||||||
|
|
||||||
|
&:not(:empty) + .input {
|
||||||
|
margin-left: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .input {
|
||||||
|
$height: 52px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
display: block;
|
||||||
|
height: $height;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
font: inherit;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: $height;
|
||||||
|
color: var(--inputText);
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&[type='file'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .prefix,
|
||||||
|
> .suffix {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: $height;
|
||||||
|
color: var(--inputLabel);
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 16px;
|
||||||
|
max-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .prefix {
|
||||||
|
left: 0;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .suffix {
|
||||||
|
right: 0;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .save {
|
||||||
|
margin: 6px 0 0 0;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.inline {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
&, * {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
30
src/client/components/form/key-value-view.vue
Normal file
30
src/client/components/form/key-value-view.vue
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div class="_formItem">
|
||||||
|
<div class="_formPanel anocepby">
|
||||||
|
<span class="key"><slot name="key"></slot></span>
|
||||||
|
<span class="value"><slot name="value"></slot></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.anocepby {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14px 16px;
|
||||||
|
|
||||||
|
> .value {
|
||||||
|
margin-left: auto;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
90
src/client/components/form/link.vue
Normal file
90
src/client/components/form/link.vue
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div class="qmfkfnzi _formItem">
|
||||||
|
<a class="main _button _formPanel _formClickable" :href="to" target="_blank" v-if="external">
|
||||||
|
<span class="icon"><slot name="icon"></slot></span>
|
||||||
|
<span class="text"><slot></slot></span>
|
||||||
|
<Fa :icon="faExternalLinkAlt" class="right"/>
|
||||||
|
</a>
|
||||||
|
<MkA class="main _button _formPanel _formClickable" :class="{ active }" :to="to" v-else>
|
||||||
|
<span class="icon"><slot name="icon"></slot></span>
|
||||||
|
<span class="text"><slot></slot></span>
|
||||||
|
<Fa :icon="faChevronRight" class="right"/>
|
||||||
|
</MkA>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faChevronRight, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
to: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
external: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faChevronRight, faExternalLinkAlt
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.qmfkfnzi {
|
||||||
|
> .main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 14px 16px 14px 14px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
width: 32px;
|
||||||
|
margin-right: 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
& + .text {
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .right {
|
||||||
|
margin-left: auto;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
42
src/client/components/form/pagination.vue
Normal file
42
src/client/components/form/pagination.vue
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<FormGroup class="uljviswt _formItem">
|
||||||
|
<template #label><slot name="label"></slot></template>
|
||||||
|
<slot :items="items"></slot>
|
||||||
|
<div class="empty" v-if="empty" key="_empty_">
|
||||||
|
<slot name="empty"></slot>
|
||||||
|
</div>
|
||||||
|
<FormButton v-show="more" class="button" @click="fetchMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary>
|
||||||
|
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
|
||||||
|
<template v-if="moreFetching"><MkLoading inline/></template>
|
||||||
|
</FormButton>
|
||||||
|
</FormGroup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import FormButton from './button.vue';
|
||||||
|
import FormGroup from './group.vue';
|
||||||
|
import paging from '@/scripts/paging';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormButton,
|
||||||
|
FormGroup,
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [
|
||||||
|
paging({}),
|
||||||
|
],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
pagination: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.uljviswt {
|
||||||
|
}
|
||||||
|
</style>
|
106
src/client/components/form/radios.vue
Normal file
106
src/client/components/form/radios.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, h } from 'vue';
|
||||||
|
import MkRadio from '@/components/ui/radio.vue';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkRadio
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: this.modelValue,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value() {
|
||||||
|
this.$emit('update:modelValue', this.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const label = this.$slots.desc();
|
||||||
|
const options = this.$slots.default();
|
||||||
|
|
||||||
|
return h('div', {
|
||||||
|
class: 'cnklmpwm _formItem'
|
||||||
|
}, [
|
||||||
|
h('div', {
|
||||||
|
class: '_formLabel',
|
||||||
|
}, label),
|
||||||
|
...options.map(option => h('button', {
|
||||||
|
class: '_button _formPanel _formClickable',
|
||||||
|
key: option.props.value,
|
||||||
|
onClick: () => this.value = option.props.value,
|
||||||
|
}, [h('span', {
|
||||||
|
class: ['check', { checked: this.value === option.props.value }],
|
||||||
|
}), option.children]))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.cnklmpwm {
|
||||||
|
> button {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 14px 18px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
border-top: none !important;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
border-bottom: solid 0.5px var(--divider);
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .check {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: bottom;
|
||||||
|
position: relative;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 8px;
|
||||||
|
background: none;
|
||||||
|
border: 2px solid var(--inputBorder);
|
||||||
|
border-radius: 100%;
|
||||||
|
transition: inherit;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
left: 3px;
|
||||||
|
border-radius: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: .4s cubic-bezier(.25,.8,.25,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
border-color: var(--accent);
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
background-color: var(--accent);
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
122
src/client/components/form/range.vue
Normal file
122
src/client/components/form/range.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ifitouly _formItem" :class="{ focused, disabled }">
|
||||||
|
<div class="_formLabel"><slot name="label"></slot></div>
|
||||||
|
<div class="_formPanel main">
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
ref="input"
|
||||||
|
v-model="v"
|
||||||
|
:disabled="disabled"
|
||||||
|
:min="min"
|
||||||
|
:max="max"
|
||||||
|
:step="step"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
@input="$emit('update:value', $event.target.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="_formCaption"><slot name="caption"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
v: this.value,
|
||||||
|
focused: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(v) {
|
||||||
|
this.v = parseFloat(v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ifitouly {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .main {
|
||||||
|
padding: 24px 16px;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
display: block;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background: var(--X10);
|
||||||
|
height: 4px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
outline: 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: block;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: none;
|
||||||
|
background: var(--accent);
|
||||||
|
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: block;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: none;
|
||||||
|
background: var(--accent);
|
||||||
|
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
147
src/client/components/form/select.vue
Normal file
147
src/client/components/form/select.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<div class="yrtfrpux _formItem" :class="{ disabled, inline }">
|
||||||
|
<div class="_formLabel"><slot name="label"></slot></div>
|
||||||
|
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||||
|
<div class="input _formPanel _formClickable" @click="focus">
|
||||||
|
<div class="prefix" ref="prefix"><slot name="prefix"></slot></div>
|
||||||
|
<select ref="input"
|
||||||
|
v-model="v"
|
||||||
|
:required="required"
|
||||||
|
:disabled="disabled"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</select>
|
||||||
|
<div class="suffix">
|
||||||
|
<Fa :icon="faChevronDown"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="_formCaption"><slot name="caption"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
inline: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faChevronDown,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
v: {
|
||||||
|
get() {
|
||||||
|
return this.value;
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
this.$emit('update:value', v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
focus() {
|
||||||
|
this.$refs.input.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.yrtfrpux {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 24px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 32px;
|
||||||
|
|
||||||
|
&:not(:empty) + .input {
|
||||||
|
margin-left: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .input {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> select {
|
||||||
|
display: block;
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 16px;
|
||||||
|
font: inherit;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 1em;
|
||||||
|
height: 52px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
color: var(--fg);
|
||||||
|
|
||||||
|
option,
|
||||||
|
optgroup {
|
||||||
|
color: var(--fg);
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .prefix,
|
||||||
|
> .suffix {
|
||||||
|
display: block;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 32px;
|
||||||
|
color: var(--inputLabel);
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
display: block;
|
||||||
|
min-width: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .prefix {
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .suffix {
|
||||||
|
padding: 0 16px 0 0;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
132
src/client/components/form/switch.vue
Normal file
132
src/client/components/form/switch.vue
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ijnpvmgr _formItem">
|
||||||
|
<div class="main _formPanel _formClickable"
|
||||||
|
:class="{ disabled, checked }"
|
||||||
|
:aria-checked="checked"
|
||||||
|
:aria-disabled="disabled"
|
||||||
|
@click.prevent="toggle"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
ref="input"
|
||||||
|
:disabled="disabled"
|
||||||
|
@keydown.enter="toggle"
|
||||||
|
>
|
||||||
|
<span class="button">
|
||||||
|
<span></span>
|
||||||
|
</span>
|
||||||
|
<span class="label">
|
||||||
|
<span><slot></slot></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
checked(): boolean {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggle() {
|
||||||
|
if (this.disabled) return;
|
||||||
|
this.$emit('update:value', !this.checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ijnpvmgr {
|
||||||
|
> .main {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
padding: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
> .button {
|
||||||
|
background-color: var(--X10);
|
||||||
|
border-color: var(--X10);
|
||||||
|
|
||||||
|
> * {
|
||||||
|
background-color: var(--accent);
|
||||||
|
transform: translateX(14px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> input {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .button {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 3px 0 0 0;
|
||||||
|
width: 34px;
|
||||||
|
height: 14px;
|
||||||
|
background: var(--X6);
|
||||||
|
outline: none;
|
||||||
|
border-radius: 14px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
position: absolute;
|
||||||
|
top: -3px;
|
||||||
|
left: 0;
|
||||||
|
border-radius: 100%;
|
||||||
|
transition: background-color 0.3s, transform 0.3s;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 2px 1px -1px rgba(#000, 0.2), 0 1px 1px 0 rgba(#000, 0.14), 0 1px 3px 0 rgba(#000, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .label {
|
||||||
|
margin-left: 12px;
|
||||||
|
display: block;
|
||||||
|
transition: inherit;
|
||||||
|
color: var(--fg);
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: block;
|
||||||
|
line-height: 20px;
|
||||||
|
transition: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
136
src/client/components/form/textarea.vue
Normal file
136
src/client/components/form/textarea.vue
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="rivhosbp _formItem" :class="{ tall, pre }">
|
||||||
|
<div class="_formLabel"><slot></slot></div>
|
||||||
|
<div class="input _formPanel">
|
||||||
|
<textarea ref="input" :class="{ code, _monospace: code }"
|
||||||
|
:value="value"
|
||||||
|
:required="required"
|
||||||
|
:readonly="readonly"
|
||||||
|
:pattern="pattern"
|
||||||
|
:autocomplete="autocomplete"
|
||||||
|
:spellcheck="!code"
|
||||||
|
@input="onInput"
|
||||||
|
@focus="focused = true"
|
||||||
|
@blur="focused = false"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $t('save') }}</button>
|
||||||
|
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import './form.scss';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
autocomplete: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
tall: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
pre: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
save: {
|
||||||
|
type: Function,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
changed: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
focus() {
|
||||||
|
this.$refs.input.focus();
|
||||||
|
},
|
||||||
|
onInput(ev) {
|
||||||
|
this.changed = true;
|
||||||
|
this.$emit('update:value', ev.target.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.rivhosbp {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .input {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> textarea {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
min-height: 130px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font: inherit;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 1em;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
color: var(--fg);
|
||||||
|
|
||||||
|
&.code {
|
||||||
|
tab-size: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .save {
|
||||||
|
margin: 6px 0 0 0;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tall {
|
||||||
|
> .input {
|
||||||
|
> textarea {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pre {
|
||||||
|
> .input {
|
||||||
|
> textarea {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
36
src/client/components/form/tuple.vue
Normal file
36
src/client/components/form/tuple.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wthhikgt _formItem" v-size="{ max: [500] }">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wthhikgt {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> ::v-deep(*) {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.max-width_500px {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
> ::v-deep(*) {
|
||||||
|
margin: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -68,7 +68,7 @@ export default defineComponent({
|
|||||||
created() {
|
created() {
|
||||||
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
||||||
this.$watch('image', () => {
|
this.$watch('image', () => {
|
||||||
this.hide = this.image.isSensitive && !this.$store.state.device.alwaysShowNsfw;
|
this.hide = (this.$store.state.device.nsfw === 'force') ? true : this.image.isSensitive && (this.$store.state.device.nsfw !== 'ignore');
|
||||||
if (this.image.blurhash) {
|
if (this.image.blurhash) {
|
||||||
this.color = extractAvgColorFromBlurhash(this.image.blurhash);
|
this.color = extractAvgColorFromBlurhash(this.image.blurhash);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.hide = this.video.isSensitive && !this.$store.state.device.alwaysShowNsfw;
|
this.hide = (this.$store.state.device.nsfw === 'force') ? true : this.video.isSensitive && (this.$store.state.device.nsfw !== 'ignore');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
<option value="res">Response</option>
|
<option value="res">Response</option>
|
||||||
</MkTab>
|
</MkTab>
|
||||||
|
|
||||||
<code v-if="tab === 'req'">{{ reqStr }}</code>
|
<code v-if="tab === 'req'" class="_monospace">{{ reqStr }}</code>
|
||||||
<code v-if="tab === 'res'">{{ resStr }}</code>
|
<code v-if="tab === 'res'" class="_monospace">{{ resStr }}</code>
|
||||||
</div>
|
</div>
|
||||||
</XWindow>
|
</XWindow>
|
||||||
</template>
|
</template>
|
||||||
@ -67,7 +67,6 @@ export default defineComponent({
|
|||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
tab-size: 2;
|
tab-size: 2;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<Fa :icon="faTerminal" style="margin-right: 0.5em;"/>Task Manager
|
<Fa :icon="faTerminal" style="margin-right: 0.5em;"/>Task Manager
|
||||||
</template>
|
</template>
|
||||||
<div class="qljqmnzj">
|
<div class="qljqmnzj _monospace">
|
||||||
<MkTab v-model:value="tab" style="border-bottom: solid 1px var(--divider);">
|
<MkTab v-model:value="tab" style="border-bottom: solid 1px var(--divider);">
|
||||||
<option value="windows">Windows</option>
|
<option value="windows">Windows</option>
|
||||||
<option value="stream">Stream</option>
|
<option value="stream">Stream</option>
|
||||||
@ -150,7 +150,6 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
|
||||||
|
|
||||||
> .content {
|
> .content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XNotes from './notes.vue';
|
import XNotes from './notes.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import * as sound from '@/scripts/sound';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -65,7 +66,7 @@ export default defineComponent({
|
|||||||
this.$emit('note');
|
this.$emit('note');
|
||||||
|
|
||||||
if (this.sound) {
|
if (this.sound) {
|
||||||
os.sound(note.userId === this.$store.state.i.id ? 'noteMy' : 'note');
|
sound.play(note.userId === this.$store.state.i.id ? 'noteMy' : 'note');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: showing ? 'auto' : 'none' }">
|
<div class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: showing ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
|
||||||
<transition :name="$store.state.device.animation ? 'modal-bg' : ''" appear>
|
<transition :name="$store.state.device.animation ? 'modal-bg' : ''" appear>
|
||||||
<div class="bg _modalBg" v-if="showing" @click="onBgClick"></div>
|
<div class="bg _modalBg" v-if="showing" @click="onBgClick"></div>
|
||||||
</transition>
|
</transition>
|
||||||
@ -150,7 +150,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style vars="{ transformOrigin }">
|
<style>
|
||||||
.modal-popup-content-enter-active, .modal-popup-content-leave-active,
|
.modal-popup-content-enter-active, .modal-popup-content-leave-active,
|
||||||
.modal-content-enter-from, .modal-content-leave-to {
|
.modal-content-enter-from, .modal-content-leave-to {
|
||||||
transform-origin: var(--transformOrigin);
|
transform-origin: var(--transformOrigin);
|
||||||
|
@ -7,9 +7,6 @@ export default defineComponent({
|
|||||||
MkRadio
|
MkRadio
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
defs: {
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
modelValue: {
|
modelValue: {
|
||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="timctyfi" :class="{ focused, disabled }">
|
<div class="timctyfi" :class="{ focused, disabled }">
|
||||||
<div class="icon"><slot name="icon"></slot></div>
|
<div class="icon"><slot name="icon"></slot></div>
|
||||||
<span class="title"><slot name="title"></slot></span>
|
<span class="label"><slot name="label"></slot></span>
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
ref="input"
|
ref="input"
|
||||||
@ -19,7 +19,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';import * as os from '@/os';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
<span></span>
|
<span></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="label">
|
<span class="label">
|
||||||
<span :aria-hidden="!checked"><slot></slot></span>
|
<span><slot></slot></span>
|
||||||
<p :aria-hidden="!checked">
|
<p><slot name="desc"></slot></p>
|
||||||
<slot name="desc"></slot>
|
|
||||||
</p>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="adhpbeos" :class="{ focused, filled, tall, pre }">
|
<div class="adhpbeos" :class="{ focused, filled, tall, pre }">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<span class="label" ref="label"><slot></slot></span>
|
<span class="label" ref="label"><slot></slot></span>
|
||||||
<textarea ref="input" :class="{ code }"
|
<textarea ref="input" :class="{ code, _monospace: code }"
|
||||||
:value="value"
|
:value="value"
|
||||||
:required="required"
|
:required="required"
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
@ -166,7 +166,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
&.code {
|
&.code {
|
||||||
tab-size: 2;
|
tab-size: 2;
|
||||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ import { router } from './router';
|
|||||||
import { applyTheme } from '@/scripts/theme';
|
import { applyTheme } from '@/scripts/theme';
|
||||||
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
||||||
import { i18n, lang } from './i18n';
|
import { i18n, lang } from './i18n';
|
||||||
import { stream, sound, isMobile, dialog } from '@/os';
|
import { stream, isMobile, dialog } from '@/os';
|
||||||
|
import * as sound from './scripts/sound';
|
||||||
|
|
||||||
console.info(`Misskey v${version}`);
|
console.info(`Misskey v${version}`);
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ if (_DEV_) {
|
|||||||
document.addEventListener('touchend', () => {}, { passive: true });
|
document.addEventListener('touchend', () => {}, { passive: true });
|
||||||
|
|
||||||
if (localStorage.getItem('theme') == null) {
|
if (localStorage.getItem('theme') == null) {
|
||||||
applyTheme(require('@/themes/l-white.json5'));
|
applyTheme(require('@/themes/l-light.json5'));
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
||||||
@ -307,7 +308,7 @@ if (store.getters.isSignedIn) {
|
|||||||
hasUnreadMessagingMessage: true
|
hasUnreadMessagingMessage: true
|
||||||
});
|
});
|
||||||
|
|
||||||
sound('chatBg');
|
sound.play('chatBg');
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllAntennas', () => {
|
main.on('readAllAntennas', () => {
|
||||||
@ -321,7 +322,7 @@ if (store.getters.isSignedIn) {
|
|||||||
hasUnreadAntenna: true
|
hasUnreadAntenna: true
|
||||||
});
|
});
|
||||||
|
|
||||||
sound('antenna');
|
sound.play('antenna');
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllAnnouncements', () => {
|
main.on('readAllAnnouncements', () => {
|
||||||
@ -341,7 +342,7 @@ if (store.getters.isSignedIn) {
|
|||||||
hasUnreadChannel: true
|
hasUnreadChannel: true
|
||||||
});
|
});
|
||||||
|
|
||||||
sound('channel');
|
sound.play('channel');
|
||||||
});
|
});
|
||||||
|
|
||||||
main.on('readAllAnnouncements', () => {
|
main.on('readAllAnnouncements', () => {
|
||||||
|
@ -6,6 +6,7 @@ import { apiUrl, debug } from '@/config';
|
|||||||
import MkPostFormDialog from '@/components/post-form-dialog.vue';
|
import MkPostFormDialog from '@/components/post-form-dialog.vue';
|
||||||
import MkWaitingDialog from '@/components/waiting-dialog.vue';
|
import MkWaitingDialog from '@/components/waiting-dialog.vue';
|
||||||
import { resolve } from '@/router';
|
import { resolve } from '@/router';
|
||||||
|
import { device } from './cold-storage';
|
||||||
|
|
||||||
const ua = navigator.userAgent.toLowerCase();
|
const ua = navigator.userAgent.toLowerCase();
|
||||||
export const isMobile = /mobile|iphone|ipad|android/.test(ua);
|
export const isMobile = /mobile|iphone|ipad|android/.test(ua);
|
||||||
@ -344,15 +345,6 @@ export function post(props: Record<string, any>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sound(type: string) {
|
|
||||||
if (store.state.device.sfxVolume === 0) return;
|
|
||||||
const sound = store.state.device['sfx' + type.substr(0, 1).toUpperCase() + type.substr(1)];
|
|
||||||
if (sound == null) return;
|
|
||||||
const audio = new Audio(`/assets/sounds/${sound}.mp3`);
|
|
||||||
audio.volume = store.state.device.sfxVolume;
|
|
||||||
audio.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
export const deckGlobalEvents = new EventEmitter();
|
export const deckGlobalEvents = new EventEmitter();
|
||||||
|
|
||||||
export const uploads = ref([]);
|
export const uploads = ref([]);
|
||||||
|
@ -1,87 +1,97 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="znqjceqz">
|
<FormBase class="znqjceqz">
|
||||||
<section class="_section">
|
<section class="_formItem">
|
||||||
<div class="_content" style="text-align: center;">
|
<div class="_formPanel" style="text-align: center; padding: 16px;">
|
||||||
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;"/>
|
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;"/>
|
||||||
<div style="margin-top: 0.75em;">Misskey</div>
|
<div style="margin-top: 0.75em;">Misskey</div>
|
||||||
<div style="opacity: 0.5;">v{{ version }}</div>
|
<div style="opacity: 0.5;">v{{ version }}</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="_section">
|
<section class="_formItem" style="text-align: center;">
|
||||||
<div class="_content">
|
{{ $t('_aboutMisskey.about') }}
|
||||||
<div style="text-align: center;">{{ $t('aboutMisskeyText') }}</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
<section class="_section">
|
<FormGroup>
|
||||||
<div class="_content" style="text-align: center;">
|
<FormLink to="https://github.com/syuilo/misskey" external><template #icon><Fa :icon="faCode"/></template>{{ $t('_aboutMisskey.source') }}</FormLink>
|
||||||
<div>📦 {{ $t('misskeySource') }}</div>
|
<FormLink to="https://crowdin.com/project/misskey" external><template #icon><Fa :icon="faLanguage"/></template>{{ $t('_aboutMisskey.translation') }}</FormLink>
|
||||||
<MkUrl url="https://github.com/syuilo/misskey"/>
|
<FormLink to="https://www.patreon.com/syuilo" external><template #icon><Fa :icon="faHandHoldingMedical"/></template>{{ $t('_aboutMisskey.donate') }}</FormLink>
|
||||||
<div style="margin-top: 1em;">🌏 {{ $t('misskeyTranslation') }}</div>
|
</FormGroup>
|
||||||
<MkUrl url="https://crowdin.com/project/misskey"/>
|
<FormGroup>
|
||||||
<div style="margin-top: 1em;">💴 {{ $t('misskeyDonate') }}</div>
|
<template #label>{{ $t('_aboutMisskey.contributors') }}</template>
|
||||||
<MkUrl url="https://www.patreon.com/syuilo"/>
|
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
|
||||||
</div>
|
<FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
|
||||||
</section>
|
<FormLink to="https://github.com/mei23" external>@mei23</FormLink>
|
||||||
<section class="_section">
|
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
|
||||||
<div class="_content" style="text-align: center;">
|
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
|
||||||
<div>🛠️ {{ $t('misskeyMembers') }}</div>
|
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
|
||||||
<ul class="members" style="list-style: none; padding: 0; margin: 1em 0 0 0;">
|
<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
|
||||||
<li><MkLink url="https://github.com/syuilo" class="at">@syuilo</MkLink></li>
|
<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
|
||||||
<li><MkLink url="https://github.com/AyaMorisawa" class="at">@AyaMorisawa</MkLink></li>
|
<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
|
||||||
<li><MkLink url="https://github.com/mei23" class="at">@mei23</MkLink></li>
|
</FormGroup>
|
||||||
<li><MkLink url="https://github.com/acid-chicken" class="at">@acid-chicken</MkLink></li>
|
<FormGroup>
|
||||||
<li><MkLink url="https://github.com/tamaina" class="at">@tamaina</MkLink></li>
|
<template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
|
||||||
<li><MkLink url="https://github.com/rinsuki" class="at">@rinsuki</MkLink></li>
|
<FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
|
||||||
<li><MkLink url="https://github.com/Xeltica" class="at">@Xeltica</MkLink></li>
|
<template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
|
||||||
<li><MkLink url="https://github.com/u1-liquid" class="at">@u1-liquid</MkLink></li>
|
</FormGroup>
|
||||||
</ul>
|
</FormBase>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="_section">
|
|
||||||
<div class="_content">
|
|
||||||
<div class="_card">
|
|
||||||
<div class="_title"><Mfm text="[jelly ❤]"/> {{ $t('patrons') }}</div>
|
|
||||||
<div class="_content">
|
|
||||||
<ul style="margin: 0;">
|
|
||||||
<li>Gargron</li>
|
|
||||||
<li>Satsuki Yanagi</li>
|
|
||||||
<li>noellabo</li>
|
|
||||||
<li>naga_rus</li>
|
|
||||||
<li>Melilot</li>
|
|
||||||
<li>AureoleArk</li>
|
|
||||||
<li>Peter G.</li>
|
|
||||||
<li>motcha</li>
|
|
||||||
<li>Atsuko Tominaga</li>
|
|
||||||
<li>dansup</li>
|
|
||||||
<li>Nokotaro Takeda</li>
|
|
||||||
<li>YUKIMOCHI</li>
|
|
||||||
<li>nanami kan</li>
|
|
||||||
<li>Hekovic</li>
|
|
||||||
<li>wara</li>
|
|
||||||
<li>Takashi Shibuya</li>
|
|
||||||
<li>Noizeman</li>
|
|
||||||
<li>mydarkstar</li>
|
|
||||||
<li>nenohi</li>
|
|
||||||
<li>Eduardo Quiros</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="_footer">{{ $t('morePatrons') }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faInfoCircle, faCode, faLanguage, faHandHoldingMedical, } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { version } from '@/config';
|
import { version } from '@/config';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||||
import MkLink from '@/components/link.vue';
|
import MkLink from '@/components/link.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
const patrons = [
|
||||||
|
'Satsuki Yanagi',
|
||||||
|
'noellabo',
|
||||||
|
'Gargron',
|
||||||
|
'Atsuko Tominaga',
|
||||||
|
'AureoleArk',
|
||||||
|
'naga_rus',
|
||||||
|
'Melilot',
|
||||||
|
'Hekovic',
|
||||||
|
'Nokotaro Takeda',
|
||||||
|
'dansup',
|
||||||
|
'nenohi',
|
||||||
|
'motcha',
|
||||||
|
'nanami kan',
|
||||||
|
'Eduardo Quiros',
|
||||||
|
'Peter G.',
|
||||||
|
'YUKIMOCHI',
|
||||||
|
'Efertone',
|
||||||
|
'makokunsan',
|
||||||
|
'mewl hayabusa',
|
||||||
|
'見当かなみ',
|
||||||
|
'natalie',
|
||||||
|
'takimura',
|
||||||
|
'sikyosyounin',
|
||||||
|
'weepjp',
|
||||||
|
'mydarkstar',
|
||||||
|
'Nesakko',
|
||||||
|
'sheeta.s',
|
||||||
|
'osapon',
|
||||||
|
'YuzuRyo61',
|
||||||
|
'wara',
|
||||||
|
'mkatze',
|
||||||
|
'kiritan',
|
||||||
|
'CG',
|
||||||
|
'Denshi',
|
||||||
|
'Osushimaru',
|
||||||
|
'Liaizon Wakest',
|
||||||
|
];
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkLink
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
FormLink,
|
||||||
|
FormKeyValueView,
|
||||||
|
MkLink,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
@ -91,8 +101,17 @@ export default defineComponent({
|
|||||||
icon: null
|
icon: null
|
||||||
},
|
},
|
||||||
version,
|
version,
|
||||||
faInfoCircle
|
patrons,
|
||||||
|
faInfoCircle, faCode, faLanguage, faHandHoldingMedical,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.znqjceqz {
|
||||||
|
max-width: 800px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,46 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mmnnbwxb">
|
<FormBase class="mmnnbwxb" v-if="meta">
|
||||||
<section class="_section info" v-if="meta">
|
<div class="_formItem logo">
|
||||||
<div class="_title"><Fa :icon="faInfoCircle"/> {{ $t('instanceInfo') }}</div>
|
<img v-if="meta.logoImageUrl" :src="meta.logoImageUrl">
|
||||||
<div class="_content" v-if="meta.description">
|
<span v-else class="text">{{ instanceName }}</span>
|
||||||
<div v-html="meta.description"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="_content table">
|
<FormGroup>
|
||||||
<div><b>{{ $t('administrator') }}</b><span>{{ meta.maintainerName }}</span></div>
|
<FormKeyValueView>
|
||||||
<div><b></b><span>{{ meta.maintainerEmail }}</span></div>
|
<template #key>Misskey</template>
|
||||||
</div>
|
<template #value>v{{ version }}</template>
|
||||||
<div class="_content table">
|
</FormKeyValueView>
|
||||||
<div><b>Misskey</b><span>v{{ version }}</span></div>
|
</FormGroup>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<div class="_section">
|
<FormGroup>
|
||||||
<div class="_content">
|
<FormKeyValueView>
|
||||||
<MkInstanceStats/>
|
<template #key>{{ $t('administrator') }}</template>
|
||||||
</div>
|
<template #value>{{ meta.maintainerName }}</template>
|
||||||
</div>
|
</FormKeyValueView>
|
||||||
</div>
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('contact') }}</template>
|
||||||
|
<template #value>{{ meta.maintainerEmail }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
</FormGroup>
|
||||||
|
</FormBase>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { version } from '@/config';
|
import { version, instanceName } from '@/config';
|
||||||
import MkInstanceStats from '@/components/instance-stats.vue';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkInstanceStats
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
FormLink,
|
||||||
|
FormKeyValueView,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
INFO: {
|
INFO: {
|
||||||
title: this.$t('about'),
|
title: this.$t('instanceInfo'),
|
||||||
icon: faInfoCircle
|
icon: faInfoCircle
|
||||||
},
|
},
|
||||||
version,
|
version,
|
||||||
|
instanceName,
|
||||||
serverInfo: null,
|
serverInfo: null,
|
||||||
faInfoCircle
|
faInfoCircle
|
||||||
}
|
}
|
||||||
@ -56,15 +65,16 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.mmnnbwxb {
|
.mmnnbwxb {
|
||||||
> .info {
|
max-width: 800px;
|
||||||
> .table {
|
box-sizing: border-box;
|
||||||
> div {
|
margin: 0 auto;
|
||||||
display: flex;
|
|
||||||
|
|
||||||
> * {
|
> .logo {
|
||||||
flex: 1;
|
text-align: center;
|
||||||
}
|
|
||||||
}
|
> img {
|
||||||
|
vertical-align: bottom;
|
||||||
|
max-height: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<div class="_section">
|
||||||
<MkPagination :pagination="pagination" #default="{items}" class="ruryvtyk _content" ref="list">
|
<MkPagination :pagination="pagination" #default="{items}" class="ruryvtyk _content">
|
||||||
<section class="_card announcement _vMargin" v-for="(announcement, i) in items" :key="announcement.id">
|
<section class="_card announcement _vMargin" v-for="(announcement, i) in items" :key="announcement.id">
|
||||||
<div class="_title"><span v-if="$store.getters.isSignedIn && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
|
<div class="_title"><span v-if="$store.getters.isSignedIn && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
|
||||||
<div class="_content">
|
<div class="_content">
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
<MkTextarea v-model:value="description">{{ $t('instanceDescription') }}</MkTextarea>
|
<MkTextarea v-model:value="description">{{ $t('instanceDescription') }}</MkTextarea>
|
||||||
<MkInput v-model:value="iconUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('iconUrl') }}</MkInput>
|
<MkInput v-model:value="iconUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('iconUrl') }}</MkInput>
|
||||||
<MkInput v-model:value="bannerUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('bannerUrl') }}</MkInput>
|
<MkInput v-model:value="bannerUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('bannerUrl') }}</MkInput>
|
||||||
|
<MkInput v-model:value="backgroundImageUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('backgroundImageUrl') }}</MkInput>
|
||||||
|
<MkInput v-model:value="logoImageUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('logoImageUrl') }}</MkInput>
|
||||||
<MkInput v-model:value="tosUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('tosUrl') }}</MkInput>
|
<MkInput v-model:value="tosUrl"><template #icon><Fa :icon="faLink"/></template>{{ $t('tosUrl') }}</MkInput>
|
||||||
<MkInput v-model:value="maintainerName">{{ $t('maintainerName') }}</MkInput>
|
<MkInput v-model:value="maintainerName">{{ $t('maintainerName') }}</MkInput>
|
||||||
<MkInput v-model:value="maintainerEmail" type="email"><template #icon><Fa :icon="faEnvelope"/></template>{{ $t('maintainerEmail') }}</MkInput>
|
<MkInput v-model:value="maintainerEmail" type="email"><template #icon><Fa :icon="faEnvelope"/></template>{{ $t('maintainerEmail') }}</MkInput>
|
||||||
@ -292,6 +294,8 @@ export default defineComponent({
|
|||||||
email: null,
|
email: null,
|
||||||
bannerUrl: null,
|
bannerUrl: null,
|
||||||
iconUrl: null,
|
iconUrl: null,
|
||||||
|
logoImageUrl: null,
|
||||||
|
backgroundImageUrl: null,
|
||||||
maxNoteTextLength: 0,
|
maxNoteTextLength: 0,
|
||||||
enableRegistration: false,
|
enableRegistration: false,
|
||||||
enableLocalTimeline: false,
|
enableLocalTimeline: false,
|
||||||
@ -345,6 +349,8 @@ export default defineComponent({
|
|||||||
this.tosUrl = this.meta.tosUrl;
|
this.tosUrl = this.meta.tosUrl;
|
||||||
this.bannerUrl = this.meta.bannerUrl;
|
this.bannerUrl = this.meta.bannerUrl;
|
||||||
this.iconUrl = this.meta.iconUrl;
|
this.iconUrl = this.meta.iconUrl;
|
||||||
|
this.logoImageUrl = this.meta.logoImageUrl;
|
||||||
|
this.backgroundImageUrl = this.meta.backgroundImageUrl;
|
||||||
this.enableEmail = this.meta.enableEmail;
|
this.enableEmail = this.meta.enableEmail;
|
||||||
this.email = this.meta.email;
|
this.email = this.meta.email;
|
||||||
this.maintainerName = this.meta.maintainerName;
|
this.maintainerName = this.meta.maintainerName;
|
||||||
@ -498,6 +504,8 @@ export default defineComponent({
|
|||||||
tosUrl: this.tosUrl,
|
tosUrl: this.tosUrl,
|
||||||
bannerUrl: this.bannerUrl,
|
bannerUrl: this.bannerUrl,
|
||||||
iconUrl: this.iconUrl,
|
iconUrl: this.iconUrl,
|
||||||
|
logoImageUrl: this.logoImageUrl,
|
||||||
|
backgroundImageUrl: this.backgroundImageUrl,
|
||||||
maintainerName: this.maintainerName,
|
maintainerName: this.maintainerName,
|
||||||
maintainerEmail: this.maintainerEmail,
|
maintainerEmail: this.maintainerEmail,
|
||||||
maxNoteTextLength: this.maxNoteTextLength,
|
maxNoteTextLength: this.maxNoteTextLength,
|
||||||
|
@ -38,6 +38,7 @@ import parseAcct from '../../../misc/acct/parse';
|
|||||||
import { isBottom, onScrollBottom, scroll } from '@/scripts/scroll';
|
import { isBottom, onScrollBottom, scroll } from '@/scripts/scroll';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { popout } from '@/scripts/popout';
|
import { popout } from '@/scripts/popout';
|
||||||
|
import * as sound from '@/scripts/sound';
|
||||||
|
|
||||||
const Component = defineComponent({
|
const Component = defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -218,7 +219,7 @@ const Component = defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onMessage(message) {
|
onMessage(message) {
|
||||||
os.sound('chat');
|
sound.play('chat');
|
||||||
|
|
||||||
const _isBottom = isBottom(this.$el, 64);
|
const _isBottom = isBottom(this.$el, 64);
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ import { url } from '@/config';
|
|||||||
import MkButton from '@/components/ui/button.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import { userPage } from '@/filters/user';
|
import { userPage } from '@/filters/user';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import * as sound from '@/scripts/sound';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -245,11 +246,7 @@ export default defineComponent({
|
|||||||
this.o.put(this.myColor, pos);
|
this.o.put(this.myColor, pos);
|
||||||
|
|
||||||
// サウンドを再生する
|
// サウンドを再生する
|
||||||
if (this.$store.state.device.enableSounds) {
|
sound.play(this.myColor ? 'reversiPutBlack' : 'reversiPutWhite');
|
||||||
const sound = new Audio(`${url}/assets/reversi-put-me.mp3`);
|
|
||||||
sound.volume = this.$store.state.device.soundVolume;
|
|
||||||
sound.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.connection.send('set', {
|
this.connection.send('set', {
|
||||||
pos: pos
|
pos: pos
|
||||||
@ -268,10 +265,8 @@ export default defineComponent({
|
|||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
|
|
||||||
// サウンドを再生する
|
// サウンドを再生する
|
||||||
if (this.$store.state.device.enableSounds && x.color != this.myColor) {
|
if (x.color !== this.myColor) {
|
||||||
const sound = new Audio(`${url}/assets/reversi-put-you.mp3`);
|
sound.play(x.color ? 'reversiPutBlack' : 'reversiPutWhite');
|
||||||
sound.volume = this.$store.state.device.soundVolume;
|
|
||||||
sound.play();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -75,14 +75,25 @@ import MkButton from '@/components/ui/button.vue';
|
|||||||
import MkInfo from '@/components/ui/info.vue';
|
import MkInfo from '@/components/ui/info.vue';
|
||||||
import MkInput from '@/components/ui/input.vue';
|
import MkInput from '@/components/ui/input.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import MkSwitch from '@/components/ui/switch.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
FormBase,
|
||||||
MkButton, MkInfo, MkInput, MkSwitch
|
MkButton, MkInfo, MkInput, MkSwitch
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('twoStepAuthentication'),
|
||||||
|
icon: faLock
|
||||||
|
},
|
||||||
data: null,
|
data: null,
|
||||||
supportsCredentials: !!navigator.credentials,
|
supportsCredentials: !!navigator.credentials,
|
||||||
usePasswordLessLogin: this.$store.state.i.usePasswordLessLogin,
|
usePasswordLessLogin: this.$store.state.i.usePasswordLessLogin,
|
||||||
@ -92,6 +103,7 @@ export default defineComponent({
|
|||||||
faLock
|
faLock
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
register() {
|
register() {
|
||||||
os.dialog({
|
os.dialog({
|
||||||
@ -225,6 +237,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePasswordLessLogin() {
|
updatePasswordLessLogin() {
|
||||||
os.api('i/2fa/password-less', {
|
os.api('i/2fa/password-less', {
|
||||||
value: !!this.usePasswordLessLogin
|
value: !!this.usePasswordLessLogin
|
185
src/client/pages/settings/account-info.vue
Normal file
185
src/client/pages/settings/account-info.vue
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>ID</template>
|
||||||
|
<template #value><span class="_monospace">{{ $store.state.i.id }}</span></template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('registeredDate') }}</template>
|
||||||
|
<template #value><MkTime :time="$store.state.i.createdAt" mode="detail"/></template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup v-if="stats">
|
||||||
|
<template #label>{{ $t('statistics') }}</template>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('notesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.notesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('repliesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.repliesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('renotesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.renotesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('repliedCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.repliedCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('renotedCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.renotedCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('pollVotesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.pollVotesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('pollVotedCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.pollVotedCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('sentReactionsCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.sentReactionsCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('receivedReactionsCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.receivedReactionsCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('noteFavoritesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.noteFavoritesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followingCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.followingCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followingCount') }} ({{ $t('local') }})</template>
|
||||||
|
<template #value>{{ number(stats.localFollowingCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followingCount') }} ({{ $t('remote') }})</template>
|
||||||
|
<template #value>{{ number(stats.remoteFollowingCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followersCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.followersCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followersCount') }} ({{ $t('local') }})</template>
|
||||||
|
<template #value>{{ number(stats.localFollowersCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('followersCount') }} ({{ $t('remote') }})</template>
|
||||||
|
<template #value>{{ number(stats.remoteFollowersCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('pageLikesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.pageLikesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('pageLikedCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.pageLikedCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('driveFilesCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.driveFilesCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('driveUsage') }}</template>
|
||||||
|
<template #value>{{ bytes(stats.driveUsage) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>{{ $t('reversiCount') }}</template>
|
||||||
|
<template #value>{{ number(stats.reversiCount) }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<template #label>{{ $t('other') }}</template>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>emailVerified</template>
|
||||||
|
<template #value>{{ $store.state.i.emailVerified ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>twoFactorEnabled</template>
|
||||||
|
<template #value>{{ $store.state.i.twoFactorEnabled ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>securityKeys</template>
|
||||||
|
<template #value>{{ $store.state.i.securityKeys ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>usePasswordLessLogin</template>
|
||||||
|
<template #value>{{ $store.state.i.usePasswordLessLogin ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>isModerator</template>
|
||||||
|
<template #value>{{ $store.state.i.isModerator ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
<FormKeyValueView>
|
||||||
|
<template #key>isAdmin</template>
|
||||||
|
<template #value>{{ $store.state.i.isAdmin ? $t('yes') : $t('no') }}</template>
|
||||||
|
</FormKeyValueView>
|
||||||
|
</FormGroup>
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||||
|
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
import number from '@/filters/number';
|
||||||
|
import bytes from '@/filters/bytes';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormBase,
|
||||||
|
FormSelect,
|
||||||
|
FormSwitch,
|
||||||
|
FormButton,
|
||||||
|
FormLink,
|
||||||
|
FormGroup,
|
||||||
|
FormKeyValueView,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('accountInfo'),
|
||||||
|
icon: faInfoCircle
|
||||||
|
},
|
||||||
|
stats: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
|
||||||
|
os.api('users/stats', {
|
||||||
|
userId: this.$store.state.i.id
|
||||||
|
}).then(stats => {
|
||||||
|
this.stats = stats;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
number,
|
||||||
|
bytes,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,26 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FormBase>
|
||||||
<div class="_section">
|
<FormButton @click="generateToken" primary>{{ $t('generateAccessToken') }}</FormButton>
|
||||||
<div class="_content">
|
<FormLink to="/settings/apps">{{ $t('manageAccessTokens') }}</FormLink>
|
||||||
<MkButton @click="generateToken">{{ $t('generateAccessToken') }}</MkButton>
|
<FormLink to="/api-console" :behavior="isDesktop ? 'window' : null">API console</FormLink>
|
||||||
</div>
|
</FormBase>
|
||||||
</div>
|
|
||||||
<div class="_section">
|
|
||||||
<MkA to="/api-console" :behavior="isDesktop ? 'window' : null">API console</MkA>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faKey } from '@fortawesome/free-solid-svg-icons';
|
import { faKey } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkInput from '@/components/ui/input.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton, MkInput
|
FormBase,
|
||||||
|
FormButton,
|
||||||
|
FormLink,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FormBase>
|
||||||
<MkPagination :pagination="pagination" class="bfomjevm" ref="list">
|
<FormPagination :pagination="pagination" ref="list">
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div class="_fullinfo">
|
<div class="_fullinfo">
|
||||||
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||||
@ -8,8 +8,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{items}">
|
<template #default="{items}">
|
||||||
<div class="token _panel" v-for="token in items" :key="token.id">
|
<div class="_formPanel bfomjevm" v-for="token in items" :key="token.id">
|
||||||
<img class="icon" :src="token.iconUrl" alt=""/>
|
<img class="icon" :src="token.iconUrl" alt="" v-if="token.iconUrl"/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="name">{{ token.name }}</div>
|
<div class="name">{{ token.name }}</div>
|
||||||
<div class="description">{{ token.description }}</div>
|
<div class="description">{{ token.description }}</div>
|
||||||
@ -33,21 +33,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MkPagination>
|
</FormPagination>
|
||||||
</div>
|
</FormBase>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faTrashAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
|
import { faTrashAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkPagination from '@/components/ui/pagination.vue';
|
import FormPagination from '@/components/form/pagination.vue';
|
||||||
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkPagination
|
FormBase,
|
||||||
|
FormPagination,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
INFO: {
|
INFO: {
|
||||||
@ -65,6 +73,10 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
revoke(token) {
|
revoke(token) {
|
||||||
os.api('i/revoke-token', { tokenId: token.id }).then(() => {
|
os.api('i/revoke-token', { tokenId: token.id }).then(() => {
|
||||||
@ -77,7 +89,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.bfomjevm {
|
.bfomjevm {
|
||||||
> .token {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
@ -99,5 +110,4 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
90
src/client/pages/settings/deck.vue
Normal file
90
src/client/pages/settings/deck.vue
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
|
||||||
|
<section class="_card _vMargin">
|
||||||
|
<div class="_title"><Fa :icon="faColumns"/> </div>
|
||||||
|
<div class="_content">
|
||||||
|
<div>{{ $t('defaultNavigationBehaviour') }}</div>
|
||||||
|
<MkSwitch v-model:value="deckNavWindow">{{ $t('openInWindow') }}</MkSwitch>
|
||||||
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<MkSwitch v-model:value="deckAlwaysShowMainColumn">
|
||||||
|
{{ $t('_deck.alwaysShowMainColumn') }}
|
||||||
|
</MkSwitch>
|
||||||
|
</div>
|
||||||
|
<div class="_content">
|
||||||
|
<div>{{ $t('_deck.columnAlign') }}</div>
|
||||||
|
<MkRadio v-model="deckColumnAlign" value="left">{{ $t('left') }}</MkRadio>
|
||||||
|
<MkRadio v-model="deckColumnAlign" value="center">{{ $t('center') }}</MkRadio>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faImage, faCog, faColumns } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import MkButton from '@/components/ui/button.vue';
|
||||||
|
import MkSwitch from '@/components/ui/switch.vue';
|
||||||
|
import MkSelect from '@/components/ui/select.vue';
|
||||||
|
import MkRadio from '@/components/ui/radio.vue';
|
||||||
|
import MkRadios from '@/components/ui/radios.vue';
|
||||||
|
import MkRange from '@/components/ui/range.vue';
|
||||||
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import { clientDb, set } from '@/db';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkButton,
|
||||||
|
MkSwitch,
|
||||||
|
MkSelect,
|
||||||
|
MkRadio,
|
||||||
|
MkRadios,
|
||||||
|
MkRange,
|
||||||
|
FormSwitch,
|
||||||
|
FormSelect,
|
||||||
|
FormRadios,
|
||||||
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('deck'),
|
||||||
|
icon: faColumns
|
||||||
|
},
|
||||||
|
faImage, faCog,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
deckNavWindow: {
|
||||||
|
get() { return this.$store.state.device.deckNavWindow; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'deckNavWindow', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
|
deckAlwaysShowMainColumn: {
|
||||||
|
get() { return this.$store.state.device.deckAlwaysShowMainColumn; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'deckAlwaysShowMainColumn', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
|
deckColumnAlign: {
|
||||||
|
get() { return this.$store.state.device.deckColumnAlign; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'deckColumnAlign', value }); }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
71
src/client/pages/settings/email-address.vue
Normal file
71
src/client/pages/settings/email-address.vue
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
<FormGroup>
|
||||||
|
<FormInput v-model:value="emailAddress" type="email">
|
||||||
|
{{ $t('emailAddress') }}
|
||||||
|
<template #desc v-if="$store.state.i.email && !$store.state.i.emailVerified">{{ $t('verificationEmailSent') }}</template>
|
||||||
|
<template #desc v-else-if="emailAddress === $store.state.i.email && $store.state.i.emailVerified">{{ $t('emailVerified') }}</template>
|
||||||
|
</FormInput>
|
||||||
|
</FormGroup>
|
||||||
|
<FormButton @click="save" primary>{{ $t('save') }}</FormButton>
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import FormInput from '@/components/form/input.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormBase,
|
||||||
|
FormInput,
|
||||||
|
FormButton,
|
||||||
|
FormGroup,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('emailAddress'),
|
||||||
|
icon: faEnvelope
|
||||||
|
},
|
||||||
|
emailAddress: null,
|
||||||
|
code: null,
|
||||||
|
faCog
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.emailAddress = this.$store.state.i.email;
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
save() {
|
||||||
|
os.dialog({
|
||||||
|
title: this.$t('password'),
|
||||||
|
input: {
|
||||||
|
type: 'password'
|
||||||
|
}
|
||||||
|
}).then(({ canceled, result: password }) => {
|
||||||
|
if (canceled) return;
|
||||||
|
os.api('i/update-email', {
|
||||||
|
password: password,
|
||||||
|
email: this.emailAddress,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
52
src/client/pages/settings/email.vue
Normal file
52
src/client/pages/settings/email.vue
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
<FormGroup>
|
||||||
|
<template #label>{{ $t('emailAddress') }}</template>
|
||||||
|
<FormLink to="/settings/email/address">
|
||||||
|
<template v-if="$store.state.i.email && !$store.state.i.emailVerified" #icon><Fa :icon="faExclamationTriangle" style="color: var(--warn);"/></template>
|
||||||
|
<template v-else-if="$store.state.i.email && $store.state.i.emailVerified" #icon><Fa :icon="faCheck" style="color: var(--success);"/></template>
|
||||||
|
{{ $store.state.i.email || $t('notSet') }}
|
||||||
|
</FormLink>
|
||||||
|
</FormGroup>
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faCog, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormBase,
|
||||||
|
FormLink,
|
||||||
|
FormButton,
|
||||||
|
FormGroup,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('email'),
|
||||||
|
icon: faEnvelope
|
||||||
|
},
|
||||||
|
faCog, faExclamationTriangle, faCheck
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,109 +1,111 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="">
|
<FormBase>
|
||||||
<section class="_card _vMargin">
|
<FormSwitch v-model:value="showFixedPostForm">{{ $t('showFixedPostForm') }}</FormSwitch>
|
||||||
<div class="_title"><Fa :icon="faCog"/> {{ $t('general') }}</div>
|
|
||||||
<div class="_content">
|
<FormSelect v-model:value="lang">
|
||||||
<MkRadios v-model="serverDisconnectedBehavior">
|
<template #label>{{ $t('uiLanguage') }}</template>
|
||||||
<template #desc>{{ $t('whenServerDisconnected') }}</template>
|
<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
|
||||||
|
<template #caption>
|
||||||
|
<i18n-t keypath="i18nInfo" tag="span">
|
||||||
|
<template #link>
|
||||||
|
<MkLink url="https://crowdin.com/project/misskey">Crowdin</MkLink>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</template>
|
||||||
|
</FormSelect>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<template #label>{{ $t('behavior') }}</template>
|
||||||
|
<FormSwitch v-model:value="imageNewTab">{{ $t('openImageInNewTab') }}</FormSwitch>
|
||||||
|
<FormSwitch v-model:value="enableInfiniteScroll">{{ $t('enableInfiniteScroll') }}</FormSwitch>
|
||||||
|
<FormSwitch v-model:value="disablePagesScript">{{ $t('disablePagesScript') }}</FormSwitch>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormSelect v-model:value="serverDisconnectedBehavior">
|
||||||
|
<template #label>{{ $t('whenServerDisconnected') }}</template>
|
||||||
<option value="reload">{{ $t('_serverDisconnectedBehavior.reload') }}</option>
|
<option value="reload">{{ $t('_serverDisconnectedBehavior.reload') }}</option>
|
||||||
<option value="dialog">{{ $t('_serverDisconnectedBehavior.dialog') }}</option>
|
<option value="dialog">{{ $t('_serverDisconnectedBehavior.dialog') }}</option>
|
||||||
<option value="quiet">{{ $t('_serverDisconnectedBehavior.quiet') }}</option>
|
<option value="quiet">{{ $t('_serverDisconnectedBehavior.quiet') }}</option>
|
||||||
</MkRadios>
|
</FormSelect>
|
||||||
<MkSwitch v-model:value="imageNewTab">{{ $t('openImageInNewTab') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="showFixedPostForm">{{ $t('showFixedPostForm') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="enableInfiniteScroll">{{ $t('enableInfiniteScroll') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="disablePagesScript">{{ $t('disablePagesScript') }}</MkSwitch>
|
|
||||||
<MkSelect v-model:value="lang">
|
|
||||||
<template #label>{{ $t('uiLanguage') }}</template>
|
|
||||||
<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
|
|
||||||
</MkSelect>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="_card _vMargin">
|
<FormGroup>
|
||||||
<div class="_title"><Fa :icon="faCog"/> {{ $t('defaultNavigationBehaviour') }}</div>
|
<template #label>{{ $t('appearance') }}</template>
|
||||||
<div class="_content">
|
<FormSwitch v-model:value="disableAnimatedMfm">{{ $t('disableAnimatedMfm') }}</FormSwitch>
|
||||||
<MkSwitch v-model:value="defaultSideView">{{ $t('openInSideView') }}</MkSwitch>
|
<FormSwitch v-model:value="reduceAnimation">{{ $t('reduceUiAnimation') }}</FormSwitch>
|
||||||
</div>
|
<FormSwitch v-model:value="useBlurEffectForModal">{{ $t('useBlurEffectForModal') }}</FormSwitch>
|
||||||
<div class="_content">
|
<FormSwitch v-model:value="loadRawImages">{{ $t('loadRawImages') }}</FormSwitch>
|
||||||
<MkRadios v-model="chatOpenBehavior">
|
<FormSwitch v-model:value="disableShowingAnimatedImages">{{ $t('disableShowingAnimatedImages') }}</FormSwitch>
|
||||||
<template #desc>{{ $t('chatOpenBehavior') }}</template>
|
<FormSwitch v-model:value="useSystemFont">{{ $t('useSystemFont') }}</FormSwitch>
|
||||||
<option value="page">{{ $t('showInPage') }}</option>
|
<FormSwitch v-model:value="useOsNativeEmojis">{{ $t('useOsNativeEmojis') }}
|
||||||
<option value="window">{{ $t('openInWindow') }}</option>
|
<div><Mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></div>
|
||||||
<option value="popout">{{ $t('popout') }}</option>
|
</FormSwitch>
|
||||||
</MkRadios>
|
</FormGroup>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="_card _vMargin">
|
<FormRadios v-model="fontSize">
|
||||||
<div class="_title"><Fa :icon="faCog"/> {{ $t('appearance') }}</div>
|
|
||||||
<div class="_content">
|
|
||||||
<MkSwitch v-model:value="disableAnimatedMfm">{{ $t('disableAnimatedMfm') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="reduceAnimation">{{ $t('reduceUiAnimation') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="useBlurEffectForModal">{{ $t('useBlurEffectForModal') }}</MkSwitch>
|
|
||||||
<MkSwitch v-model:value="useOsNativeEmojis">
|
|
||||||
{{ $t('useOsNativeEmojis') }}
|
|
||||||
<template #desc><Mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template>
|
|
||||||
</MkSwitch>
|
|
||||||
<MkRadios v-model="fontSize">
|
|
||||||
<template #desc>{{ $t('fontSize') }}</template>
|
<template #desc>{{ $t('fontSize') }}</template>
|
||||||
<option value="small"><span style="font-size: 14px;">Aa</span></option>
|
<option value="small"><span style="font-size: 14px;">Aa</span></option>
|
||||||
<option :value="null"><span style="font-size: 16px;">Aa</span></option>
|
<option :value="null"><span style="font-size: 16px;">Aa</span></option>
|
||||||
<option value="large"><span style="font-size: 18px;">Aa</span></option>
|
<option value="large"><span style="font-size: 18px;">Aa</span></option>
|
||||||
<option value="veryLarge"><span style="font-size: 20px;">Aa</span></option>
|
<option value="veryLarge"><span style="font-size: 20px;">Aa</span></option>
|
||||||
</MkRadios>
|
</FormRadios>
|
||||||
<MkRadios v-model="instanceTicker">
|
|
||||||
<template #desc>{{ $t('instanceTicker') }}</template>
|
<FormSelect v-model:value="instanceTicker">
|
||||||
|
<template #label>{{ $t('instanceTicker') }}</template>
|
||||||
<option value="none">{{ $t('_instanceTicker.none') }}</option>
|
<option value="none">{{ $t('_instanceTicker.none') }}</option>
|
||||||
<option value="remote">{{ $t('_instanceTicker.remote') }}</option>
|
<option value="remote">{{ $t('_instanceTicker.remote') }}</option>
|
||||||
<option value="always">{{ $t('_instanceTicker.always') }}</option>
|
<option value="always">{{ $t('_instanceTicker.always') }}</option>
|
||||||
</MkRadios>
|
</FormSelect>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="_card _vMargin">
|
<FormSelect v-model:value="nsfw">
|
||||||
<div class="_title"><Fa :icon="faColumns"/> {{ $t('deck') }}</div>
|
<template #label>{{ $t('nsfw') }}</template>
|
||||||
<div class="_content">
|
<option value="respect">{{ $t('_nsfw.respect') }}</option>
|
||||||
<div>{{ $t('defaultNavigationBehaviour') }}</div>
|
<option value="ignore">{{ $t('_nsfw.ignore') }}</option>
|
||||||
<MkSwitch v-model:value="deckNavWindow">{{ $t('openInWindow') }}</MkSwitch>
|
<option value="force">{{ $t('_nsfw.force') }}</option>
|
||||||
</div>
|
</FormSelect>
|
||||||
<div class="_content">
|
|
||||||
<MkSwitch v-model:value="deckAlwaysShowMainColumn">
|
|
||||||
{{ $t('_deck.alwaysShowMainColumn') }}
|
|
||||||
</MkSwitch>
|
|
||||||
</div>
|
|
||||||
<div class="_content">
|
|
||||||
<div>{{ $t('_deck.columnAlign') }}</div>
|
|
||||||
<MkRadio v-model="deckColumnAlign" value="left">{{ $t('left') }}</MkRadio>
|
|
||||||
<MkRadio v-model="deckColumnAlign" value="center">{{ $t('center') }}</MkRadio>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<MkButton @click="cacheClear()" primary style="margin: var(--margin) auto;">{{ $t('cacheClear') }}</MkButton>
|
<FormGroup>
|
||||||
</div>
|
<template #label>{{ $t('defaultNavigationBehaviour') }}</template>
|
||||||
|
<FormSwitch v-model:value="defaultSideView">{{ $t('openInSideView') }}</FormSwitch>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormSelect v-model:value="chatOpenBehavior">
|
||||||
|
<template #label>{{ $t('chatOpenBehavior') }}</template>
|
||||||
|
<option value="page">{{ $t('showInPage') }}</option>
|
||||||
|
<option value="window">{{ $t('openInWindow') }}</option>
|
||||||
|
<option value="popout">{{ $t('popout') }}</option>
|
||||||
|
</FormSelect>
|
||||||
|
|
||||||
|
<FormLink to="/settings/deck">{{ $t('deck') }}</FormLink>
|
||||||
|
|
||||||
|
<FormButton @click="cacheClear()" danger>{{ $t('cacheClear') }}</FormButton>
|
||||||
|
</FormBase>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faImage, faCog, faColumns, faCogs } from '@fortawesome/free-solid-svg-icons';
|
import { faImage, faCog, faColumns, faCogs } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
import MkRadio from '@/components/ui/radio.vue';
|
import FormBase from '@/components/form/base.vue';
|
||||||
import MkRadios from '@/components/ui/radios.vue';
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import MkRange from '@/components/ui/range.vue';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import MkLink from '@/components/link.vue';
|
||||||
import { langs } from '@/config';
|
import { langs } from '@/config';
|
||||||
import { clientDb, set } from '@/db';
|
import { clientDb, set } from '@/db';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
MkLink,
|
||||||
MkSwitch,
|
FormSwitch,
|
||||||
MkSelect,
|
FormSelect,
|
||||||
MkRadio,
|
FormRadios,
|
||||||
MkRadios,
|
FormBase,
|
||||||
MkRange,
|
FormGroup,
|
||||||
|
FormLink,
|
||||||
|
FormButton,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -117,6 +119,7 @@ export default defineComponent({
|
|||||||
langs,
|
langs,
|
||||||
lang: localStorage.getItem('lang'),
|
lang: localStorage.getItem('lang'),
|
||||||
fontSize: localStorage.getItem('fontSize'),
|
fontSize: localStorage.getItem('fontSize'),
|
||||||
|
useSystemFont: localStorage.getItem('useSystemFont') != null,
|
||||||
faImage, faCog, faColumns
|
faImage, faCog, faColumns
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -167,11 +170,6 @@ export default defineComponent({
|
|||||||
set(value) { this.$store.commit('device/set', { key: 'defaultSideView', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'defaultSideView', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
deckNavWindow: {
|
|
||||||
get() { return this.$store.state.device.deckNavWindow; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'deckNavWindow', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
chatOpenBehavior: {
|
chatOpenBehavior: {
|
||||||
get() { return this.$store.state.device.chatOpenBehavior; },
|
get() { return this.$store.state.device.chatOpenBehavior; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'chatOpenBehavior', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'chatOpenBehavior', value }); }
|
||||||
@ -182,20 +180,25 @@ export default defineComponent({
|
|||||||
set(value) { this.$store.commit('device/set', { key: 'instanceTicker', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'instanceTicker', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadRawImages: {
|
||||||
|
get() { return this.$store.state.device.loadRawImages; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'loadRawImages', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
|
disableShowingAnimatedImages: {
|
||||||
|
get() { return this.$store.state.device.disableShowingAnimatedImages; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'disableShowingAnimatedImages', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
|
nsfw: {
|
||||||
|
get() { return this.$store.state.device.nsfw; },
|
||||||
|
set(value) { this.$store.commit('device/set', { key: 'nsfw', value }); }
|
||||||
|
},
|
||||||
|
|
||||||
enableInfiniteScroll: {
|
enableInfiniteScroll: {
|
||||||
get() { return this.$store.state.device.enableInfiniteScroll; },
|
get() { return this.$store.state.device.enableInfiniteScroll; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'enableInfiniteScroll', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'enableInfiniteScroll', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
deckAlwaysShowMainColumn: {
|
|
||||||
get() { return this.$store.state.device.deckAlwaysShowMainColumn; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'deckAlwaysShowMainColumn', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
deckColumnAlign: {
|
|
||||||
get() { return this.$store.state.device.deckColumnAlign; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'deckColumnAlign', value }); }
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -220,6 +223,15 @@ export default defineComponent({
|
|||||||
location.reload();
|
location.reload();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
useSystemFont() {
|
||||||
|
if (this.useSystemFont) {
|
||||||
|
localStorage.setItem('useSystemFont', 't');
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('useSystemFont');
|
||||||
|
}
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
|
||||||
enableInfiniteScroll() {
|
enableInfiniteScroll() {
|
||||||
location.reload()
|
location.reload()
|
||||||
},
|
},
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="vvcocwet" :class="{ wide: !narrow }" ref="el">
|
<div class="vvcocwet" :class="{ wide: !narrow }" ref="el">
|
||||||
<div class="nav" v-if="!narrow || page == null">
|
<FormBase class="nav" v-if="!narrow || page == null" :force-wide="!narrow">
|
||||||
<div class="menu">
|
<FormGroup>
|
||||||
<div class="label">{{ $t('basicSettings') }}</div>
|
<template #label>{{ $t('basicSettings') }}</template>
|
||||||
<MkA class="item" :class="{ active: page === 'profile' }" replace to="/settings/profile"><Fa :icon="faUser" fixed-width class="icon"/>{{ $t('profile') }}</MkA>
|
<FormLink :active="page === 'profile'" replace to="/settings/profile"><template #icon><Fa :icon="faUser"/></template>{{ $t('profile') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'privacy' }" replace to="/settings/privacy"><Fa :icon="faLockOpen" fixed-width class="icon"/>{{ $t('privacy') }}</MkA>
|
<FormLink :active="page === 'privacy'" replace to="/settings/privacy"><template #icon><Fa :icon="faLockOpen"/></template>{{ $t('privacy') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'reaction' }" replace to="/settings/reaction"><Fa :icon="faLaugh" fixed-width class="icon"/>{{ $t('reaction') }}</MkA>
|
<FormLink :active="page === 'reaction'" replace to="/settings/reaction"><template #icon><Fa :icon="faLaugh"/></template>{{ $t('reaction') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'notifications' }" replace to="/settings/notifications"><Fa :icon="faBell" fixed-width class="icon"/>{{ $t('notifications') }}</MkA>
|
<FormLink :active="page === 'notifications'" replace to="/settings/notifications"><template #icon><Fa :icon="faBell"/></template>{{ $t('notifications') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'integration' }" replace to="/settings/integration"><Fa :icon="faShareAlt" fixed-width class="icon"/>{{ $t('integration') }}</MkA>
|
<FormLink :active="page === 'email'" replace to="/settings/email"><template #icon><Fa :icon="faEnvelope"/></template>{{ $t('email') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'security' }" replace to="/settings/security"><Fa :icon="faLock" fixed-width class="icon"/>{{ $t('security') }}</MkA>
|
<FormLink :active="page === 'integration'" replace to="/settings/integration"><template #icon><Fa :icon="faShareAlt"/></template>{{ $t('integration') }}</FormLink>
|
||||||
</div>
|
<FormLink :active="page === 'security'" replace to="/settings/security"><template #icon><Fa :icon="faLock"/></template>{{ $t('security') }}</FormLink>
|
||||||
<div class="menu">
|
</FormGroup>
|
||||||
<div class="label">{{ $t('clientSettings') }}</div>
|
<FormGroup>
|
||||||
<MkA class="item" :class="{ active: page === 'general' }" replace to="/settings/general"><Fa :icon="faCogs" fixed-width class="icon"/>{{ $t('general') }}</MkA>
|
<template #label>{{ $t('clientSettings') }}</template>
|
||||||
<MkA class="item" :class="{ active: page === 'theme' }" replace to="/settings/theme"><Fa :icon="faPalette" fixed-width class="icon"/>{{ $t('theme') }}</MkA>
|
<FormLink :active="page === 'general'" replace to="/settings/general"><template #icon><Fa :icon="faCogs"/></template>{{ $t('general') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'sidebar' }" replace to="/settings/sidebar"><Fa :icon="faListUl" fixed-width class="icon"/>{{ $t('sidebar') }}</MkA>
|
<FormLink :active="page === 'theme'" replace to="/settings/theme"><template #icon><Fa :icon="faPalette"/></template>{{ $t('theme') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'sounds' }" replace to="/settings/sounds"><Fa :icon="faMusic" fixed-width class="icon"/>{{ $t('sounds') }}</MkA>
|
<FormLink :active="page === 'sidebar'" replace to="/settings/sidebar"><template #icon><Fa :icon="faListUl"/></template>{{ $t('sidebar') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'plugins' }" replace to="/settings/plugins"><Fa :icon="faPlug" fixed-width class="icon"/>{{ $t('plugins') }}</MkA>
|
<FormLink :active="page === 'sounds'" replace to="/settings/sounds"><template #icon><Fa :icon="faMusic"/></template>{{ $t('sounds') }}</FormLink>
|
||||||
</div>
|
<FormLink :active="page === 'plugins'" replace to="/settings/plugins"><template #icon><Fa :icon="faPlug"/></template>{{ $t('plugins') }}</FormLink>
|
||||||
<div class="menu">
|
</FormGroup>
|
||||||
<div class="label">{{ $t('otherSettings') }}</div>
|
<FormGroup>
|
||||||
<MkA class="item" :class="{ active: page === 'import-export' }" replace to="/settings/import-export"><Fa :icon="faBoxes" fixed-width class="icon"/>{{ $t('importAndExport') }}</MkA>
|
<template #label>{{ $t('otherSettings') }}</template>
|
||||||
<MkA class="item" :class="{ active: page === 'mute-block' }" replace to="/settings/mute-block"><Fa :icon="faBan" fixed-width class="icon"/>{{ $t('muteAndBlock') }}</MkA>
|
<FormLink :active="page === 'import-export'" replace to="/settings/import-export"><template #icon><Fa :icon="faBoxes"/></template>{{ $t('importAndExport') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'word-mute' }" replace to="/settings/word-mute"><Fa :icon="faCommentSlash" fixed-width class="icon"/>{{ $t('wordMute') }}</MkA>
|
<FormLink :active="page === 'mute-block'" replace to="/settings/mute-block"><template #icon><Fa :icon="faBan"/></template>{{ $t('muteAndBlock') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'api' }" replace to="/settings/api"><Fa :icon="faKey" fixed-width class="icon"/>API</MkA>
|
<FormLink :active="page === 'word-mute'" replace to="/settings/word-mute"><template #icon><Fa :icon="faCommentSlash"/></template>{{ $t('wordMute') }}</FormLink>
|
||||||
<MkA class="item" :class="{ active: page === 'other' }" replace to="/settings/other"><Fa :icon="faEllipsisH" fixed-width class="icon"/>{{ $t('other') }}</MkA>
|
<FormLink :active="page === 'api'" replace to="/settings/api"><template #icon><Fa :icon="faKey"/></template>API</FormLink>
|
||||||
</div>
|
<FormLink :active="page === 'other'" replace to="/settings/other"><template #icon><Fa :icon="faEllipsisH"/></template>{{ $t('other') }}</FormLink>
|
||||||
<div class="menu">
|
</FormGroup>
|
||||||
<button class="_button item" @click="logout">{{ $t('logout') }}</button>
|
<FormGroup>
|
||||||
</div>
|
<FormButton @click="logout" danger>{{ $t('logout') }}</FormButton>
|
||||||
</div>
|
</FormGroup>
|
||||||
|
</FormBase>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<component :is="component" @info="onInfo"/>
|
<component :is="component" @info="onInfo"/>
|
||||||
</div>
|
</div>
|
||||||
@ -37,13 +38,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineAsyncComponent, defineComponent, onMounted, ref } from 'vue';
|
import { computed, defineAsyncComponent, defineComponent, nextTick, onMounted, ref, watch } from 'vue';
|
||||||
import { faCog, faPalette, faPlug, faUser, faListUl, faLock, faCommentSlash, faMusic, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes } from '@fortawesome/free-solid-svg-icons';
|
import { faCog, faPalette, faPlug, faUser, faListUl, faLock, faCommentSlash, faMusic, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faLaugh, faBell } from '@fortawesome/free-regular-svg-icons';
|
import { faLaugh, faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import { scroll } from '../../scripts/scroll';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormBase,
|
||||||
|
FormLink,
|
||||||
|
FormGroup,
|
||||||
|
FormButton,
|
||||||
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
page: {
|
page: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -72,21 +85,35 @@ export default defineComponent({
|
|||||||
case 'word-mute': return defineAsyncComponent(() => import('./word-mute.vue'));
|
case 'word-mute': return defineAsyncComponent(() => import('./word-mute.vue'));
|
||||||
case 'integration': return defineAsyncComponent(() => import('./integration.vue'));
|
case 'integration': return defineAsyncComponent(() => import('./integration.vue'));
|
||||||
case 'security': return defineAsyncComponent(() => import('./security.vue'));
|
case 'security': return defineAsyncComponent(() => import('./security.vue'));
|
||||||
|
case '2fa': return defineAsyncComponent(() => import('./2fa.vue'));
|
||||||
case 'api': return defineAsyncComponent(() => import('./api.vue'));
|
case 'api': return defineAsyncComponent(() => import('./api.vue'));
|
||||||
|
case 'apps': return defineAsyncComponent(() => import('./apps.vue'));
|
||||||
case 'other': return defineAsyncComponent(() => import('./other.vue'));
|
case 'other': return defineAsyncComponent(() => import('./other.vue'));
|
||||||
case 'general': return defineAsyncComponent(() => import('./general.vue'));
|
case 'general': return defineAsyncComponent(() => import('./general.vue'));
|
||||||
|
case 'email': return defineAsyncComponent(() => import('./email.vue'));
|
||||||
|
case 'email/address': return defineAsyncComponent(() => import('./email-address.vue'));
|
||||||
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
|
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
|
||||||
|
case 'theme/install': return defineAsyncComponent(() => import('./theme.install.vue'));
|
||||||
|
case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue'));
|
||||||
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
|
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
|
||||||
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
|
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
|
||||||
|
case 'deck': return defineAsyncComponent(() => import('./deck.vue'));
|
||||||
case 'plugins': return defineAsyncComponent(() => import('./plugins.vue'));
|
case 'plugins': return defineAsyncComponent(() => import('./plugins.vue'));
|
||||||
case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
|
case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
|
||||||
|
case 'account-info': return defineAsyncComponent(() => import('./account-info.vue'));
|
||||||
case 'regedit': return defineAsyncComponent(() => import('./regedit.vue'));
|
case 'regedit': return defineAsyncComponent(() => import('./regedit.vue'));
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(component, () => {
|
||||||
|
nextTick(() => {
|
||||||
|
scroll(el.value, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
narrow.value = el.value.offsetWidth < 650;
|
narrow.value = el.value.offsetWidth < 1025;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -100,7 +127,7 @@ export default defineComponent({
|
|||||||
store.dispatch('logout');
|
store.dispatch('logout');
|
||||||
location.href = '/';
|
location.href = '/';
|
||||||
},
|
},
|
||||||
faPalette, faPlug, faUser, faListUl, faLock, faLaugh, faCommentSlash, faMusic, faBell, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes,
|
faPalette, faPlug, faUser, faListUl, faLock, faLaugh, faCommentSlash, faMusic, faBell, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes, faEnvelope,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -108,63 +135,19 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.vvcocwet {
|
.vvcocwet {
|
||||||
> .nav {
|
|
||||||
> .menu {
|
|
||||||
margin: 16px 0;
|
|
||||||
|
|
||||||
> .label {
|
|
||||||
padding: 8px 32px;
|
|
||||||
font-size: 80%;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .item {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 0 32px;
|
|
||||||
line-height: 40px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
//background: var(--panel);
|
|
||||||
//border-bottom: solid 1px var(--divider);
|
|
||||||
transition: padding 0.2s ease, color 0.1s ease;
|
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
//border-top: solid 1px var(--divider);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: var(--accent);
|
|
||||||
padding-left: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
padding-left: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .icon {
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.wide {
|
&.wide {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
> .nav {
|
> .nav {
|
||||||
width: 30%;
|
width: 32%;
|
||||||
max-width: 300px;
|
box-sizing: border-box;
|
||||||
font-size: 0.95em;
|
border-right: solid 0.5px var(--divider);
|
||||||
border-right: solid 1px var(--divider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .main {
|
> .main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 32px;
|
|
||||||
--baseContentWidth: 100%;
|
--baseContentWidth: 100%;
|
||||||
|
|
||||||
::v-deep(._section) {
|
::v-deep(._section) {
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FormBase>
|
||||||
<div class="_section">
|
<FormLink @click="configure">{{ $t('notificationSetting') }}</FormLink>
|
||||||
<MkButton full primary @click="configure"><Fa :icon="faCog"/> {{ $t('notificationSetting') }}</MkButton>
|
<FormGroup>
|
||||||
</div>
|
<FormButton @click="readAllNotifications">{{ $t('markAsReadAllNotifications') }}</FormButton>
|
||||||
<div class="_section">
|
<FormButton @click="readAllUnreadNotes">{{ $t('markAsReadAllUnreadNotes') }}</FormButton>
|
||||||
<MkButton full @click="readAllNotifications">{{ $t('markAsReadAllNotifications') }}</MkButton>
|
<FormButton @click="readAllMessagingMessages">{{ $t('markAsReadAllTalkMessages') }}</FormButton>
|
||||||
<MkButton full @click="readAllUnreadNotes">{{ $t('markAsReadAllUnreadNotes') }}</MkButton>
|
</FormGroup>
|
||||||
<MkButton full @click="readAllMessagingMessages">{{ $t('markAsReadAllTalkMessages') }}</MkButton>
|
</FormBase>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faBell } from '@fortawesome/free-regular-svg-icons';
|
import { faBell } from '@fortawesome/free-regular-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormButton from '@/components/form/button.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import { notificationTypes } from '../../../types';
|
import { notificationTypes } from '../../../types';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormBase,
|
||||||
MkSwitch,
|
FormLink,
|
||||||
|
FormButton,
|
||||||
|
FormGroup,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
|
@ -1,40 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FormBase>
|
||||||
<div class="_section">
|
<FormSwitch :value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
|
||||||
<div class="_card">
|
|
||||||
<div class="_content">
|
|
||||||
<MkSwitch v-model:value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
|
|
||||||
{{ $t('showFeaturedNotesInTimeline') }}
|
{{ $t('showFeaturedNotesInTimeline') }}
|
||||||
</MkSwitch>
|
</FormSwitch>
|
||||||
</div>
|
|
||||||
</div>
|
<FormLink to="/settings/account-info">{{ $t('accountInfo') }}</FormLink>
|
||||||
</div>
|
|
||||||
<div class="_section">
|
<FormGroup>
|
||||||
<MkSwitch v-model:value="debug" @update:value="changeDebug">
|
<FormSwitch v-model:value="debug" @update:value="changeDebug">
|
||||||
DEBUG MODE
|
DEBUG MODE
|
||||||
</MkSwitch>
|
</FormSwitch>
|
||||||
<div v-if="debug">
|
<template v-if="debug">
|
||||||
<MkA to="/settings/regedit">RegEdit</MkA>
|
<FormLink to="/settings/regedit">RegEdit</FormLink>
|
||||||
<MkButton @click="taskmanager">Task Manager</MkButton>
|
<FormButton @click="taskmanager">Task Manager</FormButton>
|
||||||
</div>
|
</template>
|
||||||
</div>
|
</FormGroup>
|
||||||
</div>
|
</FormBase>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||||
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons';
|
import { faEllipsisH } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { debug } from '@/config';
|
import { debug } from '@/config';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkSelect,
|
FormBase,
|
||||||
MkSwitch,
|
FormSelect,
|
||||||
MkButton,
|
FormSwitch,
|
||||||
|
FormButton,
|
||||||
|
FormLink,
|
||||||
|
FormGroup,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
|
@ -1,36 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<FormBase>
|
||||||
<div class="_card">
|
<FormGroup>
|
||||||
<div class="_content">
|
<FormSwitch v-model:value="isLocked" @update:value="save()">{{ $t('makeFollowManuallyApprove') }}</FormSwitch>
|
||||||
<MkSwitch v-model:value="isLocked" @update:value="save()">{{ $t('makeFollowManuallyApprove') }}</MkSwitch>
|
<FormSwitch v-model:value="autoAcceptFollowed" :disabled="!isLocked" @update:value="save()">{{ $t('autoAcceptFollowed') }}</FormSwitch>
|
||||||
<MkSwitch v-model:value="autoAcceptFollowed" v-if="isLocked" @update:value="save()">{{ $t('autoAcceptFollowed') }}</MkSwitch>
|
<template #caption>{{ $t('lockedAccountInfo') }}</template>
|
||||||
</div>
|
</FormGroup>
|
||||||
<div class="_content">
|
<FormSwitch v-model:value="noCrawle" @update:value="save()">
|
||||||
<MkSwitch v-model:value="rememberNoteVisibility" @update:value="save()">{{ $t('rememberNoteVisibility') }}</MkSwitch>
|
{{ $t('noCrawle') }}
|
||||||
<MkSelect v-model:value="defaultNoteVisibility" style="margin-bottom: 8px;" v-if="!rememberNoteVisibility">
|
<template #desc>{{ $t('noCrawleDescription') }}</template>
|
||||||
|
</FormSwitch>
|
||||||
|
<FormSwitch v-model:value="rememberNoteVisibility" @update:value="save()">{{ $t('rememberNoteVisibility') }}</FormSwitch>
|
||||||
|
<FormGroup v-if="!rememberNoteVisibility">
|
||||||
<template #label>{{ $t('defaultNoteVisibility') }}</template>
|
<template #label>{{ $t('defaultNoteVisibility') }}</template>
|
||||||
|
<FormSelect v-model:value="defaultNoteVisibility">
|
||||||
<option value="public">{{ $t('_visibility.public') }}</option>
|
<option value="public">{{ $t('_visibility.public') }}</option>
|
||||||
<option value="home">{{ $t('_visibility.home') }}</option>
|
<option value="home">{{ $t('_visibility.home') }}</option>
|
||||||
<option value="followers">{{ $t('_visibility.followers') }}</option>
|
<option value="followers">{{ $t('_visibility.followers') }}</option>
|
||||||
<option value="specified">{{ $t('_visibility.specified') }}</option>
|
<option value="specified">{{ $t('_visibility.specified') }}</option>
|
||||||
</MkSelect>
|
</FormSelect>
|
||||||
<MkSwitch v-model:value="defaultNoteLocalOnly" v-if="!rememberNoteVisibility">{{ $t('_visibility.localOnly') }}</MkSwitch>
|
<FormSwitch v-model:value="defaultNoteLocalOnly">{{ $t('_visibility.localOnly') }}</FormSwitch>
|
||||||
</div>
|
</FormGroup>
|
||||||
</div>
|
</FormBase>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faLockOpen } from '@fortawesome/free-solid-svg-icons';
|
import { faLockOpen } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkSelect,
|
FormBase,
|
||||||
MkSwitch,
|
FormSelect,
|
||||||
|
FormGroup,
|
||||||
|
FormSwitch,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -43,6 +50,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
autoAcceptFollowed: false,
|
autoAcceptFollowed: false,
|
||||||
|
noCrawle: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -66,6 +74,7 @@ export default defineComponent({
|
|||||||
created() {
|
created() {
|
||||||
this.isLocked = this.$store.state.i.isLocked;
|
this.isLocked = this.$store.state.i.isLocked;
|
||||||
this.autoAcceptFollowed = this.$store.state.i.autoAcceptFollowed;
|
this.autoAcceptFollowed = this.$store.state.i.autoAcceptFollowed;
|
||||||
|
this.noCrawle = this.$store.state.i.noCrawle;
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -77,6 +86,7 @@ export default defineComponent({
|
|||||||
os.api('i/update', {
|
os.api('i/update', {
|
||||||
isLocked: !!this.isLocked,
|
isLocked: !!this.isLocked,
|
||||||
autoAcceptFollowed: !!this.autoAcceptFollowed,
|
autoAcceptFollowed: !!this.autoAcceptFollowed,
|
||||||
|
noCrawle: !!this.noCrawle,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,79 +1,67 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<FormBase class="llvierxe">
|
||||||
<div class="llvierxe _card">
|
<div class="header _formItem" :style="{ backgroundImage: $store.state.i.bannerUrl ? `url(${ $store.state.i.bannerUrl })` : null }" @click="changeBanner">
|
||||||
<div class="_title"><Fa :icon="faUser"/> {{ $t('profile') }}<small style="display: block; font-weight: normal; opacity: 0.6;">@{{ $store.state.i.username }}@{{ host }}</small></div>
|
|
||||||
<div class="_content">
|
|
||||||
<div class="header" :style="{ backgroundImage: $store.state.i.bannerUrl ? `url(${ $store.state.i.bannerUrl })` : null }" @click="changeBanner">
|
|
||||||
<MkAvatar class="avatar" :user="$store.state.i" :disable-preview="true" :disable-link="true" @click.stop="changeAvatar"/>
|
<MkAvatar class="avatar" :user="$store.state.i" :disable-preview="true" :disable-link="true" @click.stop="changeAvatar"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkInput v-model:value="name" :max="30">
|
<FormInput v-model:value="name" :max="30">
|
||||||
<span>{{ $t('_profile.name') }}</span>
|
<span>{{ $t('_profile.name') }}</span>
|
||||||
</MkInput>
|
</FormInput>
|
||||||
|
|
||||||
<MkTextarea v-model:value="description" :max="500">
|
<FormTextarea v-model:value="description" :max="500">
|
||||||
<span>{{ $t('_profile.description') }}</span>
|
<span>{{ $t('_profile.description') }}</span>
|
||||||
<template #desc>{{ $t('_profile.youCanIncludeHashtags') }}</template>
|
<template #desc>{{ $t('_profile.youCanIncludeHashtags') }}</template>
|
||||||
</MkTextarea>
|
</FormTextarea>
|
||||||
|
|
||||||
<MkInput v-model:value="location">
|
<FormInput v-model:value="location">
|
||||||
<span>{{ $t('location') }}</span>
|
<span>{{ $t('location') }}</span>
|
||||||
<template #prefix><Fa :icon="faMapMarkerAlt"/></template>
|
<template #prefix><Fa :icon="faMapMarkerAlt"/></template>
|
||||||
</MkInput>
|
</FormInput>
|
||||||
|
|
||||||
<MkInput v-model:value="birthday" type="date">
|
<FormInput v-model:value="birthday" type="date">
|
||||||
<template #title>{{ $t('birthday') }}</template>
|
<span>{{ $t('birthday') }}</span>
|
||||||
<template #prefix><Fa :icon="faBirthdayCake"/></template>
|
<template #prefix><Fa :icon="faBirthdayCake"/></template>
|
||||||
</MkInput>
|
</FormInput>
|
||||||
|
|
||||||
<details class="fields">
|
<FormGroup>
|
||||||
<summary>{{ $t('_profile.metadata') }}</summary>
|
<FormButton @click="editMetadata" primary>{{ $t('_profile.metadataEdit') }}</FormButton>
|
||||||
<div class="row">
|
<template #caption>{{ $t('_profile.metadataDescription') }}</template>
|
||||||
<MkInput v-model:value="fieldName0">{{ $t('_profile.metadataLabel') }}</MkInput>
|
</FormGroup>
|
||||||
<MkInput v-model:value="fieldValue0">{{ $t('_profile.metadataContent') }}</MkInput>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<MkInput v-model:value="fieldName1">{{ $t('_profile.metadataLabel') }}</MkInput>
|
|
||||||
<MkInput v-model:value="fieldValue1">{{ $t('_profile.metadataContent') }}</MkInput>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<MkInput v-model:value="fieldName2">{{ $t('_profile.metadataLabel') }}</MkInput>
|
|
||||||
<MkInput v-model:value="fieldValue2">{{ $t('_profile.metadataContent') }}</MkInput>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<MkInput v-model:value="fieldName3">{{ $t('_profile.metadataLabel') }}</MkInput>
|
|
||||||
<MkInput v-model:value="fieldValue3">{{ $t('_profile.metadataContent') }}</MkInput>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<MkSwitch v-model:value="isBot">{{ $t('flagAsBot') }}</MkSwitch>
|
<FormSwitch v-model:value="isCat">{{ $t('flagAsCat') }}<template #desc>{{ $t('flagAsCatDescription') }}</template></FormSwitch>
|
||||||
<MkSwitch v-model:value="isCat">{{ $t('flagAsCat') }}</MkSwitch>
|
|
||||||
</div>
|
<FormSwitch v-model:value="isBot">{{ $t('flagAsBot') }}<template #desc>{{ $t('flagAsBotDescription') }}</template></FormSwitch>
|
||||||
<div class="_footer">
|
|
||||||
<MkButton @click="save(true)" primary><Fa :icon="faSave"/> {{ $t('save') }}</MkButton>
|
<FormSwitch v-model:value="alwaysMarkNsfw">{{ $t('alwaysMarkSensitive') }}</FormSwitch>
|
||||||
</div>
|
|
||||||
</div>
|
<FormButton @click="save(true)" primary><Fa :icon="faSave"/> {{ $t('save') }}</FormButton>
|
||||||
</div>
|
</FormBase>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake } from '@fortawesome/free-solid-svg-icons';
|
import { faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faSave } from '@fortawesome/free-regular-svg-icons';
|
import { faSave } from '@fortawesome/free-regular-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormButton from '@/components/form/button.vue';
|
||||||
import MkInput from '@/components/ui/input.vue';
|
import FormInput from '@/components/form/input.vue';
|
||||||
import MkTextarea from '@/components/ui/textarea.vue';
|
import FormTextarea from '@/components/form/textarea.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
|
import FormTuple from '@/components/form/tuple.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import { host } from '@/config';
|
import { host } from '@/config';
|
||||||
import { selectFile } from '@/scripts/select-file';
|
import { selectFile } from '@/scripts/select-file';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormButton,
|
||||||
MkInput,
|
FormInput,
|
||||||
MkTextarea,
|
FormTextarea,
|
||||||
MkSwitch,
|
FormSwitch,
|
||||||
|
FormTuple,
|
||||||
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -101,6 +89,7 @@ export default defineComponent({
|
|||||||
bannerId: null,
|
bannerId: null,
|
||||||
isBot: false,
|
isBot: false,
|
||||||
isCat: false,
|
isCat: false,
|
||||||
|
alwaysMarkNsfw: false,
|
||||||
saving: false,
|
saving: false,
|
||||||
faSave, faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake
|
faSave, faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake
|
||||||
}
|
}
|
||||||
@ -115,6 +104,7 @@ export default defineComponent({
|
|||||||
this.bannerId = this.$store.state.i.bannerId;
|
this.bannerId = this.$store.state.i.bannerId;
|
||||||
this.isBot = this.$store.state.i.isBot;
|
this.isBot = this.$store.state.i.isBot;
|
||||||
this.isCat = this.$store.state.i.isCat;
|
this.isCat = this.$store.state.i.isCat;
|
||||||
|
this.alwaysMarkNsfw = this.$store.state.i.alwaysMarkNsfw;
|
||||||
|
|
||||||
this.fieldName0 = this.$store.state.i.fields[0] ? this.$store.state.i.fields[0].name : null;
|
this.fieldName0 = this.$store.state.i.fields[0] ? this.$store.state.i.fields[0].name : null;
|
||||||
this.fieldValue0 = this.$store.state.i.fields[0] ? this.$store.state.i.fields[0].value : null;
|
this.fieldValue0 = this.$store.state.i.fields[0] ? this.$store.state.i.fields[0].value : null;
|
||||||
@ -147,7 +137,60 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
save(notify) {
|
async editMetadata() {
|
||||||
|
const { canceled, result } = await os.form(this.$t('_profile.metadata'), {
|
||||||
|
fieldName0: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataLabel') + ' 1',
|
||||||
|
default: this.fieldName0,
|
||||||
|
},
|
||||||
|
fieldValue0: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataContent') + ' 1',
|
||||||
|
default: this.fieldValue0,
|
||||||
|
},
|
||||||
|
fieldName1: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataLabel') + ' 2',
|
||||||
|
default: this.fieldName1,
|
||||||
|
},
|
||||||
|
fieldValue1: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataContent') + ' 2',
|
||||||
|
default: this.fieldValue1,
|
||||||
|
},
|
||||||
|
fieldName2: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataLabel') + ' 3',
|
||||||
|
default: this.fieldName2,
|
||||||
|
},
|
||||||
|
fieldValue2: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataContent') + ' 3',
|
||||||
|
default: this.fieldValue2,
|
||||||
|
},
|
||||||
|
fieldName3: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataLabel') + ' 4',
|
||||||
|
default: this.fieldName3,
|
||||||
|
},
|
||||||
|
fieldValue3: {
|
||||||
|
type: 'string',
|
||||||
|
label: this.$t('_profile.metadataContent') + ' 4',
|
||||||
|
default: this.fieldValue3,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
this.fieldName0 = result.fieldName0;
|
||||||
|
this.fieldValue0 = result.fieldValue0;
|
||||||
|
this.fieldName1 = result.fieldName1;
|
||||||
|
this.fieldValue1 = result.fieldValue1;
|
||||||
|
this.fieldName2 = result.fieldName2;
|
||||||
|
this.fieldValue2 = result.fieldValue2;
|
||||||
|
this.fieldName3 = result.fieldName3;
|
||||||
|
this.fieldValue3 = result.fieldValue3;
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{ name: this.fieldName0, value: this.fieldValue0 },
|
{ name: this.fieldName0, value: this.fieldValue0 },
|
||||||
{ name: this.fieldName1, value: this.fieldValue1 },
|
{ name: this.fieldName1, value: this.fieldValue1 },
|
||||||
@ -155,6 +198,19 @@ export default defineComponent({
|
|||||||
{ name: this.fieldName3, value: this.fieldValue3 },
|
{ name: this.fieldName3, value: this.fieldValue3 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
os.api('i/update', {
|
||||||
|
fields,
|
||||||
|
}).then(i => {
|
||||||
|
os.success();
|
||||||
|
}).catch(err => {
|
||||||
|
os.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: err.id
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
save(notify) {
|
||||||
this.saving = true;
|
this.saving = true;
|
||||||
|
|
||||||
os.api('i/update', {
|
os.api('i/update', {
|
||||||
@ -162,9 +218,9 @@ export default defineComponent({
|
|||||||
description: this.description || null,
|
description: this.description || null,
|
||||||
location: this.location || null,
|
location: this.location || null,
|
||||||
birthday: this.birthday || null,
|
birthday: this.birthday || null,
|
||||||
fields,
|
|
||||||
isBot: !!this.isBot,
|
isBot: !!this.isBot,
|
||||||
isCat: !!this.isCat,
|
isCat: !!this.isCat,
|
||||||
|
alwaysMarkNsfw: !!this.alwaysMarkNsfw,
|
||||||
}).then(i => {
|
}).then(i => {
|
||||||
this.saving = false;
|
this.saving = false;
|
||||||
this.$store.state.i.avatarId = i.avatarId;
|
this.$store.state.i.avatarId = i.avatarId;
|
||||||
@ -189,7 +245,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.llvierxe {
|
.llvierxe {
|
||||||
> ._content {
|
|
||||||
> .header {
|
> .header {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
@ -215,16 +270,5 @@ export default defineComponent({
|
|||||||
box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.5);
|
box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .fields {
|
|
||||||
> .row {
|
|
||||||
> * {
|
|
||||||
display: inline-block;
|
|
||||||
width: 50%;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<FormBase>
|
||||||
<div class="_card">
|
<div class="_formItem">
|
||||||
<div class="_title"><Fa :icon="faLaugh"/> {{ $t('reaction') }}</div>
|
<div class="_formLabel">{{ $t('reactionSettingDescription') }}</div>
|
||||||
<div class="_content">
|
<div class="_formPanel">
|
||||||
<div class="_caption" style="padding: 0 8px 8px 8px;">{{ $t('reactionSettingDescription') }}</div>
|
|
||||||
<XDraggable class="zoaiodol" :list="reactions" animation="150" delay="100" delay-on-touch-only="true">
|
<XDraggable class="zoaiodol" :list="reactions" animation="150" delay="100" delay-on-touch-only="true">
|
||||||
<button class="_button item" v-for="reaction in reactions" :key="reaction" @click="remove(reaction, $event)">
|
<button class="_button item" v-for="reaction in reactions" :key="reaction" @click="remove(reaction, $event)">
|
||||||
<MkEmoji :emoji="reaction" :normal="true"/>
|
<MkEmoji :emoji="reaction" :normal="true"/>
|
||||||
@ -12,26 +11,25 @@
|
|||||||
<button>a</button>
|
<button>a</button>
|
||||||
</template>
|
</template>
|
||||||
</XDraggable>
|
</XDraggable>
|
||||||
<div class="_caption" style="padding: 8px;">{{ $t('reactionSettingDescription2') }} <button class="_textButton" @click="chooseEmoji">{{ $t('chooseEmoji') }}</button></div>
|
</div>
|
||||||
<MkRadios v-model="reactionPickerWidth">
|
<div class="_formCaption">{{ $t('reactionSettingDescription2') }} <button class="_textButton" @click="chooseEmoji">{{ $t('chooseEmoji') }}</button></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormRadios v-model="reactionPickerWidth">
|
||||||
<template #desc>{{ $t('width') }}</template>
|
<template #desc>{{ $t('width') }}</template>
|
||||||
<option :value="1">{{ $t('small') }}</option>
|
<option :value="1">{{ $t('small') }}</option>
|
||||||
<option :value="2">{{ $t('medium') }}</option>
|
<option :value="2">{{ $t('medium') }}</option>
|
||||||
<option :value="3">{{ $t('large') }}</option>
|
<option :value="3">{{ $t('large') }}</option>
|
||||||
</MkRadios>
|
</FormRadios>
|
||||||
<MkRadios v-model="reactionPickerHeight">
|
<FormRadios v-model="reactionPickerHeight">
|
||||||
<template #desc>{{ $t('height') }}</template>
|
<template #desc>{{ $t('height') }}</template>
|
||||||
<option :value="1">{{ $t('small') }}</option>
|
<option :value="1">{{ $t('small') }}</option>
|
||||||
<option :value="2">{{ $t('medium') }}</option>
|
<option :value="2">{{ $t('medium') }}</option>
|
||||||
<option :value="3">{{ $t('large') }}</option>
|
<option :value="3">{{ $t('large') }}</option>
|
||||||
</MkRadios>
|
</FormRadios>
|
||||||
</div>
|
<FormButton @click="preview"><Fa :icon="faEye"/> {{ $t('preview') }}</FormButton>
|
||||||
<div class="_footer">
|
<FormButton danger @click="setDefault"><Fa :icon="faUndo"/> {{ $t('default') }}</FormButton>
|
||||||
<MkButton inline @click="preview"><Fa :icon="faEye"/> {{ $t('preview') }}</MkButton>
|
</FormBase>
|
||||||
<MkButton inline @click="setDefault"><Fa :icon="faUndo"/> {{ $t('default') }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -39,20 +37,19 @@ import { defineComponent } from 'vue';
|
|||||||
import { faLaugh, faSave, faEye } from '@fortawesome/free-regular-svg-icons';
|
import { faLaugh, faSave, faEye } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { faUndo } from '@fortawesome/free-solid-svg-icons';
|
import { faUndo } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { VueDraggableNext } from 'vue-draggable-next';
|
import { VueDraggableNext } from 'vue-draggable-next';
|
||||||
import MkInput from '@/components/ui/input.vue';
|
import FormInput from '@/components/form/input.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormBase from '@/components/form/base.vue';
|
||||||
import MkRadios from '@/components/ui/radios.vue';
|
import FormButton from '@/components/form/button.vue';
|
||||||
import { emojiRegexWithCustom } from '../../../misc/emoji-regex';
|
|
||||||
import { defaultSettings } from '@/store';
|
import { defaultSettings } from '@/store';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkInput,
|
FormInput,
|
||||||
MkButton,
|
FormButton,
|
||||||
MkSwitch,
|
FormBase,
|
||||||
MkRadios,
|
FormRadios,
|
||||||
XDraggable: VueDraggableNext,
|
XDraggable: VueDraggableNext,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -62,7 +59,11 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
INFO: {
|
INFO: {
|
||||||
title: this.$t('reaction'),
|
title: this.$t('reaction'),
|
||||||
icon: faLaugh
|
icon: faLaugh,
|
||||||
|
action: {
|
||||||
|
icon: faEye,
|
||||||
|
handler: this.preview
|
||||||
|
}
|
||||||
},
|
},
|
||||||
reactions: JSON.parse(JSON.stringify(this.$store.state.settings.reactions)),
|
reactions: JSON.parse(JSON.stringify(this.$store.state.settings.reactions)),
|
||||||
faLaugh, faSave, faEye, faUndo
|
faLaugh, faSave, faEye, faUndo
|
||||||
@ -144,8 +145,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.zoaiodol {
|
.zoaiodol {
|
||||||
border: solid 1px var(--divider);
|
|
||||||
border-radius: var(--radius);
|
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
> .item {
|
> .item {
|
||||||
|
@ -1,29 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<FormBase>
|
||||||
<div class="_section">
|
|
||||||
<X2fa/>
|
<X2fa/>
|
||||||
|
<FormLink to="/settings/2fa"><template #icon><Fa :icon="faMobileAlt"/></template>{{ $t('twoStepAuthentication') }}</FormLink>
|
||||||
|
<FormButton primary @click="change()">{{ $t('changePassword') }}</FormButton>
|
||||||
|
<FormPagination :pagination="pagination">
|
||||||
|
<template #label>{{ $t('signinHistory') }}</template>
|
||||||
|
<template #default="{items}">
|
||||||
|
<div class="_formPanel timnmucd" v-for="item in items" :key="item.id">
|
||||||
|
<header>
|
||||||
|
<Fa class="icon succ" :icon="faCheck" v-if="item.success"/>
|
||||||
|
<Fa class="icon fail" :icon="faTimesCircle" v-else/>
|
||||||
|
<code class="ip _monospace">{{ item.ip }}</code>
|
||||||
|
<MkTime :time="item.createdAt" class="time"/>
|
||||||
|
</header>
|
||||||
</div>
|
</div>
|
||||||
<div class="_section">
|
</template>
|
||||||
<MkButton primary @click="change()" full>{{ $t('changePassword') }}</MkButton>
|
</FormPagination>
|
||||||
</div>
|
<FormGroup>
|
||||||
<div class="_section">
|
<FormButton danger @click="regenerateToken"><Fa :icon="faSyncAlt"/> {{ $t('regenerateLoginToken') }}</FormButton>
|
||||||
<MkButton class="_vMargin" primary @click="regenerateToken" full><Fa :icon="faSyncAlt"/> {{ $t('regenerateLoginToken') }}</MkButton>
|
<template #caption>{{ $t('regenerateLoginTokenDescription') }}</template>
|
||||||
<div class="_caption _vMargin" style="padding: 0 6px;">{{ $t('regenerateLoginTokenDescription') }}</div>
|
</FormGroup>
|
||||||
</div>
|
</FormBase>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faLock, faSyncAlt } from '@fortawesome/free-solid-svg-icons';
|
import { faCheck, faTimesCircle, faLock, faSyncAlt, faMobileAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormBase from '@/components/form/base.vue';
|
||||||
import X2fa from './security.2fa.vue';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import FormPagination from '@/components/form/pagination.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormBase,
|
||||||
X2fa,
|
FormLink,
|
||||||
|
FormButton,
|
||||||
|
FormPagination,
|
||||||
|
FormGroup,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -34,7 +50,11 @@ export default defineComponent({
|
|||||||
title: this.$t('security'),
|
title: this.$t('security'),
|
||||||
icon: faLock
|
icon: faLock
|
||||||
},
|
},
|
||||||
faLock, faSyncAlt
|
pagination: {
|
||||||
|
endpoint: 'i/signin-history',
|
||||||
|
limit: 5,
|
||||||
|
},
|
||||||
|
faLock, faSyncAlt, faCheck, faTimesCircle, faMobileAlt,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -98,3 +118,32 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.timnmucd {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
> header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
width: 1em;
|
||||||
|
margin-right: 0.75em;
|
||||||
|
|
||||||
|
&.succ {
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fail {
|
||||||
|
color: var(--error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .time {
|
||||||
|
margin-left: auto;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,41 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<FormBase>
|
||||||
<div class="_card">
|
<FormTextarea v-model:value="items" tall>
|
||||||
<div class="_content">
|
|
||||||
<MkTextarea v-model:value="items" tall>
|
|
||||||
<span>{{ $t('sidebar') }}</span>
|
<span>{{ $t('sidebar') }}</span>
|
||||||
<template #desc><button class="_textButton" @click="addItem">{{ $t('addItem') }}</button></template>
|
<template #desc><button class="_textButton" @click="addItem">{{ $t('addItem') }}</button></template>
|
||||||
</MkTextarea>
|
</FormTextarea>
|
||||||
</div>
|
|
||||||
<div class="_content">
|
<FormRadios v-model="sidebarDisplay">
|
||||||
<div>{{ $t('display') }}</div>
|
<template #desc>{{ $t('display') }}</template>
|
||||||
<MkRadio v-model="sidebarDisplay" value="full">{{ $t('_sidebar.full') }}</MkRadio>
|
<option value="full">{{ $t('_sidebar.full') }}</option>
|
||||||
<MkRadio v-model="sidebarDisplay" value="icon">{{ $t('_sidebar.icon') }}</MkRadio>
|
<option value="icon">{{ $t('_sidebar.icon') }}</option>
|
||||||
<!-- <MkRadio v-model="sidebarDisplay" value="hide" disabled>{{ $t('_sidebar.hide') }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると、別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
|
<!-- <MkRadio v-model="sidebarDisplay" value="hide" disabled>{{ $t('_sidebar.hide') }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると、別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
|
||||||
</div>
|
</FormRadios>
|
||||||
<div class="_footer">
|
|
||||||
<MkButton inline @click="save()" primary><Fa :icon="faSave"/> {{ $t('save') }}</MkButton>
|
<FormButton @click="save()" primary><Fa :icon="faSave"/> {{ $t('save') }}</FormButton>
|
||||||
<MkButton inline @click="reset()"><Fa :icon="faRedo"/> {{ $t('default') }}</MkButton>
|
<FormButton @click="reset()" danger><Fa :icon="faRedo"/> {{ $t('default') }}</FormButton>
|
||||||
</div>
|
</FormBase>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faListUl, faSave, faRedo } from '@fortawesome/free-solid-svg-icons';
|
import { faListUl, faSave, faRedo } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkTextarea from '@/components/ui/textarea.vue';
|
import FormTextarea from '@/components/form/textarea.vue';
|
||||||
import MkRadio from '@/components/ui/radio.vue';
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import { defaultDeviceUserSettings } from '@/store';
|
import { defaultDeviceUserSettings } from '@/store';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { sidebarDef } from '@/sidebar';
|
import { sidebarDef } from '@/sidebar';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormBase,
|
||||||
MkTextarea,
|
FormButton,
|
||||||
MkRadio,
|
FormTextarea,
|
||||||
|
FormRadios,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -102,7 +102,3 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
@ -1,62 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<FormBase>
|
||||||
<div class="_card">
|
<FormRange v-model:value="masterVolume" :min="0" :max="1" :step="0.05">
|
||||||
<div class="_title"><Fa :icon="faMusic"/> {{ $t('sounds') }}</div>
|
<template #label><Fa :icon="volumeIcon" :key="volumeIcon"/> {{ $t('masterVolume') }}</template>
|
||||||
<div class="_content">
|
</FormRange>
|
||||||
<MkRange v-model:value="sfxVolume" :min="0" :max="1" :step="0.1">
|
|
||||||
<Fa slot="icon" :icon="volumeIcon"/>
|
<FormGroup>
|
||||||
<span slot="title">{{ $t('volume') }}</span>
|
<template #label>{{ $t('sounds') }}</template>
|
||||||
</MkRange>
|
<FormButton v-for="type in Object.keys(sounds)" :key="type" :center="false" @click="edit(type)">
|
||||||
</div>
|
{{ $t('_sfx.' + type) }}
|
||||||
<div class="_content">
|
<template #suffix>{{ sounds[type].type || $t('none') }}</template>
|
||||||
<MkSelect v-model:value="sfxNote">
|
<template #suffixIcon><Fa :icon="faChevronDown"/></template>
|
||||||
<template #label>{{ $t('_sfx.note') }}</template>
|
</FormButton>
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
</FormGroup>
|
||||||
<template #text><button class="_textButton" @click="listen(sfxNote)" v-if="sfxNote"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
<FormButton @click="reset()" danger><Fa :icon="faRedo"/> {{ $t('default') }}</FormButton>
|
||||||
<MkSelect v-model:value="sfxNoteMy">
|
</FormBase>
|
||||||
<template #label>{{ $t('_sfx.noteMy') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxNoteMy)" v-if="sfxNoteMy"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model:value="sfxNotification">
|
|
||||||
<template #label>{{ $t('_sfx.notification') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxNotification)" v-if="sfxNotification"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model:value="sfxChat">
|
|
||||||
<template #label>{{ $t('_sfx.chat') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxChat)" v-if="sfxChat"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model:value="sfxChatBg">
|
|
||||||
<template #label>{{ $t('_sfx.chatBg') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxChatBg)" v-if="sfxChatBg"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model:value="sfxAntenna">
|
|
||||||
<template #label>{{ $t('_sfx.antenna') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxAntenna)" v-if="sfxAntenna"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
<MkSelect v-model:value="sfxChannel">
|
|
||||||
<template #label>{{ $t('_sfx.channel') }}</template>
|
|
||||||
<option v-for="sound in sounds" :value="sound" :key="sound">{{ sound || $t('none') }}</option>
|
|
||||||
<template #text><button class="_textButton" @click="listen(sfxChannel)" v-if="sfxChannel"><Fa :icon="faPlay"/> {{ $t('listen') }}</button></template>
|
|
||||||
</MkSelect>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faMusic, faPlay, faVolumeUp, faVolumeMute } from '@fortawesome/free-solid-svg-icons';
|
import { faMusic, faPlay, faVolumeUp, faVolumeMute, faChevronDown, faRedo } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import FormRange from '@/components/form/range.vue';
|
||||||
import MkRange from '@/components/ui/range.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import { device, defaultDeviceSettings } from '@/cold-storage';
|
||||||
|
import { playFile } from '@/scripts/sound';
|
||||||
|
|
||||||
const sounds = [
|
const soundsTypes = [
|
||||||
null,
|
null,
|
||||||
'syuilo/up',
|
'syuilo/up',
|
||||||
'syuilo/down',
|
'syuilo/down',
|
||||||
@ -73,6 +46,8 @@ const sounds = [
|
|||||||
'syuilo/square-pico',
|
'syuilo/square-pico',
|
||||||
'syuilo/reverved',
|
'syuilo/reverved',
|
||||||
'syuilo/ryukyu',
|
'syuilo/ryukyu',
|
||||||
|
'syuilo/kick',
|
||||||
|
'syuilo/snare',
|
||||||
'aisha/1',
|
'aisha/1',
|
||||||
'aisha/2',
|
'aisha/2',
|
||||||
'aisha/3',
|
'aisha/3',
|
||||||
@ -82,71 +57,98 @@ const sounds = [
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkSelect,
|
FormSelect,
|
||||||
MkRange,
|
FormButton,
|
||||||
|
FormBase,
|
||||||
|
FormRange,
|
||||||
|
FormGroup,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sounds,
|
INFO: {
|
||||||
faMusic, faPlay, faVolumeUp, faVolumeMute,
|
title: this.$t('sounds'),
|
||||||
|
icon: faMusic
|
||||||
|
},
|
||||||
|
sounds: {},
|
||||||
|
faMusic, faPlay, faVolumeUp, faVolumeMute, faChevronDown, faRedo,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
sfxVolume: {
|
masterVolume: { // TODO: (外部)関数にcomputedを使うのはアレなので直す
|
||||||
get() { return this.$store.state.device.sfxVolume; },
|
get() { return device.get('sound_masterVolume'); },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxVolume', value: parseFloat(value, 10) }); }
|
set(value) { device.set('sound_masterVolume', value); }
|
||||||
},
|
},
|
||||||
|
volumeIcon() {
|
||||||
sfxNote: {
|
return this.masterVolume === 0 ? faVolumeMute : faVolumeUp;
|
||||||
get() { return this.$store.state.device.sfxNote; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxNote', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxNoteMy: {
|
|
||||||
get() { return this.$store.state.device.sfxNoteMy; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxNoteMy', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxNotification: {
|
|
||||||
get() { return this.$store.state.device.sfxNotification; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxNotification', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxChat: {
|
|
||||||
get() { return this.$store.state.device.sfxChat; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxChat', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxChatBg: {
|
|
||||||
get() { return this.$store.state.device.sfxChatBg; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxChatBg', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxAntenna: {
|
|
||||||
get() { return this.$store.state.device.sfxAntenna; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxAntenna', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
sfxChannel: {
|
|
||||||
get() { return this.$store.state.device.sfxChannel; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'sfxChannel', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
volumeIcon: {
|
|
||||||
get() {
|
|
||||||
return this.sfxVolume === 0 ? faVolumeMute : faVolumeUp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.sounds.note = device.get('sound_note');
|
||||||
|
this.sounds.noteMy = device.get('sound_noteMy');
|
||||||
|
this.sounds.notification = device.get('sound_notification');
|
||||||
|
this.sounds.chat = device.get('sound_chat');
|
||||||
|
this.sounds.chatBg = device.get('sound_chatBg');
|
||||||
|
this.sounds.antenna = device.get('sound_antenna');
|
||||||
|
this.sounds.channel = device.get('sound_channel');
|
||||||
|
this.sounds.reversiPutBlack = device.get('sound_reversiPutBlack');
|
||||||
|
this.sounds.reversiPutWhite = device.get('sound_reversiPutWhite');
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
listen(sound) {
|
async edit(type) {
|
||||||
const audio = new Audio(`/assets/sounds/${sound}.mp3`);
|
const { canceled, result } = await os.form(this.$t('_sfx.' + type), {
|
||||||
audio.volume = this.$store.state.device.sfxVolume;
|
type: {
|
||||||
audio.play();
|
type: 'enum',
|
||||||
|
enum: soundsTypes.map(x => ({
|
||||||
|
value: x,
|
||||||
|
label: x == null ? this.$t('none') : x,
|
||||||
|
})),
|
||||||
|
label: this.$t('sound'),
|
||||||
|
default: this.sounds[type].type,
|
||||||
},
|
},
|
||||||
|
volume: {
|
||||||
|
type: 'range',
|
||||||
|
mim: 0,
|
||||||
|
max: 1,
|
||||||
|
step: 0.05,
|
||||||
|
label: this.$t('volume'),
|
||||||
|
default: this.sounds[type].volume
|
||||||
|
},
|
||||||
|
listen: {
|
||||||
|
type: 'button',
|
||||||
|
content: this.$t('listen'),
|
||||||
|
action: (_, values) => {
|
||||||
|
playFile(values.type, values.volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
const v = {
|
||||||
|
type: result.type,
|
||||||
|
volume: result.volume,
|
||||||
|
};
|
||||||
|
|
||||||
|
device.set('sound_' + type, v);
|
||||||
|
this.sounds[type] = v;
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
for (const sound of Object.keys(this.sounds)) {
|
||||||
|
const v = defaultDeviceSettings['sound_' + sound];
|
||||||
|
device.set('sound_' + sound, v);
|
||||||
|
this.sounds[sound] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
106
src/client/pages/settings/theme.install.vue
Normal file
106
src/client/pages/settings/theme.install.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
<FormGroup>
|
||||||
|
<FormTextarea v-model:value="installThemeCode">
|
||||||
|
<span>{{ $t('_theme.code') }}</span>
|
||||||
|
</FormTextarea>
|
||||||
|
<FormButton @click="() => preview(installThemeCode)" :disabled="installThemeCode == null" inline><Fa :icon="faEye"/> {{ $t('preview') }}</FormButton>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormButton @click="() => install(installThemeCode)" :disabled="installThemeCode == null" primary inline><Fa :icon="faCheck"/> {{ $t('install') }}</FormButton>
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as JSON5 from 'json5';
|
||||||
|
import FormTextarea from '@/components/form/textarea.vue';
|
||||||
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import { applyTheme, validateTheme } from '@/scripts/theme';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormTextarea,
|
||||||
|
FormSelect,
|
||||||
|
FormRadios,
|
||||||
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
FormLink,
|
||||||
|
FormButton,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('_theme.install'),
|
||||||
|
icon: faDownload
|
||||||
|
},
|
||||||
|
installThemeCode: null,
|
||||||
|
faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
parseThemeCode(code) {
|
||||||
|
let theme;
|
||||||
|
|
||||||
|
try {
|
||||||
|
theme = JSON5.parse(code);
|
||||||
|
} catch (e) {
|
||||||
|
os.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: this.$t('_theme.invalid')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!validateTheme(theme)) {
|
||||||
|
os.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: this.$t('_theme.invalid')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.$store.state.device.themes.some(t => t.id === theme.id)) {
|
||||||
|
os.dialog({
|
||||||
|
type: 'info',
|
||||||
|
text: this.$t('_theme.alreadyInstalled')
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return theme;
|
||||||
|
},
|
||||||
|
|
||||||
|
preview(code) {
|
||||||
|
const theme = this.parseThemeCode(code);
|
||||||
|
if (theme) applyTheme(theme, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
install(code) {
|
||||||
|
const theme = this.parseThemeCode(code);
|
||||||
|
if (!theme) return;
|
||||||
|
const themes = this.$store.state.device.themes.concat(theme);
|
||||||
|
this.$store.commit('device/set', {
|
||||||
|
key: 'themes', value: themes
|
||||||
|
});
|
||||||
|
os.dialog({
|
||||||
|
type: 'success',
|
||||||
|
text: this.$t('_theme.installed', { name: theme.name })
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
103
src/client/pages/settings/theme.manage.vue
Normal file
103
src/client/pages/settings/theme.manage.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<FormBase>
|
||||||
|
<FormSelect v-model:value="selectedThemeId">
|
||||||
|
<template #label>{{ $t('installedThemes') }}</template>
|
||||||
|
<option v-for="x in installedThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
<optgroup :label="$t('builtinThemes')">
|
||||||
|
<option v-for="x in builtinThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</optgroup>
|
||||||
|
</FormSelect>
|
||||||
|
<template v-if="selectedTheme">
|
||||||
|
<FormInput readonly :value="selectedTheme.author">
|
||||||
|
<span>{{ $t('author') }}</span>
|
||||||
|
</FormInput>
|
||||||
|
<FormTextarea readonly tall :value="selectedThemeCode">
|
||||||
|
<span>{{ $t('_theme.code') }}</span>
|
||||||
|
<template #desc><button @click="copyThemeCode()" class="_textButton">{{ $t('copy') }}</button></template>
|
||||||
|
</FormTextarea>
|
||||||
|
<FormButton @click="uninstall()" danger v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><Fa :icon="faTrashAlt"/> {{ $t('uninstall') }}</FormButton>
|
||||||
|
</template>
|
||||||
|
</FormBase>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as JSON5 from 'json5';
|
||||||
|
import FormTextarea from '@/components/form/textarea.vue';
|
||||||
|
import FormSelect from '@/components/form/select.vue';
|
||||||
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormGroup from '@/components/form/group.vue';
|
||||||
|
import FormInput from '@/components/form/input.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import { Theme, builtinThemes } from '@/scripts/theme';
|
||||||
|
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||||
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
FormTextarea,
|
||||||
|
FormSelect,
|
||||||
|
FormRadios,
|
||||||
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
FormInput,
|
||||||
|
FormButton,
|
||||||
|
},
|
||||||
|
|
||||||
|
emits: ['info'],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: this.$t('_theme.manage'),
|
||||||
|
icon: faFolderOpen
|
||||||
|
},
|
||||||
|
builtinThemes,
|
||||||
|
selectedThemeId: null,
|
||||||
|
faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
themes(): Theme[] {
|
||||||
|
return builtinThemes.concat(this.$store.state.device.themes);
|
||||||
|
},
|
||||||
|
|
||||||
|
installedThemes(): Theme[] {
|
||||||
|
return this.$store.state.device.themes;
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedTheme() {
|
||||||
|
if (this.selectedThemeId == null) return null;
|
||||||
|
return this.themes.find(x => x.id === this.selectedThemeId);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedThemeCode() {
|
||||||
|
if (this.selectedTheme == null) return null;
|
||||||
|
return JSON5.stringify(this.selectedTheme, null, '\t');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$emit('info', this.INFO);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
copyThemeCode() {
|
||||||
|
copyToClipboard(this.selectedThemeCode);
|
||||||
|
os.success();
|
||||||
|
},
|
||||||
|
|
||||||
|
uninstall() {
|
||||||
|
const theme = this.selectedTheme;
|
||||||
|
const themes = this.$store.state.device.themes.filter(t => t.id != theme.id);
|
||||||
|
this.$store.commit('device/set', {
|
||||||
|
key: 'themes', value: themes
|
||||||
|
});
|
||||||
|
os.success();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,7 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="">
|
<FormBase>
|
||||||
<div class="rfqxtzch _card _vMargin">
|
<FormSelect v-model:value="lightTheme" v-if="!darkMode">
|
||||||
<div class="_content">
|
<template #label>{{ $t('themeForLightMode') }}</template>
|
||||||
|
<optgroup :label="$t('lightThemes')">
|
||||||
|
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup :label="$t('darkThemes')">
|
||||||
|
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</optgroup>
|
||||||
|
</FormSelect>
|
||||||
|
<FormSelect v-model:value="darkTheme" v-else>
|
||||||
|
<template #label>{{ $t('themeForDarkMode') }}</template>
|
||||||
|
<optgroup :label="$t('darkThemes')">
|
||||||
|
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup :label="$t('lightThemes')">
|
||||||
|
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||||
|
</optgroup>
|
||||||
|
</FormSelect>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<div class="rfqxtzch _formItem _formPanel">
|
||||||
<div class="darkMode" :class="{ disabled: syncDeviceDarkMode }">
|
<div class="darkMode" :class="{ disabled: syncDeviceDarkMode }">
|
||||||
<div class="toggleWrapper">
|
<div class="toggleWrapper">
|
||||||
<input type="checkbox" class="dn" id="dn" v-model="darkMode" :disabled="syncDeviceDarkMode"/>
|
<input type="checkbox" class="dn" id="dn" v-model="darkMode" :disabled="syncDeviceDarkMode"/>
|
||||||
@ -23,85 +42,47 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="_content">
|
<FormSwitch v-model:value="syncDeviceDarkMode">{{ $t('syncDeviceDarkMode') }}</FormSwitch>
|
||||||
<MkSwitch v-model:value="syncDeviceDarkMode">{{ $t('syncDeviceDarkMode') }}</MkSwitch>
|
</FormGroup>
|
||||||
</div>
|
|
||||||
</div>
|
<FormButton primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</FormButton>
|
||||||
<div class="_card _vMargin">
|
<FormButton primary v-else @click="wallpaper = null">{{ $t('removeWallpaper') }}</FormButton>
|
||||||
<div class="_content">
|
|
||||||
<MkSelect v-model:value="lightTheme">
|
<FormGroup>
|
||||||
<template #label>{{ $t('themeForLightMode') }}</template>
|
<FormLink to="https://assets.msky.cafe/theme/list" external>{{ $t('_theme.explore') }}</FormLink>
|
||||||
<optgroup :label="$t('lightThemes')">
|
<FormLink to="/theme-editor">{{ $t('_theme.make') }}</FormLink>
|
||||||
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
</FormGroup>
|
||||||
</optgroup>
|
|
||||||
<optgroup :label="$t('darkThemes')">
|
<FormLink to="/settings/theme/install"><template #icon><Fa :icon="faDownload"/></template>{{ $t('_theme.install') }}</FormLink>
|
||||||
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
|
||||||
</optgroup>
|
<FormLink to="/settings/theme/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $t('_theme.manage') }}</FormLink>
|
||||||
</MkSelect>
|
</FormBase>
|
||||||
<MkSelect v-model:value="darkTheme">
|
|
||||||
<template #label>{{ $t('themeForDarkMode') }}</template>
|
|
||||||
<optgroup :label="$t('darkThemes')">
|
|
||||||
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup :label="$t('lightThemes')">
|
|
||||||
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
|
||||||
</optgroup>
|
|
||||||
</MkSelect>
|
|
||||||
<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>・<MkA to="/theme-editor" class="_link">{{ $t('_theme.make') }}</MkA>
|
|
||||||
</div>
|
|
||||||
<div class="_content">
|
|
||||||
<MkButton primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</MkButton>
|
|
||||||
<MkButton primary v-else @click="wallpaper = null">{{ $t('removeWallpaper') }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="_card _vMargin">
|
|
||||||
<div class="_title"><Fa :icon="faDownload"/> {{ $t('_theme.install') }}</div>
|
|
||||||
<div class="_content">
|
|
||||||
<MkTextarea v-model:value="installThemeCode">
|
|
||||||
<span>{{ $t('_theme.code') }}</span>
|
|
||||||
</MkTextarea>
|
|
||||||
<MkButton @click="() => install(installThemeCode)" :disabled="installThemeCode == null" primary inline><Fa :icon="faCheck"/> {{ $t('install') }}</MkButton>
|
|
||||||
<MkButton @click="() => preview(installThemeCode)" :disabled="installThemeCode == null" inline><Fa :icon="faEye"/> {{ $t('preview') }}</MkButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="_card _vMargin">
|
|
||||||
<div class="_title"><Fa :icon="faFolderOpen"/> {{ $t('_theme.manage') }}</div>
|
|
||||||
<div class="_content">
|
|
||||||
<MkSelect v-model:value="selectedThemeId">
|
|
||||||
<option v-for="x in installedThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
|
||||||
</MkSelect>
|
|
||||||
<template v-if="selectedTheme">
|
|
||||||
<MkTextarea readonly tall :value="selectedThemeCode">
|
|
||||||
<span>{{ $t('_theme.code') }}</span>
|
|
||||||
<template #desc><button @click="copyThemeCode()" class="_textButton">{{ $t('copy') }}</button></template>
|
|
||||||
</MkTextarea>
|
|
||||||
<MkButton @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><Fa :icon="faTrashAlt"/> {{ $t('uninstall') }}</MkButton>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons';
|
import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||||
import * as JSON5 from 'json5';
|
import FormSwitch from '@/components/form/switch.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormSelect from '@/components/form/select.vue';
|
||||||
import MkSelect from '@/components/ui/select.vue';
|
import FormRadios from '@/components/form/radios.vue';
|
||||||
import MkSwitch from '@/components/ui/switch.vue';
|
import FormBase from '@/components/form/base.vue';
|
||||||
import MkTextarea from '@/components/ui/textarea.vue';
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import { Theme, builtinThemes, applyTheme, validateTheme } from '@/scripts/theme';
|
import FormLink from '@/components/form/link.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
|
import { Theme, builtinThemes, applyTheme } from '@/scripts/theme';
|
||||||
import { selectFile } from '@/scripts/select-file';
|
import { selectFile } from '@/scripts/select-file';
|
||||||
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormSwitch,
|
||||||
MkSelect,
|
FormSelect,
|
||||||
MkSwitch,
|
FormRadios,
|
||||||
MkTextarea,
|
FormBase,
|
||||||
|
FormGroup,
|
||||||
|
FormLink,
|
||||||
|
FormButton,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['info'],
|
emits: ['info'],
|
||||||
@ -113,8 +94,6 @@ export default defineComponent({
|
|||||||
icon: faPalette
|
icon: faPalette
|
||||||
},
|
},
|
||||||
builtinThemes,
|
builtinThemes,
|
||||||
installThemeCode: null,
|
|
||||||
selectedThemeId: null,
|
|
||||||
wallpaper: localStorage.getItem('wallpaper'),
|
wallpaper: localStorage.getItem('wallpaper'),
|
||||||
faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye
|
faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye
|
||||||
}
|
}
|
||||||
@ -156,16 +135,6 @@ export default defineComponent({
|
|||||||
get() { return this.$store.state.device.syncDeviceDarkMode; },
|
get() { return this.$store.state.device.syncDeviceDarkMode; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'syncDeviceDarkMode', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'syncDeviceDarkMode', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
selectedTheme() {
|
|
||||||
if (this.selectedThemeId == null) return null;
|
|
||||||
return this.themes.find(x => x.id === this.selectedThemeId);
|
|
||||||
},
|
|
||||||
|
|
||||||
selectedThemeCode() {
|
|
||||||
if (this.selectedTheme == null) return null;
|
|
||||||
return JSON5.stringify(this.selectedTheme, null, '\t');
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -207,75 +176,14 @@ export default defineComponent({
|
|||||||
this.wallpaper = file.url;
|
this.wallpaper = file.url;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
copyThemeCode() {
|
|
||||||
copyToClipboard(this.selectedThemeCode);
|
|
||||||
os.success();
|
|
||||||
},
|
|
||||||
|
|
||||||
parseThemeCode(code) {
|
|
||||||
let theme;
|
|
||||||
|
|
||||||
try {
|
|
||||||
theme = JSON5.parse(code);
|
|
||||||
} catch (e) {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: this.$t('_theme.invalid')
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!validateTheme(theme)) {
|
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: this.$t('_theme.invalid')
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.$store.state.device.themes.some(t => t.id === theme.id)) {
|
|
||||||
os.dialog({
|
|
||||||
type: 'info',
|
|
||||||
text: this.$t('_theme.alreadyInstalled')
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return theme;
|
|
||||||
},
|
|
||||||
|
|
||||||
preview(code) {
|
|
||||||
const theme = this.parseThemeCode(code);
|
|
||||||
if (theme) applyTheme(theme, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
install(code) {
|
|
||||||
const theme = this.parseThemeCode(code);
|
|
||||||
if (!theme) return;
|
|
||||||
const themes = this.$store.state.device.themes.concat(theme);
|
|
||||||
this.$store.commit('device/set', {
|
|
||||||
key: 'themes', value: themes
|
|
||||||
});
|
|
||||||
os.dialog({
|
|
||||||
type: 'success',
|
|
||||||
text: this.$t('_theme.installed', { name: theme.name })
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
uninstall() {
|
|
||||||
const theme = this.selectedTheme;
|
|
||||||
const themes = this.$store.state.device.themes.filter(t => t.id != theme.id);
|
|
||||||
this.$store.commit('device/set', {
|
|
||||||
key: 'themes', value: themes
|
|
||||||
});
|
|
||||||
os.success();
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.rfqxtzch {
|
.rfqxtzch {
|
||||||
> ._content {
|
padding: 16px;
|
||||||
|
|
||||||
> .darkMode {
|
> .darkMode {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 32px 0;
|
padding: 32px 0;
|
||||||
@ -497,5 +405,4 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,47 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<div>
|
||||||
<div class="_card">
|
|
||||||
<MkTab v-model:value="tab">
|
<MkTab v-model:value="tab">
|
||||||
<option value="soft">{{ $t('_wordMute.soft') }}</option>
|
<option value="soft">{{ $t('_wordMute.soft') }}</option>
|
||||||
<option value="hard">{{ $t('_wordMute.hard') }}</option>
|
<option value="hard">{{ $t('_wordMute.hard') }}</option>
|
||||||
</MkTab>
|
</MkTab>
|
||||||
<div class="_content">
|
<FormBase>
|
||||||
|
<div class="_formItem">
|
||||||
<div v-show="tab === 'soft'">
|
<div v-show="tab === 'soft'">
|
||||||
<MkInfo>{{ $t('_wordMute.softDescription') }}</MkInfo>
|
<MkInfo>{{ $t('_wordMute.softDescription') }}</MkInfo>
|
||||||
<MkTextarea v-model:value="softMutedWords">
|
<FormTextarea v-model:value="softMutedWords">
|
||||||
<span>{{ $t('_wordMute.muteWords') }}</span>
|
<span>{{ $t('_wordMute.muteWords') }}</span>
|
||||||
<template #desc>{{ $t('_wordMute.muteWordsDescription') }}<br>{{ $t('_wordMute.muteWordsDescription2') }}</template>
|
<template #desc>{{ $t('_wordMute.muteWordsDescription') }}<br>{{ $t('_wordMute.muteWordsDescription2') }}</template>
|
||||||
</MkTextarea>
|
</FormTextarea>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="tab === 'hard'">
|
<div v-show="tab === 'hard'">
|
||||||
<MkInfo>{{ $t('_wordMute.hardDescription') }}</MkInfo>
|
<MkInfo>{{ $t('_wordMute.hardDescription') }}</MkInfo>
|
||||||
<MkTextarea v-model:value="hardMutedWords" style="margin-bottom: 16px;">
|
<FormTextarea v-model:value="hardMutedWords">
|
||||||
<span>{{ $t('_wordMute.muteWords') }}</span>
|
<span>{{ $t('_wordMute.muteWords') }}</span>
|
||||||
<template #desc>{{ $t('_wordMute.muteWordsDescription') }}<br>{{ $t('_wordMute.muteWordsDescription2') }}</template>
|
<template #desc>{{ $t('_wordMute.muteWordsDescription') }}<br>{{ $t('_wordMute.muteWordsDescription2') }}</template>
|
||||||
</MkTextarea>
|
</FormTextarea>
|
||||||
<div v-if="hardWordMutedNotesCount != null" class="_caption">{{ $t('_wordMute.mutedNotes') }}: {{ hardWordMutedNotesCount | number }}</div>
|
<FormKeyValueView v-if="hardWordMutedNotesCount != null">
|
||||||
</div>
|
<template #key>{{ $t('_wordMute.mutedNotes') }}</template>
|
||||||
</div>
|
<template #value>{{ number(hardWordMutedNotesCount) }}</template>
|
||||||
<div class="_footer">
|
</FormKeyValueView>
|
||||||
<MkButton @click="save()" primary inline :disabled="!changed"><Fa :icon="faSave"/> {{ $t('save') }}</MkButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<FormButton @click="save()" primary inline :disabled="!changed"><Fa :icon="faSave"/> {{ $t('save') }}</FormButton>
|
||||||
|
</FormBase>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faCommentSlash, faSave } from '@fortawesome/free-solid-svg-icons';
|
import { faCommentSlash, faSave } from '@fortawesome/free-solid-svg-icons';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import FormTextarea from '@/components/form/textarea.vue';
|
||||||
import MkTextarea from '@/components/ui/textarea.vue';
|
import FormBase from '@/components/form/base.vue';
|
||||||
|
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||||
|
import FormButton from '@/components/form/button.vue';
|
||||||
import MkTab from '@/components/tab.vue';
|
import MkTab from '@/components/tab.vue';
|
||||||
import MkInfo from '@/components/ui/info.vue';
|
import MkInfo from '@/components/ui/info.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import number from '@/filters/number';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkButton,
|
FormBase,
|
||||||
MkTextarea,
|
FormButton,
|
||||||
|
FormTextarea,
|
||||||
|
FormKeyValueView,
|
||||||
MkTab,
|
MkTab,
|
||||||
MkInfo,
|
MkInfo,
|
||||||
},
|
},
|
||||||
@ -97,6 +103,8 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
this.changed = false;
|
this.changed = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
number
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="_section">
|
<div>
|
||||||
<MkPagination :pagination="pagination" #default="{items}" class="mk-following-or-followers _content" ref="list">
|
<MkPagination :pagination="pagination" #default="{items}" class="mk-following-or-followers _content" ref="list">
|
||||||
<div class="users">
|
<div class="users">
|
||||||
<MkUserInfo class="user" v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :user="user" :key="user.id"/>
|
<MkUserInfo class="user" v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :user="user" :key="user.id"/>
|
||||||
|
@ -1,15 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<MkContainer>
|
||||||
|
<template #header><Fa :icon="faChartBar" style="margin-right: 0.5em;"/>{{ $t('activity') }}</template>
|
||||||
|
|
||||||
|
<div style="padding: 8px;">
|
||||||
<div ref="chart"></div>
|
<div ref="chart"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</MkContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import ApexCharts from 'apexcharts';
|
import ApexCharts from 'apexcharts';
|
||||||
|
import { faChartBar } from '@fortawesome/free-solid-svg-icons';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import MkContainer from '@/components/ui/container.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkContainer,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
user: {
|
user: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -25,7 +34,8 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
fetching: true,
|
fetching: true,
|
||||||
data: [],
|
data: [],
|
||||||
peak: null
|
peak: null,
|
||||||
|
faChartBar,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<MkContainer>
|
||||||
|
<template #header><Fa :icon="faImage" style="margin-right: 0.5em;"/>{{ $t('images') }}</template>
|
||||||
<div class="ujigsodd">
|
<div class="ujigsodd">
|
||||||
<MkLoading v-if="fetching"/>
|
<MkLoading v-if="fetching"/>
|
||||||
<div class="stream" v-if="!fetching && images.length > 0">
|
<div class="stream" v-if="!fetching && images.length > 0">
|
||||||
@ -10,20 +12,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="empty" v-if="!fetching && images.length == 0">{{ $t('nothing') }}</p>
|
<p class="empty" v-if="!fetching && images.length == 0">{{ $t('nothing') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
</MkContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { faImage } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import notePage from '../../filters/note';
|
import notePage from '../../filters/note';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import MkContainer from '@/components/ui/container.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: ['user'],
|
components: {
|
||||||
|
MkContainer,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
fetching: true,
|
fetching: true,
|
||||||
images: []
|
images: [],
|
||||||
|
faImage
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -37,7 +51,7 @@ export default defineComponent({
|
|||||||
os.api('users/notes', {
|
os.api('users/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
fileType: image,
|
fileType: image,
|
||||||
excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
|
excludeNsfw: this.$store.state.device.nsfw !== 'ignore',
|
||||||
limit: 9,
|
limit: 9,
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
@ -66,6 +80,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.ujigsodd {
|
.ujigsodd {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
> .stream {
|
> .stream {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-user-page" v-if="user" v-size="{ max: [500] }">
|
<div>
|
||||||
|
<div class="mk-user-page" v-if="user" v-size="{ max: [500] }" :class="{ _section: narrow === false }">
|
||||||
<!-- TODO -->
|
<!-- TODO -->
|
||||||
<!-- <div class="punished" v-if="user.isSuspended"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $t('userSuspended') }}</div> -->
|
<!-- <div class="punished" v-if="user.isSuspended"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $t('userSuspended') }}</div> -->
|
||||||
<!-- <div class="punished" v-if="user.isSilenced"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $t('userSilenced') }}</div> -->
|
<!-- <div class="punished" v-if="user.isSilenced"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $t('userSilenced') }}</div> -->
|
||||||
|
|
||||||
<div class="profile _section _fitBottom">
|
<div class="main">
|
||||||
|
<div class="profile _vMargin" :class="{ _section: narrow === true }">
|
||||||
<MkRemoteCaution v-if="user.host != null" :href="user.url" class="_content _vMargin"/>
|
<MkRemoteCaution v-if="user.host != null" :href="user.url" class="_content _vMargin"/>
|
||||||
|
|
||||||
<div class="_content _vMargin" :key="user.id">
|
<div class="_content _panel _vMargin" :key="user.id">
|
||||||
<div class="banner-container" :style="style">
|
<div class="banner-container" :style="style">
|
||||||
<div class="banner" ref="banner" :style="style"></div>
|
<div class="banner" ref="banner" :style="style"></div>
|
||||||
<div class="fade"></div>
|
<div class="fade"></div>
|
||||||
@ -84,33 +86,29 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="page === 'index'">
|
<template v-if="page === 'index'">
|
||||||
<div class="_section">
|
<div v-if="user.pinnedNotes.length > 0" :class="{ _section: narrow === true, _vMargin: narrow === false }">
|
||||||
<div class="_content _vMargin" v-if="user.pinnedNotes.length > 0">
|
<XNote v-for="note in user.pinnedNotes" class="note _content _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
|
||||||
<XNote v-for="note in user.pinnedNotes" class="note _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
|
|
||||||
</div>
|
</div>
|
||||||
<MkFolder :body-togglable="true" class="_content _vMargin" persist-key="user-images">
|
<div v-if="narrow === true" class="_section">
|
||||||
<template #header><Fa :icon="faImage" style="margin-right: 0.5em;"/>{{ $t('images') }}</template>
|
<XPhotos class="_content _vMargin" :user="user" :key="user.id"/>
|
||||||
<div>
|
<XActivity class="_content _vMargin" :user="user" :key="user.id"/>
|
||||||
<XPhotos :user="user" :key="user.id"/>
|
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
<div :class="{ _section: narrow === true, _vMargin: narrow === false }">
|
||||||
<MkFolder :body-togglable="true" class="_content _vMargin" persist-key="user-activity">
|
|
||||||
<template #header><Fa :icon="faChartBar" style="margin-right: 0.5em;"/>{{ $t('activity') }}</template>
|
|
||||||
<div>
|
|
||||||
<XActivity :user="user" :key="user.id"/>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
</div>
|
|
||||||
<div class="_section">
|
|
||||||
<XUserTimeline :user="user" class="_content"/>
|
<XUserTimeline :user="user" class="_content"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<XFollowList v-else-if="page === 'following'" type="following" :user="user"/>
|
<XFollowList v-else-if="page === 'following'" :class="{ _section: narrow === true, _vMargin: narrow === false }" type="following" :user="user"/>
|
||||||
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user"/>
|
<XFollowList v-else-if="page === 'followers'" :class="{ _section: narrow === true, _vMargin: narrow === false }" type="followers" :user="user"/>
|
||||||
|
</div>
|
||||||
|
<div class="side" v-if="narrow === false">
|
||||||
|
<XPhotos class="_vMargin" :user="user" :key="user.id"/>
|
||||||
|
<XActivity class="_vMargin" :user="user" :key="user.id"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="error">
|
<div v-else-if="error">
|
||||||
<MkError @retry="fetch()"/>
|
<MkError @retry="fetch()"/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -170,6 +168,7 @@ export default defineComponent({
|
|||||||
user: null,
|
user: null,
|
||||||
error: null,
|
error: null,
|
||||||
parallaxAnimationId: null,
|
parallaxAnimationId: null,
|
||||||
|
narrow: null,
|
||||||
faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, farBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faCalendarAlt
|
faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, farBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faCalendarAlt
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -197,6 +196,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
window.requestAnimationFrame(this.parallaxLoop);
|
window.requestAnimationFrame(this.parallaxLoop);
|
||||||
|
this.narrow = this.$el.clientWidth < 1000;
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
@ -254,6 +254,13 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.mk-user-page {
|
.mk-user-page {
|
||||||
|
display: flex;
|
||||||
|
max-width: 1050px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
> .main {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
> .punished {
|
> .punished {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
@ -270,7 +277,6 @@ export default defineComponent({
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
border-radius: 12px;
|
|
||||||
|
|
||||||
> .banner {
|
> .banner {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -465,9 +471,17 @@ export default defineComponent({
|
|||||||
> .content {
|
> .content {
|
||||||
margin-bottom: var(--margin);
|
margin-bottom: var(--margin);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .side {
|
||||||
|
flex-basis: 300px;
|
||||||
|
margin-left: var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
&.max-width_500px {
|
&.max-width_500px {
|
||||||
> .profile > ._content {
|
display: block;
|
||||||
|
|
||||||
|
> .main > .profile > ._content {
|
||||||
> .banner-container {
|
> .banner-container {
|
||||||
height: 140px;
|
height: 140px;
|
||||||
|
|
||||||
|
30
src/client/pages/v.vue
Normal file
30
src/client/pages/v.vue
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<section class="_section">
|
||||||
|
<div class="_content" style="text-align: center;">
|
||||||
|
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;"/>
|
||||||
|
<div style="margin-top: 0.75em;">Misskey</div>
|
||||||
|
<div style="opacity: 0.5;">v{{ version }}</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { version } from '@/config';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
INFO: {
|
||||||
|
title: 'Misskey',
|
||||||
|
icon: null
|
||||||
|
},
|
||||||
|
version,
|
||||||
|
faInfoCircle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,11 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="rsqzvsbo _section" v-if="meta">
|
<div class="rsqzvsbo _section" v-if="meta">
|
||||||
<div class="about">
|
|
||||||
<h1>{{ instanceName }}</h1>
|
|
||||||
<div class="desc" v-html="meta.description || $t('introMisskey')"></div>
|
|
||||||
<MkButton @click="signup()" style="display: inline-block; margin-right: 16px;" primary>{{ $t('signup') }}</MkButton>
|
|
||||||
<MkButton @click="signin()" style="display: inline-block;">{{ $t('login') }}</MkButton>
|
|
||||||
</div>
|
|
||||||
<div class="blocks">
|
<div class="blocks">
|
||||||
<XBlock class="block" v-for="path in meta.pinnedPages" :initial-path="path" :key="path"/>
|
<XBlock class="block" v-for="path in meta.pinnedPages" :initial-path="path" :key="path"/>
|
||||||
</div>
|
</div>
|
||||||
@ -68,28 +62,6 @@ export default defineComponent({
|
|||||||
.rsqzvsbo {
|
.rsqzvsbo {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
> .about {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 24px;
|
|
||||||
margin-bottom: var(--margin);
|
|
||||||
-webkit-backdrop-filter: blur(8px);
|
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
border-radius: var(--radius);
|
|
||||||
text-align: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-width: 300px;
|
|
||||||
max-width: 800px;
|
|
||||||
|
|
||||||
&, * {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
> h1 {
|
|
||||||
margin: 0 0 16px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .blocks {
|
> .blocks {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
||||||
|
@ -22,7 +22,7 @@ export const router = createRouter({
|
|||||||
{ path: '/@:user/pages/:page', component: page('page'), props: route => ({ pageName: route.params.page, username: route.params.user }) },
|
{ path: '/@:user/pages/:page', component: page('page'), props: route => ({ pageName: route.params.page, username: route.params.user }) },
|
||||||
{ path: '/@:user/pages/:pageName/view-source', component: page('page-editor/page-editor'), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
|
{ path: '/@:user/pages/:pageName/view-source', component: page('page-editor/page-editor'), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
|
||||||
{ path: '/@:acct/room', props: true, component: page('room/room') },
|
{ path: '/@:acct/room', props: true, component: page('room/room') },
|
||||||
{ path: '/settings/:page?', name: 'settings', component: page('settings/index'), props: route => ({ page: route.params.page || null }) },
|
{ path: '/settings/:page(.*)?', name: 'settings', component: page('settings/index'), props: route => ({ page: route.params.page || null }) },
|
||||||
{ path: '/announcements', component: page('announcements') },
|
{ path: '/announcements', component: page('announcements') },
|
||||||
{ path: '/about', component: page('about') },
|
{ path: '/about', component: page('about') },
|
||||||
{ path: '/about-misskey', component: page('about-misskey') },
|
{ path: '/about-misskey', component: page('about-misskey') },
|
||||||
@ -57,7 +57,6 @@ export const router = createRouter({
|
|||||||
{ path: '/my/groups/:group', component: page('my-groups/group') },
|
{ path: '/my/groups/:group', component: page('my-groups/group') },
|
||||||
{ path: '/my/antennas', component: page('my-antennas/index') },
|
{ path: '/my/antennas', component: page('my-antennas/index') },
|
||||||
{ path: '/my/clips', component: page('my-clips/index') },
|
{ path: '/my/clips', component: page('my-clips/index') },
|
||||||
{ path: '/my/apps', component: page('apps') },
|
|
||||||
{ path: '/scratchpad', component: page('scratchpad') },
|
{ path: '/scratchpad', component: page('scratchpad') },
|
||||||
{ path: '/instance', component: page('instance/index') },
|
{ path: '/instance', component: page('instance/index') },
|
||||||
{ path: '/instance/emojis', component: page('instance/emojis') },
|
{ path: '/instance/emojis', component: page('instance/emojis') },
|
||||||
|
24
src/client/scripts/sound.ts
Normal file
24
src/client/scripts/sound.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { device } from '@/cold-storage';
|
||||||
|
|
||||||
|
const cache = new Map<string, HTMLAudioElement>();
|
||||||
|
|
||||||
|
export function play(type: string) {
|
||||||
|
const sound = device.get('sound_' + type as any);
|
||||||
|
if (sound.type == null) return;
|
||||||
|
playFile(sound.type, sound.volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function playFile(file: string, volume: number) {
|
||||||
|
const masterVolume = device.get('sound_masterVolume');
|
||||||
|
if (masterVolume === 0) return;
|
||||||
|
|
||||||
|
let audio: HTMLAudioElement;
|
||||||
|
if (cache.has(file)) {
|
||||||
|
audio = cache.get(file);
|
||||||
|
} else {
|
||||||
|
audio = new Audio(`/assets/sounds/${file}.mp3`);
|
||||||
|
cache.set(file, audio);
|
||||||
|
}
|
||||||
|
audio.volume = masterVolume - ((1 - volume) * masterVolume);
|
||||||
|
audio.play();
|
||||||
|
}
|
@ -15,19 +15,12 @@ export const darkTheme: Theme = require('../themes/_dark.json5');
|
|||||||
export const themeProps = Object.keys(lightTheme.props).filter(key => !key.startsWith('X'));
|
export const themeProps = Object.keys(lightTheme.props).filter(key => !key.startsWith('X'));
|
||||||
|
|
||||||
export const builtinThemes = [
|
export const builtinThemes = [
|
||||||
require('../themes/l-white.json5'),
|
require('../themes/l-light.json5'),
|
||||||
require('../themes/l-red.json5'),
|
|
||||||
require('../themes/l-green.json5'),
|
|
||||||
require('../themes/l-blue.json5'),
|
|
||||||
require('../themes/l-apricot.json5'),
|
require('../themes/l-apricot.json5'),
|
||||||
|
|
||||||
require('../themes/d-black.json5'),
|
require('../themes/d-dark.json5'),
|
||||||
require('../themes/d-red.json5'),
|
|
||||||
require('../themes/d-green.json5'),
|
|
||||||
require('../themes/d-blue.json5'),
|
|
||||||
require('../themes/d-persimmon.json5'),
|
require('../themes/d-persimmon.json5'),
|
||||||
|
require('../themes/d-black.json5'),
|
||||||
require('../themes/d-battery-saver.json5'),
|
|
||||||
] as Theme[];
|
] as Theme[];
|
||||||
|
|
||||||
let timeout = null;
|
let timeout = null;
|
||||||
|
@ -55,7 +55,7 @@ export const defaultDeviceUserSettings = {
|
|||||||
export const defaultDeviceSettings = {
|
export const defaultDeviceSettings = {
|
||||||
lang: null,
|
lang: null,
|
||||||
loadRawImages: false,
|
loadRawImages: false,
|
||||||
alwaysShowNsfw: false,
|
nsfw: 'respect', // respect, force, ignore
|
||||||
useOsNativeEmojis: false,
|
useOsNativeEmojis: false,
|
||||||
serverDisconnectedBehavior: 'quiet',
|
serverDisconnectedBehavior: 'quiet',
|
||||||
accounts: [],
|
accounts: [],
|
||||||
@ -87,14 +87,6 @@ export const defaultDeviceSettings = {
|
|||||||
deckColumnAlign: 'left',
|
deckColumnAlign: 'left',
|
||||||
deckAlwaysShowMainColumn: true,
|
deckAlwaysShowMainColumn: true,
|
||||||
deckMainColumnPlace: 'left',
|
deckMainColumnPlace: 'left',
|
||||||
sfxVolume: 0.3,
|
|
||||||
sfxNote: 'syuilo/down',
|
|
||||||
sfxNoteMy: 'syuilo/up',
|
|
||||||
sfxNotification: 'syuilo/pope2',
|
|
||||||
sfxChat: 'syuilo/pope1',
|
|
||||||
sfxChatBg: 'syuilo/waon',
|
|
||||||
sfxAntenna: 'syuilo/triple',
|
|
||||||
sfxChannel: 'syuilo/square-pico',
|
|
||||||
userData: {},
|
userData: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@charset "utf-8";
|
@charset "utf-8";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--baseContentWidth: 750px;
|
--baseContentWidth: 760px;
|
||||||
--radius: 8px;
|
--radius: 8px;
|
||||||
--marginFull: 16px;
|
--marginFull: 16px;
|
||||||
--marginHalf: 10px;
|
--marginHalf: 10px;
|
||||||
@ -26,6 +26,9 @@ html {
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
font-family: "BIZ UDPGothic", Roboto, HelveticaNeue, Arial, sans-serif;
|
||||||
|
line-height: 1.35;
|
||||||
|
text-size-adjust: 100%;
|
||||||
|
|
||||||
&, * {
|
&, * {
|
||||||
scrollbar-color: var(--scrollbarHandle) var(--panel);
|
scrollbar-color: var(--scrollbarHandle) var(--panel);
|
||||||
@ -72,6 +75,10 @@ html {
|
|||||||
&.f-veryLarge {
|
&.f-veryLarge {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.useSystemFont {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html.changing-theme {
|
html.changing-theme {
|
||||||
@ -88,8 +95,6 @@ html, body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
text-size-adjust: 100%;
|
|
||||||
font-family: Roboto, HelveticaNeue, Arial, sans-serif;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -160,6 +165,8 @@ hr {
|
|||||||
tap-highlight-color: transparent;
|
tap-highlight-color: transparent;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
|
||||||
&, * {
|
&, * {
|
||||||
@extend ._noSelect;
|
@extend ._noSelect;
|
||||||
@ -445,10 +452,14 @@ hr {
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
._monospace {
|
||||||
|
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
._code {
|
._code {
|
||||||
|
@extend ._monospace;
|
||||||
background: #2d2d2d;
|
background: #2d2d2d;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
divider: 'rgba(255, 255, 255, 0.1)',
|
divider: 'rgba(255, 255, 255, 0.1)',
|
||||||
indicator: '@accent',
|
indicator: '@accent',
|
||||||
panel: '#000',
|
panel: '#000',
|
||||||
|
panelHighlight: ':lighten<3<@panel',
|
||||||
panelHeaderBg: ':lighten<3<@panel',
|
panelHeaderBg: ':lighten<3<@panel',
|
||||||
panelHeaderFg: '@fg',
|
panelHeaderFg: '@fg',
|
||||||
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
|
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
divider: 'rgba(0, 0, 0, 0.1)',
|
divider: 'rgba(0, 0, 0, 0.1)',
|
||||||
indicator: '@accent',
|
indicator: '@accent',
|
||||||
panel: '#fff',
|
panel: '#fff',
|
||||||
|
panelHighlight: ':darken<3<@panel',
|
||||||
panelHeaderBg: ':lighten<3<@panel',
|
panelHeaderBg: ':lighten<3<@panel',
|
||||||
panelHeaderFg: '@fg',
|
panelHeaderFg: '@fg',
|
||||||
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
|
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
|
|
||||||
|
|
||||||
name: 'Battery Saver',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'dark',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
divider: '#2d2d2d',
|
|
||||||
panelHeaderBg: '@panel',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
shadow: 'rgba(255, 255, 255, 0.05)',
|
|
||||||
modalBg: 'rgba(255, 255, 255, 0.1)',
|
|
||||||
messageBg: '#1d1d1d',
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,29 +1,19 @@
|
|||||||
{
|
{
|
||||||
id: '8050783a-7f63-445a-b270-36d0f6ba1677',
|
id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
|
||||||
|
|
||||||
name: 'Mi Black',
|
name: 'Mi Black',
|
||||||
author: 'syuilo',
|
author: 'syuilo',
|
||||||
desc: 'Default light theme',
|
|
||||||
|
|
||||||
base: 'dark',
|
base: 'dark',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
bg: '#272727',
|
divider: '#2d2d2d',
|
||||||
fg: 'rgb(199, 209, 216)',
|
panel: '#0a0a0a',
|
||||||
fgHighlighted: '#fff',
|
|
||||||
divider: 'rgba(255, 255, 255, 0.14)',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderBg: '@panel',
|
panelHeaderBg: '@panel',
|
||||||
panelHeaderDivider: '@divider',
|
panelHeaderDivider: '@divider',
|
||||||
infoFg: '@accent',
|
panelShadow: '" 0 8px 24px rgb(0 0 0 / 25%)',
|
||||||
infoBg: 'rgb(0, 0, 0)',
|
shadow: 'rgba(255, 255, 255, 0.05)',
|
||||||
header: ':alpha<0.7<@bg',
|
modalBg: 'rgba(255, 255, 255, 0.1)',
|
||||||
navBg: '#363636',
|
messageBg: '#1d1d1d',
|
||||||
renote: '@accent',
|
|
||||||
mention: '#da6d35',
|
|
||||||
mentionMe: '#d44c4c',
|
|
||||||
hashtag: '#4cb8d4',
|
|
||||||
link: '@accent',
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
id: 'ab4eb6d5-dcc0-4457-8a3c-98aad8ea3979',
|
|
||||||
|
|
||||||
name: 'Mi D Blue',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'dark',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
accent: 'rgb(81 185 189)',
|
|
||||||
bg: 'rgb(54, 54, 54)',
|
|
||||||
fg: 'rgb(199, 209, 216)',
|
|
||||||
fgHighlighted: '#fff',
|
|
||||||
divider: 'rgba(255, 255, 255, 0.14)',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderBg: '@panel',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
infoFg: '@accent',
|
|
||||||
infoBg: 'rgb(0, 0, 0)',
|
|
||||||
header: ':alpha<0.7<@bg',
|
|
||||||
navBg: 'rgb(71, 71, 71)',
|
|
||||||
renote: '@accent',
|
|
||||||
mention: '#da6d35',
|
|
||||||
mentionMe: '#d44c4c',
|
|
||||||
hashtag: '#4cb8d4',
|
|
||||||
link: '@accent',
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,25 +1,25 @@
|
|||||||
{
|
{
|
||||||
id: '60960086-26da-4f3c-bb0c-f6a4f89e0f60',
|
id: '8050783a-7f63-445a-b270-36d0f6ba1677',
|
||||||
|
|
||||||
name: 'Mi D Red',
|
name: 'Mi Dark',
|
||||||
author: 'syuilo',
|
author: 'syuilo',
|
||||||
|
desc: 'Default light theme',
|
||||||
|
|
||||||
base: 'dark',
|
base: 'dark',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
accent: 'rgb(196 115 69)',
|
bg: '#232323',
|
||||||
bg: 'rgb(54, 54, 54)',
|
|
||||||
fg: 'rgb(199, 209, 216)',
|
fg: 'rgb(199, 209, 216)',
|
||||||
fgHighlighted: '#fff',
|
fgHighlighted: '#fff',
|
||||||
divider: 'rgba(255, 255, 255, 0.14)',
|
divider: 'rgba(255, 255, 255, 0.14)',
|
||||||
panel: '@bg',
|
panel: '#2d2d2d',
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
panelShadow: '" 0 8px 24px rgb(0 0 0 / 25%)',
|
||||||
panelHeaderBg: '@panel',
|
panelHeaderBg: '@panel',
|
||||||
panelHeaderDivider: '@divider',
|
panelHeaderDivider: '@divider',
|
||||||
infoFg: '@accent',
|
infoFg: '@accent',
|
||||||
infoBg: 'rgb(0, 0, 0)',
|
infoBg: 'rgb(0, 0, 0)',
|
||||||
header: ':alpha<0.7<@bg',
|
header: ':alpha<0.7<@bg',
|
||||||
navBg: 'rgb(71, 71, 71)',
|
navBg: '#363636',
|
||||||
renote: '@accent',
|
renote: '@accent',
|
||||||
mention: '#da6d35',
|
mention: '#da6d35',
|
||||||
mentionMe: '#d44c4c',
|
mentionMe: '#d44c4c',
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
id: '326dc4bf-29d9-45b4-889e-bdc33e84919b',
|
|
||||||
|
|
||||||
name: 'Mi D Green',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'dark',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
accent: 'rgb(152, 196, 69)',
|
|
||||||
bg: 'rgb(54, 54, 54)',
|
|
||||||
fg: 'rgb(199, 209, 216)',
|
|
||||||
fgHighlighted: '#fff',
|
|
||||||
divider: 'rgba(255, 255, 255, 0.14)',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderBg: '@panel',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
infoFg: '@accent',
|
|
||||||
infoBg: 'rgb(0, 0, 0)',
|
|
||||||
header: ':alpha<0.7<@bg',
|
|
||||||
navBg: 'rgb(71, 71, 71)',
|
|
||||||
renote: '@accent',
|
|
||||||
mention: '#da6d35',
|
|
||||||
mentionMe: '#d44c4c',
|
|
||||||
hashtag: '#4cb8d4',
|
|
||||||
link: '@accent',
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
id: 'c503d768-7c70-4db2-a4e6-08264304bc8d',
|
id: 'c503d768-7c70-4db2-a4e6-08264304bc8d',
|
||||||
|
|
||||||
name: 'Ai Persimmon',
|
name: 'Mi Persimmon',
|
||||||
author: 'syuilo',
|
author: 'syuilo',
|
||||||
|
|
||||||
base: 'dark',
|
base: 'dark',
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
accent: 'rgb(206, 102, 65)',
|
accent: 'rgb(206, 102, 65)',
|
||||||
bg: 'rgb(41, 43, 41)',
|
bg: 'rgb(31, 33, 31)',
|
||||||
fg: '#cdd8c7',
|
fg: '#cdd8c7',
|
||||||
fgHighlighted: '#fff',
|
fgHighlighted: '#fff',
|
||||||
divider: 'rgba(255, 255, 255, 0.14)',
|
divider: 'rgba(255, 255, 255, 0.14)',
|
||||||
panel: '@bg',
|
panel: 'rgb(41, 43, 41)',
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
panelShadow: '" 0 8px 24px rgb(0 0 0 / 25%)',
|
||||||
panelHeaderBg: '@panel',
|
panelHeaderBg: '@panel',
|
||||||
panelHeaderDivider: '@divider',
|
panelHeaderDivider: '@divider',
|
||||||
infoFg: '@accent',
|
infoFg: '@fg',
|
||||||
infoBg: 'rgb(0, 0, 0)',
|
infoBg: '#333c3b',
|
||||||
header: ':alpha<0.7<@bg',
|
header: ':alpha<0.7<@bg',
|
||||||
navBg: '#1f211f',
|
navBg: '#1f211f',
|
||||||
renote: '@accent',
|
renote: '@accent',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
id: '0ff48d43-aab3-46e7-ab12-8492110d2e2b',
|
id: '0ff48d43-aab3-46e7-ab12-8492110d2e2b',
|
||||||
|
|
||||||
name: 'Ai Apricot',
|
name: 'Mi Apricot',
|
||||||
author: 'syuilo',
|
author: 'syuilo',
|
||||||
|
|
||||||
base: 'light',
|
base: 'light',
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
id: 'ad18a23b-6af6-4af0-9ed4-600568250574',
|
|
||||||
|
|
||||||
name: 'Mi L Blue',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'light',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
accent: '#4dbccc',
|
|
||||||
bg: '#fff',
|
|
||||||
fg: '#5d5d5d',
|
|
||||||
divider: 'rgb(223, 223, 223)',
|
|
||||||
header: ':alpha<0.7<@bg',
|
|
||||||
navBg: '@bg',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
messageBg: '#dedede',
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
id: 'a55af79a-12bf-4f8d-a0cc-718957ad59b4',
|
|
||||||
|
|
||||||
name: 'Mi L Green',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'light',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
accent: '#8bcc4d',
|
|
||||||
bg: '#fff',
|
|
||||||
fg: '#5d5d5d',
|
|
||||||
divider: 'rgb(223, 223, 223)',
|
|
||||||
header: ':alpha<0.7<@bg',
|
|
||||||
navBg: '@bg',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
messageBg: '#dedede',
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
id: '4eea646f-7afa-4645-83e9-83af0333cd37',
|
id: '4eea646f-7afa-4645-83e9-83af0333cd37',
|
||||||
|
|
||||||
name: 'Mi White',
|
name: 'Mi Light',
|
||||||
author: 'syuilo',
|
author: 'syuilo',
|
||||||
desc: 'Default light theme',
|
desc: 'Default light theme',
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
id: '957db7cb-30fb-4c80-bf0b-04198e7ae7e3',
|
|
||||||
|
|
||||||
name: 'Mi L Red',
|
|
||||||
author: 'syuilo',
|
|
||||||
|
|
||||||
base: 'light',
|
|
||||||
|
|
||||||
props: {
|
|
||||||
accent: '#fb734d',
|
|
||||||
bg: '#fff',
|
|
||||||
fg: '#5d5d5d',
|
|
||||||
divider: 'rgb(223, 223, 223)',
|
|
||||||
header: ':alpha<0.7<@bg',
|
|
||||||
navBg: '@bg',
|
|
||||||
panel: '@bg',
|
|
||||||
panelShadow: '" 0 0 0 1px var(--divider)',
|
|
||||||
panelHeaderDivider: '@divider',
|
|
||||||
messageBg: '#dedede',
|
|
||||||
},
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user