mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-29 20:39:15 +01:00
Merge branch 'develop'
This commit is contained in:
commit
17fff8c665
23 changed files with 562 additions and 153 deletions
|
@ -900,11 +900,13 @@ _theme:
|
||||||
funcKind: "Type de fonction"
|
funcKind: "Type de fonction"
|
||||||
argument: "Argument"
|
argument: "Argument"
|
||||||
alpha: "Transparence"
|
alpha: "Transparence"
|
||||||
darken: "Assombrir"
|
darken: "Sombre"
|
||||||
|
lighten: "Clair"
|
||||||
inputConstantName: "Insérez un nom de constante"
|
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."
|
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} ?"
|
deleteConstantConfirm: "Êtes-vous sûr·e de vouloir supprimer la constante {const} ?"
|
||||||
keys:
|
keys:
|
||||||
|
accent: "Accentuation"
|
||||||
bg: "Arrière-plan"
|
bg: "Arrière-plan"
|
||||||
fg: "Texte"
|
fg: "Texte"
|
||||||
focus: "Mise au point"
|
focus: "Mise au point"
|
||||||
|
@ -940,6 +942,8 @@ _theme:
|
||||||
driveFolderBg: "Arrière-plan du dossier de disque"
|
driveFolderBg: "Arrière-plan du dossier de disque"
|
||||||
badge: "Badge"
|
badge: "Badge"
|
||||||
messageBg: "Arrière plan de la discussion"
|
messageBg: "Arrière plan de la discussion"
|
||||||
|
accentDarken: "Plus sombre"
|
||||||
|
accentLighten: "Plus clair"
|
||||||
fgHighlighted: "Texte mis en évidence"
|
fgHighlighted: "Texte mis en évidence"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Nouvelle note"
|
note: "Nouvelle note"
|
||||||
|
@ -1155,12 +1159,12 @@ _instanceCharts:
|
||||||
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
|
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
|
||||||
notes: "Variation du nombre des notes"
|
notes: "Variation du nombre des notes"
|
||||||
notesTotal: "Nombre total cumulé des notes"
|
notesTotal: "Nombre total cumulé des notes"
|
||||||
ff: "Variation des abonné·e·s"
|
ff: "Variation des abonné·e·s et des abonnements"
|
||||||
ffTotal: "Nombre d'abonné·e·s au total cumulé"
|
ffTotal: "Total cumulé du nombre d'abonné·e·s et du nombre d'abonnements"
|
||||||
cacheSize: "Variation de la taille du cache"
|
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"
|
files: "Variation du nombre de fichiers"
|
||||||
filesTotal: "Nombre de fichiers au total cumulé"
|
filesTotal: "Total cumulé du nombre de fichiers"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Principal"
|
home: "Principal"
|
||||||
local: "Local"
|
local: "Local"
|
||||||
|
@ -1237,7 +1241,7 @@ _pages:
|
||||||
deleted: "La page a été supprimée"
|
deleted: "La page a été supprimée"
|
||||||
pageSetting: "Paramètres de la Page"
|
pageSetting: "Paramètres de la Page"
|
||||||
nameAlreadyExists: "L'URL de page spécifiée existe déjà"
|
nameAlreadyExists: "L'URL de page spécifiée existe déjà"
|
||||||
invalidNameTitle: "La URL de la page spécifiée n’est pas valide"
|
invalidNameTitle: "L'URL de page spécifiée n’est pas valide"
|
||||||
invalidNameText: "Assurez-vous qu’il n’est pas vide"
|
invalidNameText: "Assurez-vous qu’il n’est pas vide"
|
||||||
editThisPage: "Éditer cette page"
|
editThisPage: "Éditer cette page"
|
||||||
viewSource: "Afficher la source"
|
viewSource: "Afficher la source"
|
||||||
|
@ -1259,14 +1263,14 @@ _pages:
|
||||||
font: "Police de caractères"
|
font: "Police de caractères"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans Serif"
|
fontSansSerif: "Sans Serif"
|
||||||
eyeCatchingImageSet: "Définir une image attirante"
|
eyeCatchingImageSet: "Définir une image attractive"
|
||||||
eyeCatchingImageRemove: "Supprimer une image attirante"
|
eyeCatchingImageRemove: "Supprimer l'image attractive"
|
||||||
chooseBlock: "Ajouter un bloc"
|
chooseBlock: "Ajouter un bloc"
|
||||||
selectType: "Choisir un type"
|
selectType: "Choisir un type"
|
||||||
enterVariableName: "Veuillez entrer un nom pour votre variable"
|
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"
|
contentBlocks: "Contenu"
|
||||||
inputBlocks: "Entrée"
|
inputBlocks: "Blocs d'entrée"
|
||||||
specialBlocks: "Spécial"
|
specialBlocks: "Spécial"
|
||||||
blocks:
|
blocks:
|
||||||
text: "Texte"
|
text: "Texte"
|
||||||
|
|
|
@ -571,6 +571,7 @@ useGlobalSetting: "Usa impostazioni generali"
|
||||||
useGlobalSettingDesc: "Se abilitato, le impostazioni notifiche dell'account verranno utilizzate. Se disabilitato, si possono definire diverse singole impostazioni."
|
useGlobalSettingDesc: "Se abilitato, le impostazioni notifiche dell'account verranno utilizzate. Se disabilitato, si possono definire diverse singole impostazioni."
|
||||||
other: "Avanzate"
|
other: "Avanzate"
|
||||||
fileIdOrUrl: "ID o URL del file"
|
fileIdOrUrl: "ID o URL del file"
|
||||||
|
chatOpenBehavior: "Comportamento della finestra di chat quando viene aperta"
|
||||||
behavior: "Comportamento"
|
behavior: "Comportamento"
|
||||||
abuseReports: "Segnala"
|
abuseReports: "Segnala"
|
||||||
reportAbuse: "Segnala"
|
reportAbuse: "Segnala"
|
||||||
|
@ -652,8 +653,10 @@ youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
|
||||||
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
|
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
|
||||||
usageAmount: "In utilizzo"
|
usageAmount: "In utilizzo"
|
||||||
capacity: "Capacità"
|
capacity: "Capacità"
|
||||||
|
inUse: "In utilizzo"
|
||||||
editCode: "Modifica codice"
|
editCode: "Modifica codice"
|
||||||
apply: "Applica"
|
apply: "Applica"
|
||||||
|
receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
|
||||||
emailNotification: "Eventi per notifiche via mail"
|
emailNotification: "Eventi per notifiche via mail"
|
||||||
publish: "Pubblico"
|
publish: "Pubblico"
|
||||||
inChannelSearch: "Cerca in canale"
|
inChannelSearch: "Cerca in canale"
|
||||||
|
@ -932,6 +935,7 @@ _widgets:
|
||||||
photos: "Foto"
|
photos: "Foto"
|
||||||
digitalClock: "Orologio digitale"
|
digitalClock: "Orologio digitale"
|
||||||
federation: "Federazione"
|
federation: "Federazione"
|
||||||
|
postForm: "Finestra di pubblicazione"
|
||||||
button: "Pulsante"
|
button: "Pulsante"
|
||||||
onlineUsers: "Utenti online"
|
onlineUsers: "Utenti online"
|
||||||
jobQueue: "Coda di lavoro"
|
jobQueue: "Coda di lavoro"
|
||||||
|
@ -1005,6 +1009,9 @@ _instanceCharts:
|
||||||
users: "Variazione del numero di utenti"
|
users: "Variazione del numero di utenti"
|
||||||
usersTotal: "Totale cumulativo di utenti"
|
usersTotal: "Totale cumulativo di utenti"
|
||||||
notes: "Variazione del numero di note"
|
notes: "Variazione del numero di note"
|
||||||
|
notesTotal: "Totale cumulato di note"
|
||||||
|
files: "Variazione del numero di file"
|
||||||
|
filesTotal: "Totale cumulato del numero di file"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "Home"
|
home: "Home"
|
||||||
local: "Locale"
|
local: "Locale"
|
||||||
|
@ -1012,8 +1019,16 @@ _timelines:
|
||||||
global: "Federata"
|
global: "Federata"
|
||||||
_rooms:
|
_rooms:
|
||||||
roomOf: "Camera di {user}"
|
roomOf: "Camera di {user}"
|
||||||
|
addFurniture: "Disponi mobilia"
|
||||||
|
translate: "Sposta"
|
||||||
|
rotate: "Ruota"
|
||||||
|
exit: "Indietro"
|
||||||
remove: "Togli"
|
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?"
|
leaveConfirm: "Hai fatto modifiche ancora non salvate. Vuoi davvero uscire?"
|
||||||
|
chooseImage: "Seleziona immagine"
|
||||||
|
roomType: "Tipo di stanza"
|
||||||
_roomType:
|
_roomType:
|
||||||
default: "Predefinito"
|
default: "Predefinito"
|
||||||
washitsu: "Washitsu"
|
washitsu: "Washitsu"
|
||||||
|
@ -1050,6 +1065,7 @@ _rooms:
|
||||||
cube: "Cubo"
|
cube: "Cubo"
|
||||||
tv: "Televisore"
|
tv: "Televisore"
|
||||||
pinguin: "Pinguino"
|
pinguin: "Pinguino"
|
||||||
|
rubik-cube: "Cubo di Rubik"
|
||||||
bin: "Cestino"
|
bin: "Cestino"
|
||||||
cup-noodle: "Noodle istantanei"
|
cup-noodle: "Noodle istantanei"
|
||||||
_pages:
|
_pages:
|
||||||
|
@ -1060,6 +1076,8 @@ _pages:
|
||||||
updated: "Pagina aggiornata con successo!"
|
updated: "Pagina aggiornata con successo!"
|
||||||
deleted: "Pagina eliminata"
|
deleted: "Pagina eliminata"
|
||||||
pageSetting: "Impostazioni pagina"
|
pageSetting: "Impostazioni pagina"
|
||||||
|
nameAlreadyExists: "Esiste già una pagina con lo stesso URL."
|
||||||
|
invalidNameTitle: "L'URL di pagina definito non è valido"
|
||||||
editThisPage: "Modifica questa pagina"
|
editThisPage: "Modifica questa pagina"
|
||||||
viewSource: "Visualizza sorgente"
|
viewSource: "Visualizza sorgente"
|
||||||
viewPage: "Visualizza pagina"
|
viewPage: "Visualizza pagina"
|
||||||
|
@ -1072,11 +1090,21 @@ _pages:
|
||||||
content: "Blocco di pagina"
|
content: "Blocco di pagina"
|
||||||
variables: "Variabili"
|
variables: "Variabili"
|
||||||
title: "Titolo"
|
title: "Titolo"
|
||||||
|
url: "URL della pagina"
|
||||||
|
summary: "Riassunto di pagina"
|
||||||
hideTitleWhenPinned: "Nascondere il titolo pagina quando è fissata in cima al profilo."
|
hideTitleWhenPinned: "Nascondere il titolo pagina quando è fissata in cima al profilo."
|
||||||
font: "Tipo di carattere"
|
font: "Tipo di carattere"
|
||||||
fontSerif: "Serif"
|
fontSerif: "Serif"
|
||||||
fontSansSerif: "Sans serif"
|
fontSansSerif: "Sans serif"
|
||||||
|
eyeCatchingImageSet: "Imposta un'immagine attrattiva"
|
||||||
|
eyeCatchingImageRemove: "Elimina l'immagine attrattiva"
|
||||||
chooseBlock: "Aggiungi blocco"
|
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:
|
blocks:
|
||||||
text: "Testo"
|
text: "Testo"
|
||||||
textarea: "Area di testo"
|
textarea: "Area di testo"
|
||||||
|
@ -1086,16 +1114,20 @@ _pages:
|
||||||
if: "Se"
|
if: "Se"
|
||||||
_if:
|
_if:
|
||||||
variable: "Variabili"
|
variable: "Variabili"
|
||||||
|
post: "Finestra di pubblicazione"
|
||||||
_post:
|
_post:
|
||||||
text: "Contenuto"
|
text: "Contenuto"
|
||||||
|
textInput: "Immissione testo"
|
||||||
_textInput:
|
_textInput:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
default: "Valore predefinito"
|
default: "Valore predefinito"
|
||||||
|
textareaInput: "Immissione testo a più righe"
|
||||||
_textareaInput:
|
_textareaInput:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
default: "Valore predefinito"
|
default: "Valore predefinito"
|
||||||
|
numberInput: "Immissione numerica"
|
||||||
_numberInput:
|
_numberInput:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
|
@ -1108,24 +1140,35 @@ _pages:
|
||||||
id: "ID nota"
|
id: "ID nota"
|
||||||
idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
|
idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
|
||||||
detailed: "Visualizzazione dettagliata"
|
detailed: "Visualizzazione dettagliata"
|
||||||
|
switch: "Interruttore"
|
||||||
_switch:
|
_switch:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
default: "Valore predefinito"
|
default: "Valore predefinito"
|
||||||
|
counter: "Contatore"
|
||||||
_counter:
|
_counter:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
|
inc: "Valore da aggiungere"
|
||||||
_button:
|
_button:
|
||||||
text: "Titolo"
|
text: "Titolo"
|
||||||
|
colored: "Colorato"
|
||||||
|
action: "Operazione da eseguire quando viene premuto il pulsante"
|
||||||
_action:
|
_action:
|
||||||
|
dialog: "Visualizzare una finestra di dialogo"
|
||||||
_dialog:
|
_dialog:
|
||||||
content: "Contenuto"
|
content: "Contenuto"
|
||||||
|
resetRandom: "Ripristinare un numero aleatorio"
|
||||||
pushEvent: "Inviare evento"
|
pushEvent: "Inviare evento"
|
||||||
_pushEvent:
|
_pushEvent:
|
||||||
event: "Nome evento"
|
event: "Nome evento"
|
||||||
message: "Messaggio da visualizzare quando abilitato"
|
message: "Messaggio da visualizzare quando abilitato"
|
||||||
variable: "Variabile da inviare"
|
variable: "Variabile da inviare"
|
||||||
no-variable: "Nessun contenuto"
|
no-variable: "Nessun contenuto"
|
||||||
|
callAiScript: "Chiamare AiScript"
|
||||||
|
_callAiScript:
|
||||||
|
functionName: "Nome della funzione"
|
||||||
|
radioButton: "Opzioni"
|
||||||
_radioButton:
|
_radioButton:
|
||||||
name: "Nome della variabile"
|
name: "Nome della variabile"
|
||||||
title: "Titolo"
|
title: "Titolo"
|
||||||
|
@ -1139,6 +1182,8 @@ _pages:
|
||||||
list: "Liste"
|
list: "Liste"
|
||||||
blocks:
|
blocks:
|
||||||
text: "Testo"
|
text: "Testo"
|
||||||
|
multiLineText: "Testo (a più righe)"
|
||||||
|
textList: "Lista di testo"
|
||||||
_strLen:
|
_strLen:
|
||||||
arg1: "Testo"
|
arg1: "Testo"
|
||||||
_strPick:
|
_strPick:
|
||||||
|
@ -1193,13 +1238,18 @@ _pages:
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
_if:
|
_if:
|
||||||
arg1: "Se"
|
arg1: "Se"
|
||||||
|
arg2: "Se"
|
||||||
random: "Aleatorietà"
|
random: "Aleatorietà"
|
||||||
_randomPick:
|
_randomPick:
|
||||||
arg1: "Liste"
|
arg1: "Liste"
|
||||||
_dailyRandomPick:
|
_dailyRandomPick:
|
||||||
arg1: "Liste"
|
arg1: "Liste"
|
||||||
|
_seedRandom:
|
||||||
|
arg2: "Probabilità"
|
||||||
_seedRandomPick:
|
_seedRandomPick:
|
||||||
arg2: "Liste"
|
arg2: "Liste"
|
||||||
|
_DRPWPM:
|
||||||
|
arg1: "Lista di testo"
|
||||||
_pick:
|
_pick:
|
||||||
arg1: "Liste"
|
arg1: "Liste"
|
||||||
_listLen:
|
_listLen:
|
||||||
|
@ -1213,6 +1263,7 @@ _pages:
|
||||||
types:
|
types:
|
||||||
string: "Testo"
|
string: "Testo"
|
||||||
array: "Liste"
|
array: "Liste"
|
||||||
|
stringArray: "Lista di testo"
|
||||||
_notification:
|
_notification:
|
||||||
fileUploaded: "File caricato correttamente"
|
fileUploaded: "File caricato correttamente"
|
||||||
youGotMention: "{name} ti ha menzionato"
|
youGotMention: "{name} ti ha menzionato"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||||
"version": "12.79.1",
|
"version": "12.79.2",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
|
||||||
type Captcha = {
|
type Captcha = {
|
||||||
render(container: string | Node, options: {
|
render(container: string | Node, options: {
|
||||||
|
@ -32,7 +32,7 @@ declare global {
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
provider: {
|
provider: {
|
||||||
type: String,
|
type: String as PropType<CaptchaProvider>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
sitekey: {
|
sitekey: {
|
||||||
|
@ -51,19 +51,25 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
loaded() {
|
variable(): string {
|
||||||
return !!window[this.provider as CaptchaProvider];
|
switch (this.provider) {
|
||||||
|
case 'hcaptcha': return 'hcaptcha';
|
||||||
|
case 'recaptcha': return 'grecaptcha';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
src() {
|
loaded(): boolean {
|
||||||
|
return !!window[this.variable];
|
||||||
|
},
|
||||||
|
src(): string {
|
||||||
const endpoint = ({
|
const endpoint = ({
|
||||||
hcaptcha: 'https://hcaptcha.com/1',
|
hcaptcha: 'https://hcaptcha.com/1',
|
||||||
recaptcha: 'https://www.recaptcha.net/recaptcha',
|
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() {
|
captcha(): Captcha {
|
||||||
return window[this.provider as CaptchaProvider] || {} as unknown as Captcha;
|
return window[this.variable] || {} as unknown as Captcha;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -94,7 +100,7 @@ export default defineComponent({
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
reset() {
|
reset() {
|
||||||
this.captcha?.reset();
|
if (this.captcha?.reset) this.captcha.reset();
|
||||||
},
|
},
|
||||||
requestRender() {
|
requestRender() {
|
||||||
if (this.captcha.render && this.$refs.captcha instanceof Element) {
|
if (this.captcha.render && this.$refs.captcha instanceof Element) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ export default defineComponent({
|
||||||
getMenu() {
|
getMenu() {
|
||||||
return [{
|
return [{
|
||||||
text: this.$ts.rename,
|
text: this.$ts.rename,
|
||||||
icon: faICursor,
|
icon: 'fas fa-i-cursor',
|
||||||
action: this.rename
|
action: this.rename
|
||||||
}, {
|
}, {
|
||||||
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||||
|
|
|
@ -247,7 +247,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}, null, {
|
}, null, {
|
||||||
text: this.$ts.rename,
|
text: this.$ts.rename,
|
||||||
icon: faICursor,
|
icon: 'fas fa-i-cursor',
|
||||||
action: this.rename
|
action: this.rename
|
||||||
}, null, {
|
}, null, {
|
||||||
text: this.$ts.delete,
|
text: this.$ts.delete,
|
||||||
|
|
|
@ -614,7 +614,7 @@ export default defineComponent({
|
||||||
type: 'label'
|
type: 'label'
|
||||||
}, this.folder ? {
|
}, this.folder ? {
|
||||||
text: this.$ts.renameFolder,
|
text: this.$ts.renameFolder,
|
||||||
icon: faICursor,
|
icon: 'fas fa-i-cursor',
|
||||||
action: () => { this.renameFolder(this.folder); }
|
action: () => { this.renameFolder(this.folder); }
|
||||||
} : undefined, this.folder ? {
|
} : undefined, this.folder ? {
|
||||||
text: this.$ts.deleteFolder,
|
text: this.$ts.deleteFolder,
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default defineComponent({
|
||||||
if (this.menu) return;
|
if (this.menu) return;
|
||||||
this.menu = os.modalMenu([{
|
this.menu = os.modalMenu([{
|
||||||
text: this.$ts.renameFile,
|
text: this.$ts.renameFile,
|
||||||
icon: faICursor,
|
icon: 'fas fa-i-cursor',
|
||||||
action: () => { this.rename(file) }
|
action: () => { this.rename(file) }
|
||||||
}, {
|
}, {
|
||||||
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||||
|
|
168
src/client/pages/gallery/edit.vue
Normal file
168
src/client/pages/gallery/edit.vue
Normal 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>
|
|
@ -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>
|
|
|
@ -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>
|
<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>
|
||||||
<div class="other">
|
<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="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>
|
<button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,6 +85,11 @@ export default defineComponent({
|
||||||
title: this.post.title,
|
title: this.post.title,
|
||||||
text: this.post.description,
|
text: this.post.description,
|
||||||
},
|
},
|
||||||
|
actions: [{
|
||||||
|
icon: 'fas fa-pencil-alt',
|
||||||
|
text: this.$ts.edit,
|
||||||
|
handler: this.edit
|
||||||
|
}]
|
||||||
} : null),
|
} : null),
|
||||||
otherPostsPagination: {
|
otherPostsPagination: {
|
||||||
endpoint: 'users/gallery/posts',
|
endpoint: 'users/gallery/posts',
|
||||||
|
@ -154,6 +160,10 @@ export default defineComponent({
|
||||||
this.post.likedCount--;
|
this.post.likedCount--;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
edit() {
|
||||||
|
this.$router.push(`/gallery/${this.post.id}/edit`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,7 +25,6 @@ export default defineComponent({
|
||||||
endpoint: 'notes/mentions',
|
endpoint: 'notes/mentions',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
},
|
},
|
||||||
faAt
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -161,15 +161,15 @@
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="status">
|
<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>
|
<b>{{ number(user.notesCount) }}</b>
|
||||||
<span>{{ $ts.notes }}</span>
|
<span>{{ $ts.notes }}</span>
|
||||||
</MkA>
|
</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>
|
<b>{{ number(user.followingCount) }}</b>
|
||||||
<span>{{ $ts.following }}</span>
|
<span>{{ $ts.following }}</span>
|
||||||
</MkA>
|
</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>
|
<b>{{ number(user.followersCount) }}</b>
|
||||||
<span>{{ $ts.followers }}</span>
|
<span>{{ $ts.followers }}</span>
|
||||||
</MkA>
|
</MkA>
|
||||||
|
|
|
@ -38,7 +38,8 @@ export const router = createRouter({
|
||||||
{ path: '/pages/new', component: page('page-editor/page-editor') },
|
{ 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: '/pages/edit/:pageId', component: page('page-editor/page-editor'), props: route => ({ initPageId: route.params.pageId }) },
|
||||||
{ path: '/gallery', component: page('gallery/index') },
|
{ 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: '/gallery/:postId', component: page('gallery/post'), props: route => ({ postId: route.params.postId }) },
|
||||||
{ path: '/channels', component: page('channels') },
|
{ path: '/channels', component: page('channels') },
|
||||||
{ path: '/channels/new', component: page('channel-editor') },
|
{ path: '/channels/new', component: page('channel-editor') },
|
||||||
|
|
|
@ -18,9 +18,11 @@ export const builtinThemes = [
|
||||||
require('@client/themes/l-light.json5'),
|
require('@client/themes/l-light.json5'),
|
||||||
require('@client/themes/l-apricot.json5'),
|
require('@client/themes/l-apricot.json5'),
|
||||||
require('@client/themes/l-rainy.json5'),
|
require('@client/themes/l-rainy.json5'),
|
||||||
|
require('@client/themes/l-vivid.json5'),
|
||||||
|
|
||||||
require('@client/themes/d-dark.json5'),
|
require('@client/themes/d-dark.json5'),
|
||||||
require('@client/themes/d-persimmon.json5'),
|
require('@client/themes/d-persimmon.json5'),
|
||||||
|
require('@client/themes/d-astro.json5'),
|
||||||
require('@client/themes/d-black.json5'),
|
require('@client/themes/d-black.json5'),
|
||||||
] as Theme[];
|
] as Theme[];
|
||||||
|
|
||||||
|
|
76
src/client/themes/d-astro.json5
Normal file
76
src/client/themes/d-astro.json5
Normal 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',
|
||||||
|
},
|
||||||
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
props: {
|
props: {
|
||||||
bg: '#f9f9f9',
|
bg: '#f9f9f9',
|
||||||
fg: '#676767',
|
fg: '#676767',
|
||||||
divider: 'rgb(223, 223, 223)',
|
divider: '#e8e8e8',
|
||||||
header: ':alpha<0.7<@panel',
|
header: ':alpha<0.7<@panel',
|
||||||
navBg: '#fff',
|
navBg: '#fff',
|
||||||
panel: '#fff',
|
panel: '#fff',
|
||||||
|
|
82
src/client/themes/l-vivid.json5
Normal file
82
src/client/themes/l-vivid.json5
Normal 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',
|
||||||
|
},
|
||||||
|
}
|
|
@ -36,7 +36,6 @@ export default defineComponent({
|
||||||
endpoint: 'notes/mentions',
|
endpoint: 'notes/mentions',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
},
|
},
|
||||||
faAt
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ y = Math.floor(pos / mapWidth)
|
||||||
```
|
```
|
||||||
|
|
||||||
### フォームコントロールの種類
|
### フォームコントロールの種類
|
||||||
#### スイッチ
|
#### Interruttore
|
||||||
type: `switch` スイッチを表示します。何かの機能をオン/オフさせたい場合に有用です。
|
type: `switch` スイッチを表示します。何かの機能をオン/オフさせたい場合に有用です。
|
||||||
|
|
||||||
##### プロパティ
|
##### プロパティ
|
||||||
|
|
40
src/server/api/endpoints/gallery/posts/delete.ts
Normal file
40
src/server/api/endpoints/gallery/posts/delete.ts
Normal 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);
|
||||||
|
});
|
81
src/server/api/endpoints/gallery/posts/update.ts
Normal file
81
src/server/api/endpoints/gallery/posts/update.ts
Normal 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);
|
||||||
|
});
|
|
@ -252,7 +252,7 @@ router.get('/users/:user', async ctx => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note
|
// Note
|
||||||
router.get('/notes/:note', async ctx => {
|
router.get('/notes/:note', async (ctx, next) => {
|
||||||
const note = await Notes.findOne(ctx.params.note);
|
const note = await Notes.findOne(ctx.params.note);
|
||||||
|
|
||||||
if (note) {
|
if (note) {
|
||||||
|
@ -277,11 +277,11 @@ router.get('/notes/:note', async ctx => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.status = 404;
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Page
|
// Page
|
||||||
router.get('/@:user/pages/:page', async ctx => {
|
router.get('/@:user/pages/:page', async (ctx, next) => {
|
||||||
const { username, host } = parseAcct(ctx.params.user);
|
const { username, host } = parseAcct(ctx.params.user);
|
||||||
const user = await Users.findOne({
|
const user = await Users.findOne({
|
||||||
usernameLower: username.toLowerCase(),
|
usernameLower: username.toLowerCase(),
|
||||||
|
@ -314,12 +314,12 @@ router.get('/@:user/pages/:page', async ctx => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.status = 404;
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clip
|
// Clip
|
||||||
// TODO: 非publicなclipのハンドリング
|
// TODO: 非publicなclipのハンドリング
|
||||||
router.get('/clips/:clip', async ctx => {
|
router.get('/clips/:clip', async (ctx, next) => {
|
||||||
const clip = await Clips.findOne({
|
const clip = await Clips.findOne({
|
||||||
id: ctx.params.clip,
|
id: ctx.params.clip,
|
||||||
});
|
});
|
||||||
|
@ -339,11 +339,11 @@ router.get('/clips/:clip', async ctx => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.status = 404;
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gallery post
|
// Gallery post
|
||||||
router.get('/gallery/:post', async ctx => {
|
router.get('/gallery/:post', async (ctx, next) => {
|
||||||
const post = await GalleryPosts.findOne(ctx.params.post);
|
const post = await GalleryPosts.findOne(ctx.params.post);
|
||||||
|
|
||||||
if (post) {
|
if (post) {
|
||||||
|
@ -362,11 +362,11 @@ router.get('/gallery/:post', async ctx => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.status = 404;
|
await next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Channel
|
// Channel
|
||||||
router.get('/channels/:channel', async ctx => {
|
router.get('/channels/:channel', async (ctx, next) => {
|
||||||
const channel = await Channels.findOne({
|
const channel = await Channels.findOne({
|
||||||
id: ctx.params.channel,
|
id: ctx.params.channel,
|
||||||
});
|
});
|
||||||
|
@ -384,7 +384,7 @@ router.get('/channels/:channel', async ctx => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.status = 404;
|
await next();
|
||||||
});
|
});
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue