Compare commits

..

14 Commits

Author SHA1 Message Date
syuilo
ea7d4d323e Merge branch 'develop' 2021-04-28 18:37:48 +09:00
syuilo
18da55bd81 12.79.3 2021-04-28 18:37:31 +09:00
syuilo
25424fe62e New Crowdin updates (#7485)
* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (French)
2021-04-28 18:36:21 +09:00
syuilo
c7e60cfd0c Fix style 2021-04-28 18:36:07 +09:00
syuilo
3e19bcb6cb Fix #7488 2021-04-28 18:32:55 +09:00
syuilo
6573c3b522 Use Node.js v16 2021-04-28 09:22:01 +09:00
syuilo
17fff8c665 Merge branch 'develop' 2021-04-26 13:00:10 +09:00
syuilo
fa9f0d9ff9 12.79.2 2021-04-26 13:00:01 +09:00
syuilo
77ccf3b929 Fix #7483 2021-04-26 12:47:54 +09:00
syuilo
4b205aee91 Fix #7480 2021-04-26 12:34:41 +09:00
syuilo
d348e211d4 New Crowdin updates (#7482)
* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations reversi-bot.md (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)
2021-04-26 11:12:34 +09:00
syuilo
42539575a6 ギャラリー投稿の編集と削除 2021-04-26 11:10:45 +09:00
syuilo
8bce241170 🎨 2021-04-26 10:46:55 +09:00
syuilo
c039665a97 Fix #7481 2021-04-25 22:32:46 +09:00
31 changed files with 740 additions and 253 deletions

View File

@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
node-version: [12.x, 14.x, 15.x]
node-version: [14.x, 16.x]
services:
postgres:

View File

@@ -1 +1 @@
v14.15.5
v16.0.0

View File

@@ -1,4 +1,4 @@
FROM node:14.15.5-alpine3.13 AS base
FROM node:16.0.0-alpine3.13 AS base
ENV NODE_ENV=production

View File

@@ -339,7 +339,7 @@ recaptcha: "reCAPTCHA"
enableRecaptcha: "Enable reCAPTCHA"
recaptchaSiteKey: "Site key"
recaptchaSecretKey: "Secret key"
avoidMultiCaptchaConfirm: "Using multiple Captchas may cause interference. Would you like to disable the other Captcha? You can leave multiple Captchas enabled by press cancel."
avoidMultiCaptchaConfirm: "Using multiple Captchas may cause interferences. Would you like to disable the other Captcha? You can leave multiple Captchas enabled by pressing cancel."
antennas: "Antennas"
manageAntennas: "Manage Antennas"
name: "Name"

View File

@@ -486,7 +486,7 @@ objectStorageRegionDesc: "Spécifiez une région comme 'xx-east-1'. Si votre ser
objectStorageUseSSL: "Utiliser SSL"
objectStorageUseSSLDesc: "Désactivez cette option si vous n'utilisez pas HTTPS pour la connexion API"
objectStorageUseProxy: "Se connecter via proxy"
objectStorageUseProxyDesc: "Désactivez cette option si vous n'utilisez pas Proxy pour la connexion API"
objectStorageUseProxyDesc: "Désactivez cette option si vous n'utilisez pas de proxy pour la connexion API"
objectStorageSetPublicRead: "Régler sur « public » lors de l'envoi"
serverLogs: "Journal du serveur"
deleteAll: "Supprimer tout"
@@ -600,7 +600,7 @@ useGlobalSettingDesc: "S'il est activé, les paramètres de notification de votr
other: "Autre"
regenerateLoginToken: "Régénérer le jeton de connexion"
regenerateLoginTokenDescription: "Générer un nouveau jeton d'authentification. Cette opération ne devrait pas être nécessaire ; lors de la génération d'un nouveau jeton, tous les appareils seront déconnectés. "
setMultipleBySeparatingWithSpace: "Vous pouvez définir plus dun, séparés par des espaces."
setMultipleBySeparatingWithSpace: "Vous pouvez en définir plusieurs, en les séparant par des espaces."
fileIdOrUrl: "ID du fichier ou URL"
chatOpenBehavior: "Comportement de la fenêtre de discussion lors de son ouverture"
behavior: "Comportement"
@@ -728,6 +728,7 @@ online: "En ligne"
offline: "Hors ligne"
notRecommended: "Déconseillé"
botProtection: "Protection contre les bots"
instanceBlocking: "Instances bloquées"
selectAccount: "Sélectionner un compte"
enabled: "Activé"
disabled: "Désactivé"
@@ -900,11 +901,13 @@ _theme:
funcKind: "Type de fonction"
argument: "Argument"
alpha: "Transparence"
darken: "Assombrir"
darken: "Sombre"
lighten: "Clair"
inputConstantName: "Insérez un nom de constante"
importInfo: "Vous pouvez importer un thème vers léditeur de thèmes en saisissant son code ici."
deleteConstantConfirm: "Êtes-vous sûr·e de vouloir supprimer la constante {const} ?"
keys:
accent: "Accentuation"
bg: "Arrière-plan"
fg: "Texte"
focus: "Mise au point"
@@ -940,6 +943,8 @@ _theme:
driveFolderBg: "Arrière-plan du dossier de disque"
badge: "Badge"
messageBg: "Arrière plan de la discussion"
accentDarken: "Plus sombre"
accentLighten: "Plus clair"
fgHighlighted: "Texte mis en évidence"
_sfx:
note: "Nouvelle note"
@@ -1136,8 +1141,8 @@ _exportOrImport:
blockingList: "Comptes bloqués"
userLists: "Listes"
_charts:
federationInstancesIncDec: "Variation du nombre des instances fédérées"
federationInstancesTotal: "Nombre total des instances fédérées"
federationInstancesIncDec: "Variation du nombre d'instances fédérées"
federationInstancesTotal: "Nombre total d'instances fédérées"
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
usersTotal: "Nombre des utilisateur·rice·s au total"
activeUsers: "Utilisateur·rice·s actif·ve·s"
@@ -1152,15 +1157,15 @@ _charts:
_instanceCharts:
requests: "Requêtes"
users: "Variation du nombre d'utilisateur·rice·s"
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
notes: "Variation du nombre des notes"
usersTotal: "Total cumulé du nombre d'utilisateur·rice·s"
notes: "Variation du nombre de notes"
notesTotal: "Nombre total cumulé des notes"
ff: "Variation des abonné·e·s"
ffTotal: "Nombre d'abonné·e·s au total cumulé"
ff: "Variation des abonné·e·s / abonnements"
ffTotal: "Total cumulé du nombre d'abonné·e·s / abonnements"
cacheSize: "Variation de la taille du cache"
cacheSizeTotal: "La taille du cache au total cumulé"
cacheSizeTotal: "Total cumulé de la taille du cache"
files: "Variation du nombre de fichiers"
filesTotal: "Nombre de fichiers au total cumulé"
filesTotal: "Total cumulé du nombre de fichiers"
_timelines:
home: "Principal"
local: "Local"
@@ -1183,7 +1188,7 @@ _rooms:
default: "Par défaut"
washitsu: "Style japonnais"
_furnitures:
milk: "Lait en carton"
milk: "Brique de lait"
bed: "Lit"
low-table: "Table basse"
desk: "Bureau"
@@ -1202,7 +1207,7 @@ _rooms:
book: "Livre"
book2: "Livre 2"
piano: "Piano"
facial-tissue: "Mouchoirs en papier"
facial-tissue: "Boîte de mouchoirs"
server: "Serveurs"
moon: "Lune"
corkboard: "Tableau en liège"
@@ -1215,7 +1220,7 @@ _rooms:
wall-clock: "Horloge murale"
photoframe: "Cadre photo"
cube: "Cube"
tv: "Téléviseur"
tv: "Télé"
pinguin: "Pingouin"
rubik-cube: "Cube de Rubik"
poster-h: "Affiche (horizontale)"
@@ -1237,7 +1242,7 @@ _pages:
deleted: "La page a été supprimée"
pageSetting: "Paramètres de la Page"
nameAlreadyExists: "L'URL de page spécifiée existe déjà"
invalidNameTitle: "La URL de la page spécifiée nest pas valide"
invalidNameTitle: "L'URL de page spécifiée nest pas valide"
invalidNameText: "Assurez-vous quil nest pas vide"
editThisPage: "Éditer cette page"
viewSource: "Afficher la source"
@@ -1259,14 +1264,14 @@ _pages:
font: "Police de caractères"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "Définir une image attirante"
eyeCatchingImageRemove: "Supprimer une image attirante"
eyeCatchingImageSet: "Définir une image attractive"
eyeCatchingImageRemove: "Supprimer l'image attractive"
chooseBlock: "Ajouter un bloc"
selectType: "Choisir un type"
enterVariableName: "Veuillez entrer un nom pour votre variable"
variableNameIsAlreadyUsed: "Cette variable est déjà utilisée"
variableNameIsAlreadyUsed: "Ce nom de variable est déjà utilisé"
contentBlocks: "Contenu"
inputBlocks: "Entrée"
inputBlocks: "Blocs d'entrée"
specialBlocks: "Spécial"
blocks:
text: "Texte"

View File

@@ -153,6 +153,9 @@ recipient: "Destinatario"
annotation: "Descrizione"
federation: "Federazione"
instances: "Istanza"
latestRequestSentAt: "Ultima richiesta inviata"
latestRequestReceivedAt: "Ultima richiesta ricevuta"
latestStatus: "Ultimo stato"
storageUsage: "Volume di dischi"
charts: "Grafici"
perHour: "All'ora"
@@ -172,6 +175,7 @@ instanceInfo: "Informazioni sull'istanza"
statistics: "Statistiche"
clearQueue: "Svuota coda"
clearQueueConfirmTitle: "Vuoi davvero svuotare la coda?"
clearQueueConfirmText: "Le note ancora non distribuite non verranno rilasciate. Solitamente, non è necessario eseguire questa operazione."
clearCachedFiles: "Svuota cache"
clearCachedFilesConfirm: "Vuoi davvero svuotare la cache da tutti i file remoti?"
blockedInstances: "Istanze bloccate"
@@ -329,6 +333,7 @@ recaptcha: "reCAPTCHA"
enableRecaptcha: "Abilita reCAPTCHA"
recaptchaSiteKey: "Chiave del sito"
recaptchaSecretKey: "Chiave segreta"
avoidMultiCaptchaConfirm: "Utilizzare diversi Captcha può causare interferenze. Vuoi disattivare l'altro Captcha? Puoi lasciare diversi Captcha attivi premendo \"Cancella\"."
antennas: "Antenne"
manageAntennas: "Gestore delle antenne"
name: "Nome"
@@ -468,6 +473,9 @@ objectStoragePrefixDesc: "I file saranno conservati sotto la directory di questo
objectStorageEndpoint: "Endpoint"
objectStorageRegion: "Region"
objectStorageUseSSL: "Usare SSL"
objectStorageUseProxy: "Usa proxy"
objectStorageUseProxyDesc: "Disabilita quest'opzione se non usi proxy per la connessione API."
objectStorageSetPublicRead: "Imposta \"visibilità pubblica\" al momento di caricare"
serverLogs: "Log del server"
deleteAll: "Cancella cronologia"
showFixedPostForm: "Visualizzare la finestra di pubblicazione in cima alla timeline"
@@ -497,7 +505,7 @@ scratchpad: "ScratchPad"
output: "Uscita"
script: "Script"
disablePagesScript: "Disabilita AiScript nelle pagine"
updateRemoteUser: "Aggiornare le informazioni di utente remoto"
updateRemoteUser: "Aggiornare le informazioni di utente remot@"
deleteAllFiles: "Elimina tutti i file"
deleteAllFilesConfirm: "Vuoi davvero eliminare tutti i file?"
removeAllFollowing: "Cancella tutti i follows"
@@ -508,7 +516,10 @@ sidebar: "Barra laterale"
divider: "Linea di separazione"
addItem: "Aggiungi elemento"
rooms: "Camera"
relays: "Ripetitori"
addRelay: "Aggiungi ripetitore"
inboxUrl: "Inbox URL"
addedRelays: "Ripetitori configurati"
serviceworkerInfo: "Deve essere abilitato per le notifiche push. "
deletedNote: "Nota eliminata"
invisibleNote: "Nota invisibile"
@@ -533,9 +544,12 @@ height: "Altezza"
large: "Grande"
medium: "Predefinito"
small: "Piccolo"
generateAccessToken: "Genera token di accesso"
permission: "Autorizzazioni "
enableAll: "Abilita tutto"
disableAll: "Disabilita tutto"
tokenRequested: "Autorizza accesso all'account"
pluginTokenRequestedDescription: "Il plugin potrà utilizzare le autorizzazioni impostate qui."
notificationType: "Tipo di notifiche"
edit: "Modifica"
useStarForReactionFallback: "Se è sconosciuto l'emoji di reazione, usare la ★ come alternativa."
@@ -570,7 +584,10 @@ notificationSettingDesc: "Seleziona il tipo di notifiche da visualizzare."
useGlobalSetting: "Usa impostazioni generali"
useGlobalSettingDesc: "Se abilitato, le impostazioni notifiche dell'account verranno utilizzate. Se disabilitato, si possono definire diverse singole impostazioni."
other: "Avanzate"
regenerateLoginToken: "Genera di nuovo un token di connessione"
regenerateLoginTokenDescription: "Genera un nuovo token di autenticazione. Solitamente questa operazione non è necessaria: quando si genera un nuovo token, tutti i dispositivi vanno disconnessi."
fileIdOrUrl: "ID o URL del file"
chatOpenBehavior: "Comportamento della finestra di chat quando viene aperta"
behavior: "Comportamento"
abuseReports: "Segnala"
reportAbuse: "Segnala"
@@ -592,6 +609,7 @@ optional: "Opzionale"
createNewClip: "Nuova clip"
public: "Pubblica"
i18nInfo: "Misskey è tradotto in diverse lingue da volontari. Anche tu puoi contribuire su {link}."
manageAccessTokens: "Gestisci token di accesso"
accountInfo: "Informazioni account"
notesCount: "Conteggio note"
repliesCount: "Numero di risposte inviate"
@@ -608,7 +626,11 @@ yes: "Sì"
no: "No"
driveFilesCount: "Numero di file nel Drive"
driveUsage: "Utilizzazione del Drive"
noCrawle: "Rifiuta l'indicizzazione dai robot."
noCrawleDescription: "Richiedi che i motori di ricerca non indicizzino la tua pagina di profilo, le tue note, pagine, ecc."
alwaysMarkSensitive: "Segnare i media come sensibili per impostazione predefinita"
loadRawImages: "Visualizza le intere immagini allegate invece delle miniature."
disableShowingAnimatedImages: "Disabilita le immagini animate"
verificationEmailSent: "Una mail di verifica è stata inviata. Si prega di accedere al collegamento per compiere la verifica."
notSet: "Non impostato"
emailVerified: "Il tuo indirizzo email è stato verificato"
@@ -628,6 +650,7 @@ duplicate: "Duplica"
left: "Sinistra"
center: "Centro"
wide: "Largo"
reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricamento della pagina. Vuoi ricaricare adesso?"
showTitlebar: "Visualizza la barra del titolo"
clearCache: "Svuota cache"
onlineUsersCount: "{n} utenti online"
@@ -644,6 +667,7 @@ createdAt: "Data di creazione"
updatedAt: "Aggiornato il"
saveConfirm: "Vuoi salvare le modifiche?"
deleteConfirm: "Rimuovere?"
invalidValue: "Questo non è un valore valido."
registry: "Registro"
closeAccount: "Disattiva account"
currentVersion: "Versione attuale"
@@ -652,8 +676,10 @@ youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
usageAmount: "In utilizzo"
capacity: "Capacità"
inUse: "In utilizzo"
editCode: "Modifica codice"
apply: "Applica"
receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
emailNotification: "Eventi per notifiche via mail"
publish: "Pubblico"
inChannelSearch: "Cerca in canale"
@@ -730,6 +756,7 @@ _nsfw:
force: "Nascondere tutti i media"
_mfm:
cheatSheet: "Bigliettino MFM"
intro: "MFM è un linguaggio Markdown particolare che si può usare in diverse parti di Misskey. Qui puoi visualizzare a colpo d'occhio tutta la sintassi MFM utile."
dummy: "Il Fediverso si espande con Misskey"
mention: "Menzioni"
mentionDescription: "Si può menzionare un utente specifico digitando il suo nome utente subito dopo il segno @."
@@ -932,6 +959,7 @@ _widgets:
photos: "Foto"
digitalClock: "Orologio digitale"
federation: "Federazione"
postForm: "Finestra di pubblicazione"
button: "Pulsante"
onlineUsers: "Utenti online"
jobQueue: "Coda di lavoro"
@@ -1001,10 +1029,19 @@ _charts:
filesIncDec: "Variazione del numero dei file"
filesTotal: "Numero totale di file"
storageUsageIncDec: "Variazione dell'utilizzo dell'immagazzinamento"
storageUsageTotal: "Utilizzo totale dell'immagazzinamento"
_instanceCharts:
requests: "Richieste"
users: "Variazione del numero di utenti"
usersTotal: "Totale cumulativo di utenti"
notes: "Variazione del numero di note"
notesTotal: "Totale cumulato di note"
ff: "Variazione dei follow/ follower"
ffTotal: "Totale cumulato dei follow/ follower"
cacheSize: "Variazione dello spazio occupato dalla cache"
cacheSizeTotal: "Totale cumulato dello spazio occupato dalla cache"
files: "Variazione del numero di file"
filesTotal: "Totale cumulato del numero di file"
_timelines:
home: "Home"
local: "Locale"
@@ -1012,20 +1049,29 @@ _timelines:
global: "Federata"
_rooms:
roomOf: "Camera di {user}"
addFurniture: "Disponi mobilia"
translate: "Sposta"
rotate: "Ruota"
exit: "Indietro"
remove: "Togli"
clear: "Rimuovi tutto"
clearConfirm: "Sei sicur@ di voler rimuovere tutti i mobili dalla tua camera?"
leaveConfirm: "Hai fatto modifiche ancora non salvate. Vuoi davvero uscire?"
chooseImage: "Seleziona immagine"
roomType: "Tipo di stanza"
carpetColor: "Colore del suolo"
_roomType:
default: "Predefinito"
washitsu: "Washitsu"
_furnitures:
milk: "Cartone del latte"
bed: "Letto"
low-table: "Tavolino Coffee"
low-table: "Tavolino"
desk: "Tavolo"
chair: "Sedia"
chair2: "Sedia 2"
fan: "Ventilatore"
pc: "PC"
pc: "Computer"
plant: "Pianta da appartamento"
plant2: "Pianta da appartamento2"
eraser: "Gomma"
@@ -1037,21 +1083,32 @@ _rooms:
book: "Libro"
book2: "Libro2"
piano: "Pianoforte"
facial-tissue: "Scatola di fazzolettini"
server: "Server"
moon: "Luna"
corkboard: "Bacheca"
mousepad: "Tappetino per il mouse"
monitor: "Monitor "
keyboard: "Tastiera"
carpet-stripe: "Tappeto (a strisce)"
mat: "Zerbino"
color-box: "Libreria"
wall-clock: "Orologio da parete"
photoframe: "Cornice"
cube: "Cubo"
tv: "Televisore"
tv: "TV"
pinguin: "Pinguino"
rubik-cube: "Cubo di Rubik"
poster-h: "Poster (orizzontale)"
poster-v: "Poster (verticale)"
sofa: "Divano"
spiral: "Scale a chiocciola"
bin: "Cestino"
cup-noodle: "Noodle istantanei"
holo-display: "Visualizzazione olografica"
energy-drink: "Bevanda energetica"
doll-ai: "Bambola Ai"
banknote: "Mazzetta di banconote"
_pages:
newPage: "Crea pagina"
editPage: "Modifica pagina"
@@ -1060,6 +1117,9 @@ _pages:
updated: "Pagina aggiornata con successo!"
deleted: "Pagina eliminata"
pageSetting: "Impostazioni pagina"
nameAlreadyExists: "Esiste già una pagina con lo stesso URL."
invalidNameTitle: "L'URL di pagina definito non è valido"
invalidNameText: "Verifica che il campo non è vuoto"
editThisPage: "Modifica questa pagina"
viewSource: "Visualizza sorgente"
viewPage: "Visualizza pagina"
@@ -1072,11 +1132,21 @@ _pages:
content: "Blocco di pagina"
variables: "Variabili"
title: "Titolo"
url: "URL della pagina"
summary: "Riassunto di pagina"
hideTitleWhenPinned: "Nascondere il titolo pagina quando è fissata in cima al profilo."
font: "Tipo di carattere"
fontSerif: "Serif"
fontSansSerif: "Sans serif"
eyeCatchingImageSet: "Imposta un'immagine attrattiva"
eyeCatchingImageRemove: "Elimina l'immagine attrattiva"
chooseBlock: "Aggiungi blocco"
selectType: "Seleziona tipo"
enterVariableName: "Digita un nome di variabile"
variableNameIsAlreadyUsed: "Esiste già una variabile con lo stesso nome"
contentBlocks: "Contenuto"
inputBlocks: "Blocchi di input"
specialBlocks: "Speciale"
blocks:
text: "Testo"
textarea: "Area di testo"
@@ -1086,16 +1156,20 @@ _pages:
if: "Se"
_if:
variable: "Variabili"
post: "Finestra di pubblicazione"
_post:
text: "Contenuto"
textInput: "Immissione testo"
_textInput:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
textareaInput: "Immissione testo a più righe"
_textareaInput:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
numberInput: "Immissione numerica"
_numberInput:
name: "Nome della variabile"
text: "Titolo"
@@ -1108,24 +1182,35 @@ _pages:
id: "ID nota"
idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
detailed: "Visualizzazione dettagliata"
switch: "Interruttore"
_switch:
name: "Nome della variabile"
text: "Titolo"
default: "Valore predefinito"
counter: "Contatore"
_counter:
name: "Nome della variabile"
text: "Titolo"
inc: "Valore da aggiungere"
_button:
text: "Titolo"
colored: "Colorato"
action: "Operazione da eseguire quando viene premuto il pulsante"
_action:
dialog: "Visualizzare una finestra di dialogo"
_dialog:
content: "Contenuto"
resetRandom: "Ripristinare un numero aleatorio"
pushEvent: "Inviare evento"
_pushEvent:
event: "Nome evento"
message: "Messaggio da visualizzare quando abilitato"
variable: "Variabile da inviare"
no-variable: "Nessun contenuto"
callAiScript: "Chiamare AiScript"
_callAiScript:
functionName: "Nome della funzione"
radioButton: "Opzioni"
_radioButton:
name: "Nome della variabile"
title: "Titolo"
@@ -1139,6 +1224,8 @@ _pages:
list: "Liste"
blocks:
text: "Testo"
multiLineText: "Testo (a più righe)"
textList: "Lista di testo"
_strLen:
arg1: "Testo"
_strPick:
@@ -1193,13 +1280,18 @@ _pages:
arg2: "B"
_if:
arg1: "Se"
arg2: "Se"
random: "Aleatorietà"
_randomPick:
arg1: "Liste"
_dailyRandomPick:
arg1: "Liste"
_seedRandom:
arg2: "Probabilità"
_seedRandomPick:
arg2: "Liste"
_DRPWPM:
arg1: "Lista di testo"
_pick:
arg1: "Liste"
_listLen:
@@ -1213,6 +1305,7 @@ _pages:
types:
string: "Testo"
array: "Liste"
stringArray: "Lista di testo"
_notification:
fileUploaded: "File caricato correttamente"
youGotMention: "{name} ti ha menzionato"

View File

@@ -138,6 +138,7 @@ flagAsBotDescription: "이 계정을 자동화된 수단으로 운용할 경우
flagAsCat: "나는 고양이다냥"
flagAsCatDescription: "이 계정이 고양이라면 활성화 해주세요."
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
addAccount: "계정 추가"
loginFailed: "로그인에 실패했습니다"
showOnRemote: "리모트에서 보기"
general: "일반"
@@ -451,6 +452,7 @@ category: "카테고리"
tags: "태그"
docSource: "이 문서의 소스"
createAccount: "계정 만들기"
existingAccount: "기존 계정"
regenerate: "재생성"
fontSize: "글자 크기"
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
@@ -565,6 +567,7 @@ pluginTokenRequestedDescription: "이 플러그인은 여기서 설정한 권한
notificationType: "알림 유형"
edit: "편집"
useStarForReactionFallback: "알 수 없는 리액션 이모지 대신 ★ 사용"
emailServer: "메일 서버"
enableEmail: "이메일 송신 기능 활성화"
emailConfigInfo: "가입 시 메일 주소 확인이나 비밀번호 초기화 시에 사용합니다."
email: "이메일"
@@ -701,6 +704,7 @@ editCode: "코드 수정"
apply: "적용"
receiveAnnouncementFromInstance: "이 인스턴스의 알림을 이메일로 수신할게요"
emailNotification: "메일 알림"
publish: "게시"
inChannelSearch: "채널에서 검색"
useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기"
typingUsers: "{users} 님이 입력하고 있어요.."
@@ -724,11 +728,30 @@ hideOnlineStatusDescription: "온라인 상태를 숨기면, 검색과 같은
online: "온라인"
active: "최근에 활동함"
offline: "오프라인"
notRecommended: "추천하지 않음"
botProtection: "Bot 방어"
instanceBlocking: "인스턴스 차단"
selectAccount: "계정 선택"
enabled: "활성화"
disabled: "비활성화"
quickAction: "빠른 동작"
user: "유저"
administration: "관리"
accounts: "계정"
switch: "전환"
noMaintainerInformationWarning: "관리자 정보가 설정되어 있지 않습니다."
noBotProtectionWarning: "Bot 방어가 설정되어 있지 않습니다."
configure: "설정하기"
postToGallery: "갤러리에 업로드"
gallery: "갤러리"
recentPosts: "최근 포스트"
popularPosts: "인기 포스트"
shareWithNote: "노트로 공유"
_gallery:
unlike: "좋아요 해제"
my: "내 갤러리"
liked: "좋아요 한 갤러리"
like: "좋아요!"
unlike: "좋아요 취소"
_email:
_follow:
title: "새로운 팔로워가 있습니다"

View File

@@ -704,6 +704,7 @@ editCode: "Редактировать исходный текст"
apply: "Применить"
receiveAnnouncementFromInstance: "Получать оповещения с инстанса"
emailNotification: "Уведомления по электронной почте"
publish: "Опубликовать"
inChannelSearch: "Поиск по каналу"
useReactionPickerForContextMenu: "Открывать палитру реакций правой кнопкой"
typingUsers: "Стук клавиш. Это {users}…"
@@ -741,7 +742,15 @@ switch: "Переключение"
noMaintainerInformationWarning: "Не заполнены сведения об администраторах"
noBotProtectionWarning: "Ботозащита не настроена"
configure: "Настроить"
postToGallery: "Опубликовать в галерею"
gallery: "Галерея"
recentPosts: "Недавние публикации"
popularPosts: "Популярные публикации"
shareWithNote: "Поделиться заметкой"
_gallery:
my: "Личная"
liked: "Понравившееся"
like: "Нравится!"
unlike: "Отменить «нравится»"
_email:
_follow:

View File

@@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.79.1",
"version": "12.79.3",
"codename": "indigo",
"repository": {
"type": "git",

View File

@@ -6,7 +6,7 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
type Captcha = {
render(container: string | Node, options: {
@@ -32,7 +32,7 @@ declare global {
export default defineComponent({
props: {
provider: {
type: String,
type: String as PropType<CaptchaProvider>,
required: true,
},
sitekey: {
@@ -51,19 +51,25 @@ export default defineComponent({
},
computed: {
loaded() {
return !!window[this.provider as CaptchaProvider];
variable(): string {
switch (this.provider) {
case 'hcaptcha': return 'hcaptcha';
case 'recaptcha': return 'grecaptcha';
}
},
src() {
loaded(): boolean {
return !!window[this.variable];
},
src(): string {
const endpoint = ({
hcaptcha: 'https://hcaptcha.com/1',
recaptcha: 'https://www.recaptcha.net/recaptcha',
} as Record<PropertyKey, unknown>)[this.provider];
} as Record<CaptchaProvider, string>)[this.provider];
return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
return `${typeof endpoint === 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
},
captcha() {
return window[this.provider as CaptchaProvider] || {} as unknown as Captcha;
captcha(): Captcha {
return window[this.variable] || {} as unknown as Captcha;
},
},
@@ -94,7 +100,7 @@ export default defineComponent({
methods: {
reset() {
this.captcha?.reset();
if (this.captcha?.reset) this.captcha.reset();
},
requestRender() {
if (this.captcha.render && this.$refs.captcha instanceof Element) {

View File

@@ -81,7 +81,7 @@ export default defineComponent({
getMenu() {
return [{
text: this.$ts.rename,
icon: faICursor,
icon: 'fas fa-i-cursor',
action: this.rename
}, {
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,

View File

@@ -247,7 +247,7 @@ export default defineComponent({
}
}, null, {
text: this.$ts.rename,
icon: faICursor,
icon: 'fas fa-i-cursor',
action: this.rename
}, null, {
text: this.$ts.delete,

View File

@@ -614,7 +614,7 @@ export default defineComponent({
type: 'label'
}, this.folder ? {
text: this.$ts.renameFolder,
icon: faICursor,
icon: 'fas fa-i-cursor',
action: () => { this.renameFolder(this.folder); }
} : undefined, this.folder ? {
text: this.$ts.deleteFolder,

View File

@@ -93,7 +93,7 @@ export default defineComponent({
if (this.menu) return;
this.menu = os.modalMenu([{
text: this.$ts.renameFile,
icon: faICursor,
icon: 'fas fa-i-cursor',
action: () => { this.rename(file) }
}, {
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,

View File

@@ -8,33 +8,35 @@
@closed="$emit('closed')"
>
<template #header>{{ $ts.selectUser }}</template>
<div class="tbhwbxda _section">
<div class="inputs">
<MkInput v-model:value="username" class="input" @update:value="search" ref="username"><span>{{ $ts.username }}</span><template #prefix>@</template></MkInput>
<MkInput v-model:value="host" class="input" @update:value="search"><span>{{ $ts.host }}</span><template #prefix>@</template></MkInput>
</div>
</div>
<div class="tbhwbxda _section result" v-if="username != '' || host != ''" :class="{ hit: users.length > 0 }">
<div class="users" v-if="users.length > 0">
<div class="user" v-for="user in users" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
<div class="body">
<MkUserName :user="user" class="name"/>
<MkAcct :user="user" class="acct"/>
</div>
<div class="tbhwbxda _monolithic_">
<div class="_section">
<div class="inputs">
<MkInput v-model:value="username" class="input" @update:value="search" ref="username"><span>{{ $ts.username }}</span><template #prefix>@</template></MkInput>
<MkInput v-model:value="host" class="input" @update:value="search"><span>{{ $ts.host }}</span><template #prefix>@</template></MkInput>
</div>
</div>
<div v-else class="empty">
<span>{{ $ts.noUsers }}</span>
<div class="_section result" v-if="username != '' || host != ''" :class="{ hit: users.length > 0 }">
<div class="users" v-if="users.length > 0">
<div class="user" v-for="user in users" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
<div class="body">
<MkUserName :user="user" class="name"/>
<MkAcct :user="user" class="acct"/>
</div>
</div>
</div>
<div v-else class="empty">
<span>{{ $ts.noUsers }}</span>
</div>
</div>
</div>
<div class="tbhwbxda _section recent" v-if="username == '' && host == ''">
<div class="users">
<div class="user" v-for="user in recentUsers" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
<div class="body">
<MkUserName :user="user" class="name"/>
<MkAcct :user="user" class="acct"/>
<div class="_section recent" v-if="username == '' && host == ''">
<div class="users">
<div class="user" v-for="user in recentUsers" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
<div class="body">
<MkUserName :user="user" class="name"/>
<MkAcct :user="user" class="acct"/>
</div>
</div>
</div>
</div>
@@ -122,76 +124,78 @@ export default defineComponent({
<style lang="scss" scoped>
.tbhwbxda {
display: flex;
flex-direction: column;
overflow: auto;
height: 100%;
&.result.hit {
padding: 0;
}
&.recent {
padding: 0;
}
> .inputs {
> .input {
display: inline-block;
width: 50%;
margin: 0;
}
}
> .users {
flex: 1;
> ._section {
display: flex;
flex-direction: column;
overflow: auto;
padding: 8px 0;
height: 100%;
> .user {
display: flex;
align-items: center;
padding: 8px var(--root-margin);
font-size: 14px;
&.result.hit {
padding: 0;
}
&:hover {
background: var(--X7);
&.recent {
padding: 0;
}
> .inputs {
> .input {
display: inline-block;
width: 50%;
margin: 0;
}
}
&.selected {
background: var(--accent);
color: #fff;
}
> .users {
flex: 1;
overflow: auto;
padding: 8px 0;
> * {
pointer-events: none;
user-select: none;
}
> .user {
display: flex;
align-items: center;
padding: 8px var(--root-margin);
font-size: 14px;
> .avatar {
width: 45px;
height: 45px;
}
> .body {
padding: 0 8px;
min-width: 0;
> .name {
display: block;
font-weight: bold;
&:hover {
background: var(--X7);
}
> .acct {
opacity: 0.5;
&.selected {
background: var(--accent);
color: #fff;
}
> * {
pointer-events: none;
user-select: none;
}
> .avatar {
width: 45px;
height: 45px;
}
> .body {
padding: 0 8px;
min-width: 0;
> .name {
display: block;
font-weight: bold;
}
> .acct {
opacity: 0.5;
}
}
}
}
}
> .empty {
opacity: 0.7;
text-align: center;
> .empty {
opacity: 0.7;
text-align: center;
}
}
}
</style>

View File

@@ -0,0 +1,168 @@
<template>
<FormBase>
<FormSuspense :p="init">
<FormInput v-model:value="title">
<span>{{ $ts.title }}</span>
</FormInput>
<FormTextarea v-model:value="description" :max="500">
<span>{{ $ts.description }}</span>
</FormTextarea>
<FormGroup>
<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
<div class="name">{{ file.name }}</div>
<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
</div>
<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
</FormGroup>
<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
<FormButton v-if="postId" @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
<FormButton v-else @click="save" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
<FormButton v-if="postId" @click="del" danger><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton>
</FormSuspense>
</FormBase>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import FormButton from '@client/components/form/button.vue';
import FormInput from '@client/components/form/input.vue';
import FormTextarea from '@client/components/form/textarea.vue';
import FormSwitch from '@client/components/form/switch.vue';
import FormTuple from '@client/components/form/tuple.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import FormSuspense from '@client/components/form/suspense.vue';
import { selectFile } from '@client/scripts/select-file';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
export default defineComponent({
components: {
FormButton,
FormInput,
FormTextarea,
FormSwitch,
FormBase,
FormGroup,
FormSuspense,
},
props: {
postId: {
type: String,
required: false,
default: null,
}
},
data() {
return {
[symbols.PAGE_INFO]: computed(() => this.postId ? {
title: this.$ts.edit,
icon: 'fas fa-pencil-alt'
} : {
title: this.$ts.postToGallery,
icon: 'fas fa-pencil-alt'
}),
init: null,
files: [],
description: null,
title: null,
isSensitive: false,
}
},
watch: {
postId: {
handler() {
this.init = () => this.postId ? os.api('gallery/posts/show', {
postId: this.postId
}).then(post => {
this.files = post.files;
this.title = post.title;
this.description = post.description;
this.isSensitive = post.isSensitive;
}) : Promise.resolve(null);
},
immediate: true,
}
},
methods: {
selectFile(e) {
selectFile(e.currentTarget || e.target, null, true).then(files => {
this.files = this.files.concat(files);
});
},
remove(file) {
this.files = this.files.filter(f => f.id !== file.id);
},
async save() {
if (this.postId) {
await os.apiWithDialog('gallery/posts/update', {
postId: this.postId,
title: this.title,
description: this.description,
fileIds: this.files.map(file => file.id),
isSensitive: this.isSensitive,
});
this.$router.push(`/gallery/${this.postId}`);
} else {
const post = await os.apiWithDialog('gallery/posts/create', {
title: this.title,
description: this.description,
fileIds: this.files.map(file => file.id),
isSensitive: this.isSensitive,
});
this.$router.push(`/gallery/${post.id}`);
}
},
async del() {
const { canceled } = await os.dialog({
type: 'warning',
text: this.$ts.deleteConfirm,
showCancelButton: true
});
if (canceled) return;
await os.apiWithDialog('gallery/posts/delete', {
postId: this.postId,
});
this.$router.push(`/gallery`);
}
}
});
</script>
<style lang="scss" scoped>
.wqugxsfx {
height: 200px;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
position: relative;
> .name {
position: absolute;
top: 8px;
left: 9px;
padding: 8px;
background: var(--panel);
}
> .remove {
position: absolute;
top: 8px;
right: 9px;
padding: 8px;
background: var(--panel);
}
}
</style>

View File

@@ -1,110 +0,0 @@
<template>
<FormBase>
<FormInput v-model:value="title">
<span>{{ $ts.title }}</span>
</FormInput>
<FormTextarea v-model:value="description" :max="500">
<span>{{ $ts.description }}</span>
</FormTextarea>
<FormGroup>
<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
<div class="name">{{ file.name }}</div>
<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
</div>
<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
</FormGroup>
<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
<FormButton @click="publish" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
</FormBase>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import FormButton from '@client/components/form/button.vue';
import FormInput from '@client/components/form/input.vue';
import FormTextarea from '@client/components/form/textarea.vue';
import FormSwitch from '@client/components/form/switch.vue';
import FormTuple from '@client/components/form/tuple.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import { selectFile } from '@client/scripts/select-file';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
export default defineComponent({
components: {
FormButton,
FormInput,
FormTextarea,
FormSwitch,
FormBase,
FormGroup,
},
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.postToGallery,
icon: 'fas fa-pencil-alt'
},
files: [],
description: null,
title: null,
isSensitive: false,
}
},
methods: {
selectFile(e) {
selectFile(e.currentTarget || e.target, null, true).then(files => {
this.files = this.files.concat(files);
});
},
remove(file) {
this.files = this.files.filter(f => f.id !== file.id);
},
async publish() {
const post = await os.apiWithDialog('gallery/posts/create', {
title: this.title,
description: this.description,
fileIds: this.files.map(file => file.id),
isSensitive: this.isSensitive,
});
this.$router.push(`/gallery/${post.id}`);
}
}
});
</script>
<style lang="scss" scoped>
.wqugxsfx {
height: 200px;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
position: relative;
> .name {
position: absolute;
top: 8px;
left: 9px;
padding: 8px;
background: var(--panel);
}
> .remove {
position: absolute;
top: 8px;
right: 9px;
padding: 8px;
background: var(--panel);
}
}
</style>

View File

@@ -19,6 +19,7 @@
<MkButton class="button" @click="like()" v-else v-tooltip="$ts._gallery.like"><i class="far fa-heart"></i><span class="count" v-if="post.likedCount > 0">{{ post.likedCount }}</span></MkButton>
</div>
<div class="other">
<button v-if="$i && $i.id === post.user.id" class="_button" @click="edit" v-tooltip="$ts.edit" v-click-anime><i class="fas fa-pencil-alt fa-fw"></i></button>
<button class="_button" @click="shareWithNote" v-tooltip="$ts.shareWithNote" v-click-anime><i class="fas fa-retweet fa-fw"></i></button>
<button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
</div>
@@ -84,6 +85,11 @@ export default defineComponent({
title: this.post.title,
text: this.post.description,
},
actions: [{
icon: 'fas fa-pencil-alt',
text: this.$ts.edit,
handler: this.edit
}]
} : null),
otherPostsPagination: {
endpoint: 'users/gallery/posts',
@@ -154,6 +160,10 @@ export default defineComponent({
this.post.likedCount--;
});
},
edit() {
this.$router.push(`/gallery/${this.post.id}/edit`);
}
}
});
</script>

View File

@@ -25,7 +25,6 @@ export default defineComponent({
endpoint: 'notes/mentions',
limit: 10,
},
faAt
};
},

View File

@@ -157,7 +157,6 @@ export default defineComponent({
maps: maps,
form: null,
messages: [],
fasCircle, farCircle
};
},

View File

@@ -161,15 +161,15 @@
</dl>
</div>
<div class="status">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" v-click-anime>
<b>{{ number(user.notesCount) }}</b>
<span>{{ $ts.notes }}</span>
</MkA>
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }" v-click-anime>
<b>{{ number(user.followingCount) }}</b>
<span>{{ $ts.following }}</span>
</MkA>
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }" v-click-anime>
<b>{{ number(user.followersCount) }}</b>
<span>{{ $ts.followers }}</span>
</MkA>

View File

@@ -38,7 +38,8 @@ export const router = createRouter({
{ path: '/pages/new', component: page('page-editor/page-editor') },
{ path: '/pages/edit/:pageId', component: page('page-editor/page-editor'), props: route => ({ initPageId: route.params.pageId }) },
{ path: '/gallery', component: page('gallery/index') },
{ path: '/gallery/new', component: page('gallery/new') },
{ path: '/gallery/new', component: page('gallery/edit') },
{ path: '/gallery/:postId/edit', component: page('gallery/edit'), props: route => ({ postId: route.params.postId }) },
{ path: '/gallery/:postId', component: page('gallery/post'), props: route => ({ postId: route.params.postId }) },
{ path: '/channels', component: page('channels') },
{ path: '/channels/new', component: page('channel-editor') },

View File

@@ -18,9 +18,11 @@ export const builtinThemes = [
require('@client/themes/l-light.json5'),
require('@client/themes/l-apricot.json5'),
require('@client/themes/l-rainy.json5'),
require('@client/themes/l-vivid.json5'),
require('@client/themes/d-dark.json5'),
require('@client/themes/d-persimmon.json5'),
require('@client/themes/d-astro.json5'),
require('@client/themes/d-black.json5'),
] as Theme[];

View File

@@ -0,0 +1,76 @@
{
id: '080a01c5-377d-4fbb-88cc-6bb5d04977ea',
base: 'dark',
name: 'Mi Astro',
author: 'syuilo',
props: {
bg: '#232125',
fg: '#efdab9',
cwBg: '#687390',
cwFg: '#393f4f',
link: '#78b0a0',
warn: '#ecb637',
badge: '#31b1ce',
error: '#ec4137',
focus: ':alpha<0.3<@accent',
navBg: '@panel',
navFg: '@fg',
panel: '#2a272b',
accent: '#81c08b',
header: ':alpha<0.7<@bg',
infoBg: '#253142',
infoFg: '#fff',
renote: '#659CC8',
shadow: 'rgba(0, 0, 0, 0.3)',
divider: 'rgba(255, 255, 255, 0.1)',
hashtag: '#ff9156',
mention: '#ffd152',
modalBg: 'rgba(0, 0, 0, 0.5)',
success: '#86b300',
buttonBg: 'rgba(255, 255, 255, 0.05)',
acrylicBg: ':alpha<0.5<@bg',
cwHoverBg: '#707b97',
indicator: '@accent',
mentionMe: '#fb5d38',
messageBg: ':lighten<5<@bg',
navActive: '@accent',
infoWarnBg: '#42321c',
infoWarnFg: '#ffbd3e',
navHoverFg: ':lighten<17<@fg',
dateLabelFg: '@fg',
inputBorder: '#959da2',
panelBorder: 'rgba(0, 0, 0, 0)',
panelShadow: '" 0 8px 24px rgba(0, 0, 0, 0.12)',
accentDarken: ':darken<10<@accent',
acrylicPanel: ':alpha<0.5<@panel',
navIndicator: '@accent',
accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg',
panelHeaderBg: ':lighten<3<@panel',
panelHeaderFg: '@fg',
htmlThemeColor: '@bg',
panelHighlight: ':lighten<3<@panel',
listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
scrollbarHandle: 'rgba(255, 255, 255, 0.2)',
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)',
X2: ':darken<2<@panel',
X3: 'rgba(255, 255, 255, 0.05)',
X4: 'rgba(255, 255, 255, 0.1)',
X5: 'rgba(255, 255, 255, 0.05)',
X6: 'rgba(255, 255, 255, 0.15)',
X7: 'rgba(255, 255, 255, 0.05)',
X8: ':lighten<5<@accent',
X9: ':darken<5<@accent',
X10: ':alpha<0.4<@accent',
X11: 'rgba(0, 0, 0, 0.3)',
X12: 'rgba(255, 255, 255, 0.1)',
X13: 'rgba(255, 255, 255, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
X16: ':alpha<0.7<@panel',
},
}

View File

@@ -10,7 +10,7 @@
props: {
bg: '#f9f9f9',
fg: '#676767',
divider: 'rgb(223, 223, 223)',
divider: '#e8e8e8',
header: ':alpha<0.7<@panel',
navBg: '#fff',
panel: '#fff',

View File

@@ -0,0 +1,82 @@
{
id: '6128c2a9-5c54-43fe-a47d-17942356470b',
name: 'Mi Vivid',
author: 'syuilo',
base: 'light',
props: {
bg: '#fafafa',
fg: '#444',
cwBg: '#b1b9c1',
cwFg: '#fff',
link: '#ff9400',
warn: '#ecb637',
badge: '#31b1ce',
error: '#ec4137',
focus: ':alpha<0.3<@accent',
navBg: '@panel',
navFg: '@fg',
panel: '#fff',
accent: '#008cff',
header: ':alpha<0.7<@panel',
infoBg: '#e5f5ff',
infoFg: '#72818a',
renote: '@accent',
shadow: 'rgba(0, 0, 0, 0.1)',
divider: 'rgba(0, 0, 0, 0.08)',
hashtag: '#92d400',
mention: '@accent',
modalBg: 'rgba(0, 0, 0, 0.3)',
success: '#86b300',
buttonBg: 'rgba(0, 0, 0, 0.05)',
acrylicBg: ':alpha<0.5<@bg',
cwHoverBg: '#bbc4ce',
indicator: '@accent',
mentionMe: '@mention',
messageBg: '@panel',
navActive: '@accent',
infoWarnBg: '#fff0db',
infoWarnFg: '#573c08',
navHoverFg: ':darken<17<@fg',
dateLabelFg: '@fg',
inputBorder: '#dae0e4',
panelBorder: 'rgba(0, 0, 0, 0)',
panelShadow: '" 0 8px 24px rgb(21 43 75 / 8%)',
accentDarken: ':darken<10<@accent',
acrylicPanel: ':alpha<0.5<@panel',
navIndicator: '@accent',
accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(0, 0, 0, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':darken<3<@fg',
fgTransparent: ':alpha<0.5<@fg',
panelHeaderBg: ':lighten<3<@panel',
panelHeaderFg: '@fg',
htmlThemeColor: '@bg',
panelHighlight: ':darken<3<@panel',
listItemHoverBg: 'rgba(0, 0, 0, 0.03)',
scrollbarHandle: 'rgba(0, 0, 0, 0.2)',
wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
fgTransparentWeak: ':alpha<0.75<@fg',
panelHeaderDivider: '@divider',
scrollbarHandleHover: 'rgba(0, 0, 0, 0.4)',
X2: ':darken<2<@panel',
X3: 'rgba(0, 0, 0, 0.05)',
X4: 'rgba(0, 0, 0, 0.1)',
X5: 'rgba(0, 0, 0, 0.05)',
X6: 'rgba(0, 0, 0, 0.25)',
X7: 'rgba(0, 0, 0, 0.05)',
X8: ':lighten<5<@accent',
X9: ':darken<5<@accent',
X10: ':alpha<0.4<@accent',
X11: 'rgba(0, 0, 0, 0.1)',
X12: 'rgba(0, 0, 0, 0.1)',
X13: 'rgba(0, 0, 0, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
X16: ':alpha<0.7<@panel',
X17: ':alpha<0.8<@bg',
},
}

View File

@@ -36,7 +36,6 @@ export default defineComponent({
endpoint: 'notes/mentions',
limit: 10,
},
faAt
}
},

View File

@@ -110,7 +110,7 @@ y = Math.floor(pos / mapWidth)
```
### フォームコントロールの種類
#### スイッチ
#### Interruttore
type: `switch` スイッチを表示します。何かの機能をオン/オフさせたい場合に有用です。
##### プロパティ

View File

@@ -0,0 +1,40 @@
import $ from 'cafy';
import define from '../../../define';
import { ApiError } from '../../../error';
import { GalleryPosts } from '../../../../../models';
import { ID } from '@/misc/cafy-id';
export const meta = {
tags: ['gallery'],
requireCredential: true as const,
kind: 'write:gallery',
params: {
postId: {
validator: $.type(ID),
},
},
errors: {
noSuchPost: {
message: 'No such post.',
code: 'NO_SUCH_POST',
id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5'
},
}
};
export default define(meta, async (ps, user) => {
const post = await GalleryPosts.findOne({
id: ps.postId,
userId: user.id,
});
if (post == null) {
throw new ApiError(meta.errors.noSuchPost);
}
await GalleryPosts.delete(post.id);
});

View File

@@ -0,0 +1,81 @@
import $ from 'cafy';
import * as ms from 'ms';
import define from '../../../define';
import { ID } from '../../../../../misc/cafy-id';
import { DriveFiles, GalleryPosts } from '../../../../../models';
import { GalleryPost } from '../../../../../models/entities/gallery-post';
import { ApiError } from '../../../error';
export const meta = {
tags: ['gallery'],
requireCredential: true as const,
kind: 'write:gallery',
limit: {
duration: ms('1hour'),
max: 300
},
params: {
postId: {
validator: $.type(ID),
},
title: {
validator: $.str.min(1),
},
description: {
validator: $.optional.nullable.str,
},
fileIds: {
validator: $.arr($.type(ID)).unique().range(1, 32),
},
isSensitive: {
validator: $.optional.bool,
default: false,
},
},
res: {
type: 'object' as const,
optional: false as const, nullable: false as const,
ref: 'GalleryPost',
},
errors: {
}
};
export default define(meta, async (ps, user) => {
const files = (await Promise.all(ps.fileIds.map(fileId =>
DriveFiles.findOne({
id: fileId,
userId: user.id
})
))).filter(file => file != null);
if (files.length === 0) {
throw new Error();
}
await GalleryPosts.update({
id: ps.postId,
userId: user.id,
}, {
updatedAt: new Date(),
title: ps.title,
description: ps.description,
isSensitive: ps.isSensitive,
fileIds: files.map(file => file.id)
});
const post = await GalleryPosts.findOneOrFail(ps.postId);
return await GalleryPosts.pack(post, user);
});

View File

@@ -252,7 +252,7 @@ router.get('/users/:user', async ctx => {
});
// Note
router.get('/notes/:note', async ctx => {
router.get('/notes/:note', async (ctx, next) => {
const note = await Notes.findOne(ctx.params.note);
if (note) {
@@ -277,11 +277,11 @@ router.get('/notes/:note', async ctx => {
return;
}
ctx.status = 404;
await next();
});
// Page
router.get('/@:user/pages/:page', async ctx => {
router.get('/@:user/pages/:page', async (ctx, next) => {
const { username, host } = parseAcct(ctx.params.user);
const user = await Users.findOne({
usernameLower: username.toLowerCase(),
@@ -314,12 +314,12 @@ router.get('/@:user/pages/:page', async ctx => {
return;
}
ctx.status = 404;
await next();
});
// Clip
// TODO: 非publicなclipのハンドリング
router.get('/clips/:clip', async ctx => {
router.get('/clips/:clip', async (ctx, next) => {
const clip = await Clips.findOne({
id: ctx.params.clip,
});
@@ -339,11 +339,11 @@ router.get('/clips/:clip', async ctx => {
return;
}
ctx.status = 404;
await next();
});
// Gallery post
router.get('/gallery/:post', async ctx => {
router.get('/gallery/:post', async (ctx, next) => {
const post = await GalleryPosts.findOne(ctx.params.post);
if (post) {
@@ -362,11 +362,11 @@ router.get('/gallery/:post', async ctx => {
return;
}
ctx.status = 404;
await next();
});
// Channel
router.get('/channels/:channel', async ctx => {
router.get('/channels/:channel', async (ctx, next) => {
const channel = await Channels.findOne({
id: ctx.params.channel,
});
@@ -384,7 +384,7 @@ router.get('/channels/:channel', async ctx => {
return;
}
ctx.status = 404;
await next();
});
//#endregion