Rework the ImagePicker component

This commit is contained in:
Johannes Zellner
2025-05-20 14:48:18 +02:00
parent 4615418000
commit d955f0e3d8
4 changed files with 120 additions and 95 deletions
+24 -32
View File
@@ -4,6 +4,7 @@ import { ref, onMounted, useTemplateRef } from 'vue';
import { FormGroup, TextInput, Button, TagInput } from 'pankow';
import ImagePicker from '../ImagePicker.vue';
import AppsModel from '../../models/AppsModel.js';
import { API_ORIGIN } from '../../constants.js';
const props = defineProps([ 'app' ]);
@@ -18,12 +19,6 @@ const label = ref('');
const tags = ref([]);
const iconUrl = ref('');
let newIcon = null;
function onIconChanged(file) {
newIcon = file;
}
function getDataURLFromFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
@@ -64,28 +59,26 @@ async function onSubmit() {
}
}
if (newIcon) {
let tmp;
if (newIcon === 'clear') {
tmp = '';
} else {
tmp = (await getDataURLFromFile(newIcon)).replace(/^data:image\/[a-z]+;base64,/, '');
}
const [error] = await appsModel.configure(props.app.id, 'icon', { icon: tmp });
if (error) {
iconError.value = error.body ? error.body.message : 'Internal error';
busy.value = false;
return console.error(error);
}
}
busy.value = false;
}
function onClearIcon() {
imagePicker.value.clear(`${iconUrl.value}&original=true`);
newIcon = 'clear';
async function onIconSubmit(icon) {
const tmp = (await getDataURLFromFile(icon)).replace(/^data:image\/[a-z]+;base64,/, '');
const [error] = await appsModel.configure(props.app.id, 'icon', { icon: tmp });
if (error) {
iconError.value = error.body ? error.body.message : 'Internal error';
return error;
}
}
async function onIconUnset() {
const [error] = await appsModel.configure(props.app.id, 'icon', { icon: '' });
if (error) {
iconError.value = error.body ? error.body.message : 'Internal error';
return error;
}
iconUrl.value = props.app.iconUrl ? `${API_ORIGIN}/api/v1/apps/${props.app.id}/icon?ts=${Date.now()}` : `${API_ORIGIN}/img/appicon_fallback.png`; // calculate full icon url with cache busting
}
onMounted(() => {
@@ -98,6 +91,11 @@ onMounted(() => {
<template>
<div>
<div style="display: inline-block;">
<label>{{ $t('app.display.icon') }}</label>
<ImagePicker ref="imagePicker" :src="iconUrl" fallback-src="/img/appicon_fallback.png" :save-handler="onIconSubmit" :unset-handler="onIconUnset" :size="512" display-height="128px"/>
</div>
<form @submit.prevent="onSubmit()" autocomplete="off">
<fieldset :disabled="busy">
<input type="submit" style="display: none;"/>
@@ -114,14 +112,8 @@ onMounted(() => {
<div class="text-error" v-if="tagsError">{{ tagsError }}</div>
</FormGroup>
<FormGroup>
<label>{{ $t('app.display.icon') }}</label>
<ImagePicker ref="imagePicker" :src="iconUrl" fallback-src="/img/appicon_fallback.png" @changed="onIconChanged" :size="512" display-height="128px"/>
<div class="actionable" @click="onClearIcon()">{{ $t('app.display.iconResetAction') }}</div>
</FormGroup>
<Button @click="onSubmit()" :loading="busy" :disabled="busy">{{ $t('app.display.saveAction') }}</Button>
</fieldset>
</form>
<br/>
<Button @click="onSubmit()" :loading="busy" :disabled="busy">{{ $t('app.display.saveAction') }}</Button>
</div>
</template>