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…
	
	Add table
		Add a link
		
	
		Reference in a new issue