diff --git a/dashboard/src/components/ImagePicker.vue b/dashboard/src/components/ImagePicker.vue index 230c82ed2..860ac2965 100644 --- a/dashboard/src/components/ImagePicker.vue +++ b/dashboard/src/components/ImagePicker.vue @@ -35,6 +35,7 @@ defineExpose({ reset }); watchEffect(() => { internalSrc.value = props.src; + isChanged.value = false; }); function dataURLtoFile(dataURL, filename) { diff --git a/dashboard/src/components/app/Display.vue b/dashboard/src/components/app/Display.vue index 540d7c7c1..7fe87e361 100644 --- a/dashboard/src/components/app/Display.vue +++ b/dashboard/src/components/app/Display.vue @@ -20,8 +20,13 @@ const label = ref(''); const tags = ref([]); const iconUrl = ref(''); +let iconFile = 'src'; +function onIconChanged(file) { + iconFile = file; +} + const haveValuesChanged = computed(() => { - return (label.value !== props.app.label) || tags.value.join() !== props.app.tags.join(); + return (label.value !== props.app.label) || (tags.value.join() !== props.app.tags.join()) || (iconFile !== 'src'); }); async function onSubmit() { @@ -30,6 +35,25 @@ async function onSubmit() { tagsError.value = ''; iconError.value = ''; + if (iconFile !== 'src') { + if (iconFile === 'fallback') { // user reset the icon + const [error] = await appsModel.configure(props.app.id, 'icon', { icon: '' }); + if (error) { + iconError.value = error.body ? error.body.message : 'Internal error'; + return error; + } + } else { // user loaded custom icon + const tmp = (await getDataURLFromFile(iconFile)).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; + } + } + iconUrl.value = `${API_ORIGIN}/api/v1/apps/${props.app.id}/icon?ts=${Date.now()}`; // will also reset the ImagePicker + iconFile = 'src'; + } + if (label.value !== props.app.label) { const [error] = await appsModel.configure(props.app.id, 'label', { label: label.value }); if (error) { @@ -51,28 +75,11 @@ async function onSubmit() { busy.value = false; } -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(() => { label.value = props.app.label; tags.value = props.app.tags; + // iconUrl is the appstore icon or user icon. there is no way to differentiate. when null (custom apps), neither is set. + // the delete button in the icon can be used to unset user icon and use the appstore icon. unfortunately, it will also appear for the appstore icon iconUrl.value = props.app.iconUrl; }); @@ -82,7 +89,7 @@ onMounted(() => {
- +