wip: refactor(client): migrate components to composition api
This commit is contained in:
		
							parent
							
								
									3e9677904d
								
							
						
					
					
						commit
						9885c6ba6c
					
				
					 3 changed files with 175 additions and 208 deletions
				
			
		|  | @ -35,9 +35,9 @@ const emit = defineEmits<{ | |||
| 	(e: 'click', ev: MouseEvent): void; | ||||
| }>(); | ||||
| 
 | ||||
| const url = defaultStore.state.disableShowingAnimatedImages | ||||
| const url = $computed(() => defaultStore.state.disableShowingAnimatedImages | ||||
| 	? getStaticImageUrl(props.user.avatarUrl) | ||||
| 	: props.user.avatarUrl; | ||||
| 	: props.user.avatarUrl); | ||||
| 
 | ||||
| function onClick(ev: MouseEvent) { | ||||
| 	emit('click', ev); | ||||
|  |  | |||
|  | @ -3,50 +3,50 @@ | |||
| 	<div class="llvierxe" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }"> | ||||
| 		<div class="avatar _acrylic"> | ||||
| 			<MkAvatar class="avatar" :user="$i" :disable-link="true" @click="changeAvatar"/> | ||||
| 			<MkButton primary class="avatarEdit" @click="changeAvatar">{{ $ts._profile.changeAvatar }}</MkButton> | ||||
| 			<MkButton primary class="avatarEdit" @click="changeAvatar">{{ i18n.locale._profile.changeAvatar }}</MkButton> | ||||
| 		</div> | ||||
| 		<MkButton primary class="bannerEdit" @click="changeBanner">{{ $ts._profile.changeBanner }}</MkButton> | ||||
| 		<MkButton primary class="bannerEdit" @click="changeBanner">{{ i18n.locale._profile.changeBanner }}</MkButton> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<FormInput v-model="name" :max="30" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ $ts._profile.name }}</template> | ||||
| 	<FormInput v-model="profile.name" :max="30" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ i18n.locale._profile.name }}</template> | ||||
| 	</FormInput> | ||||
| 
 | ||||
| 	<FormTextarea v-model="description" :max="500" tall manual-save class="_formBlock"> | ||||
| 		<template #label>{{ $ts._profile.description }}</template> | ||||
| 		<template #caption>{{ $ts._profile.youCanIncludeHashtags }}</template> | ||||
| 	<FormTextarea v-model="profile.description" :max="500" tall manual-save class="_formBlock"> | ||||
| 		<template #label>{{ i18n.locale._profile.description }}</template> | ||||
| 		<template #caption>{{ i18n.locale._profile.youCanIncludeHashtags }}</template> | ||||
| 	</FormTextarea> | ||||
| 
 | ||||
| 	<FormInput v-model="location" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ $ts.location }}</template> | ||||
| 	<FormInput v-model="profile.location" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ i18n.locale.location }}</template> | ||||
| 		<template #prefix><i class="fas fa-map-marker-alt"></i></template> | ||||
| 	</FormInput> | ||||
| 
 | ||||
| 	<FormInput v-model="birthday" type="date" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ $ts.birthday }}</template> | ||||
| 	<FormInput v-model="profile.birthday" type="date" manual-save class="_formBlock"> | ||||
| 		<template #label>{{ i18n.locale.birthday }}</template> | ||||
| 		<template #prefix><i class="fas fa-birthday-cake"></i></template> | ||||
| 	</FormInput> | ||||
| 
 | ||||
| 	<FormSelect v-model="lang" class="_formBlock"> | ||||
| 		<template #label>{{ $ts.language }}</template> | ||||
| 	<FormSelect v-model="profile.lang" class="_formBlock"> | ||||
| 		<template #label>{{ i18n.locale.language }}</template> | ||||
| 		<option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option> | ||||
| 	</FormSelect> | ||||
| 
 | ||||
| 	<FormSlot> | ||||
| 		<MkButton @click="editMetadata">{{ $ts._profile.metadataEdit }}</MkButton> | ||||
| 		<template #caption>{{ $ts._profile.metadataDescription }}</template> | ||||
| 		<MkButton @click="editMetadata">{{ i18n.locale._profile.metadataEdit }}</MkButton> | ||||
| 		<template #caption>{{ i18n.locale._profile.metadataDescription }}</template> | ||||
| 	</FormSlot> | ||||
| 
 | ||||
| 	<FormSwitch v-model="isCat" class="_formBlock">{{ $ts.flagAsCat }}<template #caption>{{ $ts.flagAsCatDescription }}</template></FormSwitch> | ||||
| 	<FormSwitch v-model="profile.isCat" class="_formBlock">{{ i18n.locale.flagAsCat }}<template #caption>{{ i18n.locale.flagAsCatDescription }}</template></FormSwitch> | ||||
| 
 | ||||
| 	<FormSwitch v-model="isBot" class="_formBlock">{{ $ts.flagAsBot }}<template #caption>{{ $ts.flagAsBotDescription }}</template></FormSwitch> | ||||
| 	<FormSwitch v-model="profile.isBot" class="_formBlock">{{ i18n.locale.flagAsBot }}<template #caption>{{ i18n.locale.flagAsBotDescription }}</template></FormSwitch> | ||||
| 
 | ||||
| 	<FormSwitch v-model="alwaysMarkNsfw" class="_formBlock">{{ $ts.alwaysMarkSensitive }}</FormSwitch> | ||||
| 	<FormSwitch v-model="profile.alwaysMarkNsfw" class="_formBlock">{{ i18n.locale.alwaysMarkSensitive }}</FormSwitch> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { defineComponent, reactive, watch } from 'vue'; | ||||
| import MkButton from '@/components/ui/button.vue'; | ||||
| import FormInput from '@/components/form/input.vue'; | ||||
| import FormTextarea from '@/components/form/textarea.vue'; | ||||
|  | @ -57,194 +57,149 @@ import { host, langs } from '@/config'; | |||
| import { selectFile } from '@/scripts/select-file'; | ||||
| import * as os from '@/os'; | ||||
| import * as symbols from '@/symbols'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import { $i } from '@/account'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		MkButton, | ||||
| 		FormInput, | ||||
| 		FormTextarea, | ||||
| 		FormSwitch, | ||||
| 		FormSelect, | ||||
| 		FormSlot, | ||||
| const profile = reactive({ | ||||
| 	name: $i.name, | ||||
| 	description: $i.description, | ||||
| 	location: $i.location, | ||||
| 	birthday: $i.birthday, | ||||
| 	lang: $i.lang, | ||||
| 	isBot: $i.isBot, | ||||
| 	isCat: $i.isCat, | ||||
| 	alwaysMarkNsfw: $i.alwaysMarkNsfw, | ||||
| }); | ||||
| 
 | ||||
| const additionalFields = reactive({ | ||||
| 	fieldName0: $i.fields[0] ? $i.fields[0].name : null, | ||||
| 	fieldValue0: $i.fields[0] ? $i.fields[0].value : null, | ||||
| 	fieldName1: $i.fields[1] ? $i.fields[1].name : null, | ||||
| 	fieldValue1: $i.fields[1] ? $i.fields[1].value : null, | ||||
| 	fieldName2: $i.fields[2] ? $i.fields[2].name : null, | ||||
| 	fieldValue2: $i.fields[2] ? $i.fields[2].value : null, | ||||
| 	fieldName3: $i.fields[3] ? $i.fields[3].name : null, | ||||
| 	fieldValue3: $i.fields[3] ? $i.fields[3].value : null, | ||||
| }); | ||||
| 
 | ||||
| watch(() => profile, () => { | ||||
| 	save(); | ||||
| }, { | ||||
| 	deep: true, | ||||
| }); | ||||
| 
 | ||||
| function save() { | ||||
| 	os.apiWithDialog('i/update', { | ||||
| 		name: profile.name || null, | ||||
| 		description: profile.description || null, | ||||
| 		location: profile.location || null, | ||||
| 		birthday: profile.birthday || null, | ||||
| 		lang: profile.lang || null, | ||||
| 		isBot: !!profile.isBot, | ||||
| 		isCat: !!profile.isCat, | ||||
| 		alwaysMarkNsfw: !!profile.alwaysMarkNsfw, | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function changeAvatar(ev) { | ||||
| 	selectFile(ev.currentTarget || ev.target, i18n.locale.avatar).then(async (file) => { | ||||
| 		const i = await os.apiWithDialog('i/update', { | ||||
| 			avatarId: file.id, | ||||
| 		}); | ||||
| 		$i.avatarId = i.avatarId; | ||||
| 		$i.avatarUrl = i.avatarUrl; | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function changeBanner(ev) { | ||||
| 	selectFile(ev.currentTarget || ev.target, i18n.locale.banner).then(async (file) => { | ||||
| 		const i = await os.apiWithDialog('i/update', { | ||||
| 			bannerId: file.id, | ||||
| 		}); | ||||
| 		$i.bannerId = i.bannerId; | ||||
| 		$i.bannerUrl = i.bannerUrl; | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| async function editMetadata() { | ||||
| 	const { canceled, result } = await os.form(i18n.locale._profile.metadata, { | ||||
| 		fieldName0: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataLabel + ' 1', | ||||
| 			default: additionalFields.fieldName0, | ||||
| 		}, | ||||
| 		fieldValue0: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataContent + ' 1', | ||||
| 			default: additionalFields.fieldValue0, | ||||
| 		}, | ||||
| 		fieldName1: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataLabel + ' 2', | ||||
| 			default: additionalFields.fieldName1, | ||||
| 		}, | ||||
| 		fieldValue1: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataContent + ' 2', | ||||
| 			default: additionalFields.fieldValue1, | ||||
| 		}, | ||||
| 		fieldName2: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataLabel + ' 3', | ||||
| 			default: additionalFields.fieldName2, | ||||
| 		}, | ||||
| 		fieldValue2: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataContent + ' 3', | ||||
| 			default: additionalFields.fieldValue2, | ||||
| 		}, | ||||
| 		fieldName3: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataLabel + ' 4', | ||||
| 			default: additionalFields.fieldName3, | ||||
| 		}, | ||||
| 		fieldValue3: { | ||||
| 			type: 'string', | ||||
| 			label: i18n.locale._profile.metadataContent + ' 4', | ||||
| 			default: additionalFields.fieldValue3, | ||||
| 		}, | ||||
| 	}); | ||||
| 	if (canceled) return; | ||||
| 
 | ||||
| 	additionalFields.fieldName0 = result.fieldName0; | ||||
| 	additionalFields.fieldValue0 = result.fieldValue0; | ||||
| 	additionalFields.fieldName1 = result.fieldName1; | ||||
| 	additionalFields.fieldValue1 = result.fieldValue1; | ||||
| 	additionalFields.fieldName2 = result.fieldName2; | ||||
| 	additionalFields.fieldValue2 = result.fieldValue2; | ||||
| 	additionalFields.fieldName3 = result.fieldName3; | ||||
| 	additionalFields.fieldValue3 = result.fieldValue3; | ||||
| 
 | ||||
| 	const fields = [ | ||||
| 		{ name: additionalFields.fieldName0, value: additionalFields.fieldValue0 }, | ||||
| 		{ name: additionalFields.fieldName1, value: additionalFields.fieldValue1 }, | ||||
| 		{ name: additionalFields.fieldName2, value: additionalFields.fieldValue2 }, | ||||
| 		{ name: additionalFields.fieldName3, value: additionalFields.fieldValue3 }, | ||||
| 	]; | ||||
| 
 | ||||
| 	os.api('i/update', { | ||||
| 		fields, | ||||
| 	}).then(i => { | ||||
| 		os.success(); | ||||
| 	}).catch(err => { | ||||
| 		os.alert({ | ||||
| 			type: 'error', | ||||
| 			text: err.id | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| defineExpose({ | ||||
| 	[symbols.PAGE_INFO]: { | ||||
| 		title: i18n.locale.profile, | ||||
| 		icon: 'fas fa-user', | ||||
| 		bg: 'var(--bg)', | ||||
| 	}, | ||||
| 	 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.profile, | ||||
| 				icon: 'fas fa-user', | ||||
| 				bg: 'var(--bg)', | ||||
| 			}, | ||||
| 			host, | ||||
| 			langs, | ||||
| 			name: null, | ||||
| 			description: null, | ||||
| 			birthday: null, | ||||
| 			lang: null, | ||||
| 			location: null, | ||||
| 			fieldName0: null, | ||||
| 			fieldValue0: null, | ||||
| 			fieldName1: null, | ||||
| 			fieldValue1: null, | ||||
| 			fieldName2: null, | ||||
| 			fieldValue2: null, | ||||
| 			fieldName3: null, | ||||
| 			fieldValue3: null, | ||||
| 			avatarId: null, | ||||
| 			bannerId: null, | ||||
| 			isBot: false, | ||||
| 			isCat: false, | ||||
| 			alwaysMarkNsfw: false, | ||||
| 			saving: false, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		this.name = this.$i.name; | ||||
| 		this.description = this.$i.description; | ||||
| 		this.location = this.$i.location; | ||||
| 		this.birthday = this.$i.birthday; | ||||
| 		this.lang = this.$i.lang; | ||||
| 		this.avatarId = this.$i.avatarId; | ||||
| 		this.bannerId = this.$i.bannerId; | ||||
| 		this.isBot = this.$i.isBot; | ||||
| 		this.isCat = this.$i.isCat; | ||||
| 		this.alwaysMarkNsfw = this.$i.alwaysMarkNsfw; | ||||
| 
 | ||||
| 		this.fieldName0 = this.$i.fields[0] ? this.$i.fields[0].name : null; | ||||
| 		this.fieldValue0 = this.$i.fields[0] ? this.$i.fields[0].value : null; | ||||
| 		this.fieldName1 = this.$i.fields[1] ? this.$i.fields[1].name : null; | ||||
| 		this.fieldValue1 = this.$i.fields[1] ? this.$i.fields[1].value : null; | ||||
| 		this.fieldName2 = this.$i.fields[2] ? this.$i.fields[2].name : null; | ||||
| 		this.fieldValue2 = this.$i.fields[2] ? this.$i.fields[2].value : null; | ||||
| 		this.fieldName3 = this.$i.fields[3] ? this.$i.fields[3].name : null; | ||||
| 		this.fieldValue3 = this.$i.fields[3] ? this.$i.fields[3].value : null; | ||||
| 
 | ||||
| 		this.$watch('name', this.save); | ||||
| 		this.$watch('description', this.save); | ||||
| 		this.$watch('location', this.save); | ||||
| 		this.$watch('birthday', this.save); | ||||
| 		this.$watch('lang', this.save); | ||||
| 		this.$watch('isBot', this.save); | ||||
| 		this.$watch('isCat', this.save); | ||||
| 		this.$watch('alwaysMarkNsfw', this.save); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		changeAvatar(e) { | ||||
| 			selectFile(e.currentTarget || e.target, this.$ts.avatar).then(file => { | ||||
| 				os.api('i/update', { | ||||
| 					avatarId: file.id, | ||||
| 				}); | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		changeBanner(e) { | ||||
| 			selectFile(e.currentTarget || e.target, this.$ts.banner).then(file => { | ||||
| 				os.api('i/update', { | ||||
| 					bannerId: file.id, | ||||
| 				}); | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		async editMetadata() { | ||||
| 			const { canceled, result } = await os.form(this.$ts._profile.metadata, { | ||||
| 				fieldName0: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataLabel + ' 1', | ||||
| 					default: this.fieldName0, | ||||
| 				}, | ||||
| 				fieldValue0: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataContent + ' 1', | ||||
| 					default: this.fieldValue0, | ||||
| 				}, | ||||
| 				fieldName1: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataLabel + ' 2', | ||||
| 					default: this.fieldName1, | ||||
| 				}, | ||||
| 				fieldValue1: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataContent + ' 2', | ||||
| 					default: this.fieldValue1, | ||||
| 				}, | ||||
| 				fieldName2: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataLabel + ' 3', | ||||
| 					default: this.fieldName2, | ||||
| 				}, | ||||
| 				fieldValue2: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataContent + ' 3', | ||||
| 					default: this.fieldValue2, | ||||
| 				}, | ||||
| 				fieldName3: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataLabel + ' 4', | ||||
| 					default: this.fieldName3, | ||||
| 				}, | ||||
| 				fieldValue3: { | ||||
| 					type: 'string', | ||||
| 					label: this.$ts._profile.metadataContent + ' 4', | ||||
| 					default: this.fieldValue3, | ||||
| 				}, | ||||
| 			}); | ||||
| 			if (canceled) return; | ||||
| 
 | ||||
| 			this.fieldName0 = result.fieldName0; | ||||
| 			this.fieldValue0 = result.fieldValue0; | ||||
| 			this.fieldName1 = result.fieldName1; | ||||
| 			this.fieldValue1 = result.fieldValue1; | ||||
| 			this.fieldName2 = result.fieldName2; | ||||
| 			this.fieldValue2 = result.fieldValue2; | ||||
| 			this.fieldName3 = result.fieldName3; | ||||
| 			this.fieldValue3 = result.fieldValue3; | ||||
| 
 | ||||
| 			const fields = [ | ||||
| 				{ name: this.fieldName0, value: this.fieldValue0 }, | ||||
| 				{ name: this.fieldName1, value: this.fieldValue1 }, | ||||
| 				{ name: this.fieldName2, value: this.fieldValue2 }, | ||||
| 				{ name: this.fieldName3, value: this.fieldValue3 }, | ||||
| 			]; | ||||
| 
 | ||||
| 			os.api('i/update', { | ||||
| 				fields, | ||||
| 			}).then(i => { | ||||
| 				os.success(); | ||||
| 			}).catch(err => { | ||||
| 				os.alert({ | ||||
| 					type: 'error', | ||||
| 					text: err.id | ||||
| 				}); | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		save() { | ||||
| 			this.saving = true; | ||||
| 
 | ||||
| 			os.apiWithDialog('i/update', { | ||||
| 				name: this.name || null, | ||||
| 				description: this.description || null, | ||||
| 				location: this.location || null, | ||||
| 				birthday: this.birthday || null, | ||||
| 				lang: this.lang || null, | ||||
| 				isBot: !!this.isBot, | ||||
| 				isCat: !!this.isCat, | ||||
| 				alwaysMarkNsfw: !!this.alwaysMarkNsfw, | ||||
| 			}).then(i => { | ||||
| 				this.saving = false; | ||||
| 				this.$i.avatarId = i.avatarId; | ||||
| 				this.$i.avatarUrl = i.avatarUrl; | ||||
| 				this.$i.bannerId = i.bannerId; | ||||
| 				this.$i.bannerUrl = i.bannerUrl; | ||||
| 			}).catch(err => { | ||||
| 				this.saving = false; | ||||
| 			}); | ||||
| 		}, | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import { inject, onUnmounted, Ref } from 'vue'; | ||||
| import { onBeforeRouteLeave } from 'vue-router'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import * as os from '@/os'; | ||||
| 
 | ||||
|  | @ -16,6 +17,17 @@ export function useLeaveGuard(enabled: Ref<boolean>) { | |||
| 
 | ||||
| 			return canceled; | ||||
| 		}); | ||||
| 	} else { | ||||
| 		onBeforeRouteLeave(async (to, from) => { | ||||
| 			if (!enabled.value) return true; | ||||
| 
 | ||||
| 			const { canceled } = await os.confirm({ | ||||
| 				type: 'warning', | ||||
| 				text: i18n.locale.leaveConfirm, | ||||
| 			}); | ||||
| 
 | ||||
| 			return !canceled; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/* | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue