feature/feat-useList-composable #2589
|
@ -9,13 +9,13 @@
|
|||
</BaseButton>
|
||||
<div
|
||||
class="app-container"
|
||||
:class="{'has-background': background || blurHash}"
|
||||
:style="{'background-image': blurHash && `url(${blurHash})`}"
|
||||
:class="{'has-background': backgroundUrl || blurHashUrl}"
|
||||
:style="{'background-image': blurHashUrl ? `url(${blurHashUrl})` : undefined}"
|
||||
>
|
||||
<div
|
||||
:class="{'is-visible': background}"
|
||||
:class="{'is-visible': backgroundUrl}"
|
||||
class="app-container-background background-fade-in d-print-none"
|
||||
:style="{'background-image': background && `url(${background})`}">
|
||||
:style="{'background-image': backgroundUrl ? `url(${backgroundUrl})` : undefined}">
|
||||
</div>
|
||||
<navigation class="d-print-none"/>
|
||||
<main
|
||||
|
@ -73,13 +73,15 @@ import {useLabelStore} from '@/stores/labels'
|
|||
|
||||
import {useRouteWithModal} from '@/composables/useRouteWithModal'
|
||||
import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus'
|
||||
import {useListBackground} from '@/stores/lists'
|
||||
|
||||
const {routeWithModal, currentModal, closeModal} = useRouteWithModal()
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const background = computed(() => baseStore.background)
|
||||
const blurHash = computed(() => baseStore.blurHash)
|
||||
const menuActive = computed(() => baseStore.menuActive)
|
||||
const currentList = computed(() => baseStore.currentList)
|
||||
|
||||
const {backgroundUrl, blurHashUrl} = useListBackground(currentList)
|
||||
|
||||
function showKeyboardShortcuts() {
|
||||
baseStore.setKeyboardShortcutsActive(true)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
:class="[background ? 'has-background' : '', $route.name as string +'-view']"
|
||||
:style="{'background-image': `url(${background})`}"
|
||||
:class="[backgroundUrl ? 'has-background' : '', $route.name as string +'-view']"
|
||||
:style="{'background-image': backgroundUrl ? `url(${backgroundUrl})`: undefined}"
|
||||
class="link-share-container"
|
||||
>
|
||||
<div class="container has-text-centered link-share-view">
|
||||
|
@ -26,14 +26,18 @@
|
|||
import {computed} from 'vue'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useListBackground} from '@/stores/lists'
|
||||
|
||||
import Logo from '@/components/home/Logo.vue'
|
||||
import PoweredByLink from './PoweredByLink.vue'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const currentList = computed(() => baseStore.currentList)
|
||||
const background = computed(() => baseStore.background)
|
||||
const logoVisible = computed(() => baseStore.logoVisible)
|
||||
|
||||
const currentList = computed(() => baseStore.currentList)
|
||||
|
||||
// TODO: use blurhash here aswell
|
||||
const{backgroundUrl} = useListBackground(currentList)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -132,8 +132,6 @@ watch(
|
|||
loadedListId.value = 0
|
||||
const listFromStore = listStore.getListById(listData.id)
|
||||
if (listFromStore !== null) {
|
||||
baseStore.setBackground(null)
|
||||
baseStore.setBlurHash(null)
|
||||
baseStore.handleSetCurrentList({list: listFromStore})
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div
|
||||
class="list-card"
|
||||
:class="{
|
||||
'has-light-text': background !== null,
|
||||
'has-background': blurHashUrl !== '' || background !== null
|
||||
'has-light-text': backgroundUrl !== null,
|
||||
'has-background': blurHashUrl !== '' || backgroundUrl !== null
|
||||
}"
|
||||
:style="{
|
||||
'border-left': list.hexColor ? `0.25rem solid ${list.hexColor}` : undefined,
|
||||
|
@ -12,8 +12,8 @@
|
|||
>
|
||||
<div
|
||||
class="list-background background-fade-in"
|
||||
:class="{'is-visible': background}"
|
||||
:style="{'background-image': background !== null ? `url(${background})` : undefined}"
|
||||
:class="{'is-visible': backgroundUrl}"
|
||||
:style="{'background-image': backgroundUrl !== null ? `url(${backgroundUrl})` : undefined}"
|
||||
/>
|
||||
<span v-if="list.isArchived" class="is-archived" >{{ $t('namespace.archived') }}</span>
|
||||
|
||||
|
@ -45,8 +45,7 @@ import type {IList} from '@/modelTypes/IList'
|
|||
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
import {useListBackground} from './useListBackground'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {useListBackground, useListStore} from '@/stores/lists'
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
|
@ -55,7 +54,7 @@ const props = defineProps({
|
|||
},
|
||||
})
|
||||
|
||||
const {background, blurHashUrl} = useListBackground(toRef(props, 'list'))
|
||||
const {backgroundUrl, blurHashUrl} = useListBackground(toRef(props, 'list'))
|
||||
|
||||
const listStore = useListStore()
|
||||
</script>
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
import {ref, watch, type Ref} from 'vue'
|
||||
import ListService from '@/services/list'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
||||
|
||||
export function useListBackground(list: Ref<IList>) {
|
||||
const background = ref<string | null>(null)
|
||||
const backgroundLoading = ref(false)
|
||||
const blurHashUrl = ref('')
|
||||
|
||||
watch(
|
||||
() => [list.value.id, list.value.backgroundBlurHash] as [IList['id'], IList['backgroundBlurHash']],
|
||||
async ([listId, blurHash], oldValue) => {
|
||||
if (
|
||||
list.value === null ||
|
||||
!list.value.backgroundInformation ||
|
||||
backgroundLoading.value
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const [oldListId, oldBlurHash] = oldValue || []
|
||||
if (
|
||||
oldValue !== undefined &&
|
||||
listId === oldListId && blurHash === oldBlurHash
|
||||
) {
|
||||
// list hasn't changed
|
||||
return
|
||||
}
|
||||
|
||||
backgroundLoading.value = true
|
||||
|
||||
try {
|
||||
const blurHashPromise = getBlobFromBlurHash(blurHash).then((blurHash) => {
|
||||
blurHashUrl.value = blurHash ? window.URL.createObjectURL(blurHash) : ''
|
||||
})
|
||||
|
||||
const listService = new ListService()
|
||||
const backgroundPromise = listService.background(list.value).then((result) => {
|
||||
background.value = result
|
||||
})
|
||||
await Promise.all([blurHashPromise, backgroundPromise])
|
||||
} finally {
|
||||
backgroundLoading.value = false
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
return {
|
||||
background,
|
||||
blurHashUrl,
|
||||
backgroundLoading,
|
||||
}
|
||||
}
|
|
@ -29,3 +29,14 @@ export async function getBlobFromBlurHash(blurHash: string): Promise<Blob | null
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function getBlurHash(blurHashString: string) {
|
||||
if (!blurHashString) {
|
||||
return
|
||||
}
|
||||
const blurHashBlob = await getBlobFromBlurHash(blurHashString)
|
||||
if (!blurHashBlob) {
|
||||
return
|
||||
}
|
||||
return URL.createObjectURL(blurHashBlob)
|
||||
}
|
|
@ -6,7 +6,6 @@ import TaskService from '@/services/task'
|
|||
import ListModel from '@/models/list'
|
||||
|
||||
import {colorFromHex} from '@/helpers/color/colorFromHex'
|
||||
import {getBlobFromBlurHash} from '@/helpers/getBlobFromBlurHash'
|
||||
|
||||
export default class ListService extends AbstractService<IList> {
|
||||
constructor() {
|
||||
|
@ -43,18 +42,6 @@ export default class ListService extends AbstractService<IList> {
|
|||
return list
|
||||
}
|
||||
|
||||
// FIXME: move out of service
|
||||
async getBlurHash(blurHashString: IList['backgroundBlurHash']) {
|
||||
if (!blurHashString) {
|
||||
return
|
||||
}
|
||||
const blurHashBlob = await getBlobFromBlurHash(blurHashString)
|
||||
if (!blurHashBlob) {
|
||||
return
|
||||
}
|
||||
return URL.createObjectURL(blurHashBlob)
|
||||
}
|
||||
|
||||
async loadBackground(list: Pick<IList, 'id' | 'backgroundInformation'>) {
|
||||
if (list === null || !list.backgroundInformation) {
|
||||
return
|
||||
|
|
|
@ -2,7 +2,6 @@ import { readonly, ref} from 'vue'
|
|||
import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
import ListService from '@/services/list'
|
||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||
|
||||
import {useMenuActive} from '@/composables/useMenuActive'
|
||||
|
@ -19,8 +18,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||
id: 0,
|
||||
isArchived: false,
|
||||
}))
|
||||
const background = ref('')
|
||||
const blurHash = ref('')
|
||||
|
||||
const hasTasks = ref(false)
|
||||
const keyboardShortcutsActive = ref(false)
|
||||
|
@ -60,14 +57,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||
quickActionsActive.value = value
|
||||
}
|
||||
|
||||
function setBackground(newBackground: string) {
|
||||
background.value = newBackground
|
||||
}
|
||||
|
||||
function setBlurHash(newBlurHash: string) {
|
||||
blurHash.value = newBlurHash
|
||||
}
|
||||
|
||||
function setLogoVisible(visible: boolean) {
|
||||
logoVisible.value = visible
|
||||
}
|
||||
|
@ -76,53 +65,14 @@ export const useBaseStore = defineStore('base', () => {
|
|||
ready.value = value
|
||||
}
|
||||
|
||||
async function handleSetCurrentList(
|
||||
{list, forceUpdate = false}: {list: IList | null, forceUpdate?: boolean},
|
||||
function handleSetCurrentList(
|
||||
{list}: {list: IList | null},
|
||||
) {
|
||||
if (list === null) {
|
||||
setCurrentList({})
|
||||
setBackground('')
|
||||
setBlurHash('')
|
||||
return
|
||||
}
|
||||
|
||||
// The forceUpdate parameter is used only when updating a list background directly because in that case
|
||||
// the current list stays the same, but we want to show the new background right away.
|
||||
if (
|
||||
(list.id !== currentList.value?.id || forceUpdate) &&
|
||||
list.backgroundInformation
|
||||
) {
|
||||
try {
|
||||
const listService = new ListService()
|
||||
const blurHashPromise = listService.getBlurHash(list.backgroundBlurHash).then(blurHash => {
|
||||
if (blurHash) {
|
||||
setBlurHash(blurHash)
|
||||
}
|
||||
})
|
||||
const backgroundPromise = listService.loadBackground(list).then(background => {
|
||||
if (background === undefined) {
|
||||
throw new Error()
|
||||
}
|
||||
setBackground(background)
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
blurHashPromise,
|
||||
backgroundPromise,
|
||||
])
|
||||
} catch (e) {
|
||||
console.error('Error getting background image for list', list.id, e)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
typeof list.backgroundInformation === 'undefined' ||
|
||||
list.backgroundInformation === null
|
||||
) {
|
||||
setBackground('')
|
||||
setBlurHash('')
|
||||
}
|
||||
|
||||
setCurrentList(list)
|
||||
}
|
||||
|
||||
|
@ -137,8 +87,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||
loading: readonly(loading),
|
||||
ready: readonly(ready),
|
||||
currentList: readonly(currentList),
|
||||
|
||||
background: readonly(background),
|
||||
blurHash: readonly(blurHash),
|
||||
hasTasks: readonly(hasTasks),
|
||||
keyboardShortcutsActive: readonly(keyboardShortcutsActive),
|
||||
quickActionsActive: readonly(quickActionsActive),
|
||||
|
@ -150,8 +98,6 @@ export const useBaseStore = defineStore('base', () => {
|
|||
setHasTasks,
|
||||
setKeyboardShortcutsActive,
|
||||
setQuickActionsActive,
|
||||
setBackground,
|
||||
setBlurHash,
|
||||
setLogoVisible,
|
||||
|
||||
handleSetCurrentList,
|
||||
|
|
|
@ -25,8 +25,9 @@ import {useNamespaceStore} from './namespaces'
|
|||
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {success} from '@/message'
|
||||
import { i18n } from '@/i18n'
|
||||
import {i18n} from '@/i18n'
|
||||
import BackgroundUploadService from '@/services/backgroundUpload'
|
||||
import {getBlurHash} from '@/helpers/blurhash'
|
||||
|
||||
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
|
||||
|
||||
|
@ -228,7 +229,7 @@ export const useListStore = defineStore('list', () => {
|
|||
id: backgroundId,
|
||||
listId,
|
||||
dpschen marked this conversation as resolved
Outdated
dpschen
commented
fix: type should be returned by update. fix: type should be returned by update.
dpschen
commented
Fixed Fixed
|
||||
})
|
||||
await baseStore.handleSetCurrentList({list, forceUpdate: true})
|
||||
baseStore.handleSetCurrentList({list})
|
||||
namespaceStore.setListInNamespaceById(list)
|
||||
setList(list)
|
||||
success({message: i18n.global.t('list.background.success')})
|
||||
|
@ -243,7 +244,7 @@ export const useListStore = defineStore('list', () => {
|
|||
|
||||
const list = await backgroundUploadService.create(listId, file)
|
||||
|
||||
await baseStore.handleSetCurrentList({list, forceUpdate: true})
|
||||
baseStore.handleSetCurrentList({list})
|
||||
namespaceStore.setListInNamespaceById(list)
|
||||
setList(list)
|
||||
success({message: i18n.global.t('list.background.success')})
|
||||
|
@ -256,32 +257,37 @@ export const useListStore = defineStore('list', () => {
|
|||
return
|
||||
}
|
||||
const list = await listService.removeBackground(listWithBackground)
|
||||
await baseStore.handleSetCurrentList({list, forceUpdate: true})
|
||||
baseStore.handleSetCurrentList({list})
|
||||
namespaceStore.setListInNamespaceById(list)
|
||||
setList(list)
|
||||
success({message: i18n.global.t('list.background.removeSuccess')})
|
||||
router.back()
|
||||
}
|
||||
|
||||
|
||||
async function loadListBackground(list: IList) {
|
||||
const result = {
|
||||
blurHash: '',
|
||||
background: '',
|
||||
async function loadListBackground(
|
||||
list: IList,
|
||||
blurhashSetter: (blurhash: string) => void,
|
||||
backgroundSetter: (background: string) => void,
|
||||
) {
|
||||
if (
|
||||
list === null ||
|
||||
!list.backgroundInformation
|
||||
) {
|
||||
blurhashSetter('')
|
||||
backgroundSetter('')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const listService = new ListService()
|
||||
const blurHashPromise = listService.getBlurHash(list.backgroundBlurHash).then(blurHash => {
|
||||
if (blurHash) {
|
||||
result.blurHash = blurHash
|
||||
}
|
||||
const blurHashPromise = getBlurHash(list.backgroundBlurHash).then(blurHash => {
|
||||
blurhashSetter(blurHash || '')
|
||||
})
|
||||
const backgroundPromise = listService.loadBackground(list).then(background => {
|
||||
if (background === undefined) {
|
||||
throw new Error()
|
||||
}
|
||||
result.background = background
|
||||
backgroundSetter(background)
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
|
@ -291,8 +297,6 @@ export const useListStore = defineStore('list', () => {
|
|||
} catch (e) {
|
||||
console.error('Error getting background image for list', list.id, e)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -405,7 +409,7 @@ export function useList(listId?: MaybeRef<IList['id']>) {
|
|||
async function saveList() {
|
||||
await listStore.updateList(list.value)
|
||||
success({message: t('list.edit.success')})
|
||||
await baseStore.handleSetCurrentList({list: list.value})
|
||||
baseStore.handleSetCurrentList({list: list.value})
|
||||
router.back()
|
||||
}
|
||||
|
||||
|
@ -421,7 +425,7 @@ export function useList(listId?: MaybeRef<IList['id']>) {
|
|||
|
||||
async function removeListBackground() {
|
||||
list.value = await listService.removeBackground(list.value)
|
||||
await useBaseStore().handleSetCurrentList({list: list.value, forceUpdate: true})
|
||||
useBaseStore().handleSetCurrentList({list: list.value})
|
||||
namespaceStore.setListInNamespaceById(list.value)
|
||||
listStore.setList(list.value)
|
||||
success({message: t('list.background.removeSuccess')})
|
||||
|
@ -440,33 +444,50 @@ export function useList(listId?: MaybeRef<IList['id']>) {
|
|||
}
|
||||
}
|
||||
|
||||
export function useListBackground(listId?: MaybeRef<IList['id']>) {
|
||||
const {
|
||||
isLoading,
|
||||
list,
|
||||
currentListId,
|
||||
} = useListBase(listId)
|
||||
|
||||
const blurHash = ref<string>()
|
||||
const background = ref<string>()
|
||||
|
||||
export function useListBackground(list: MaybeRef<IList>) {
|
||||
const listStore = useListStore()
|
||||
|
||||
const listVal = computed(() => unref(list))
|
||||
const backgroundUrl = ref<string | null>(null)
|
||||
const backgroundLoading = ref(false)
|
||||
const blurHashUrl = ref('')
|
||||
|
||||
watch(
|
||||
currentListId,
|
||||
async (id) => {
|
||||
if (id === undefined || isLoading) {
|
||||
() => [listVal.value.id, listVal.value.backgroundBlurHash] as [IList['id'], IList['backgroundBlurHash']],
|
||||
async ([listId, blurHash], oldValue) => {
|
||||
if (backgroundLoading.value) {
|
||||
return
|
||||
}
|
||||
dpschen
commented
I copied this from the old code, but I think that we shouldn't return in that case I copied this from the old code, but I think that we shouldn't return in that case
|
||||
const result = await listStore.loadListBackground(list.value)
|
||||
blurHash.value = result.blurHash
|
||||
background.value = result.background
|
||||
|
||||
const [oldListId, oldBlurHash] = oldValue || []
|
||||
if (
|
||||
oldValue !== undefined &&
|
||||
listId === oldListId && blurHash === oldBlurHash
|
||||
) {
|
||||
// list hasn't changed
|
||||
return
|
||||
}
|
||||
|
||||
backgroundLoading.value = true
|
||||
|
||||
await listStore.loadListBackground(
|
||||
listVal.value,
|
||||
(value) => {
|
||||
blurHashUrl.value = value
|
||||
},
|
||||
(value) => {
|
||||
dpschen
commented
if the list or background has changed in between we shouldn't set this. if the list or background has changed in between we shouldn't set this.
konrad
commented
When could that be the case? When could that be the case?
dpschen
commented
If you click on one list that has a background and then on another that has none. The promise would still finish and then set the (wrong) background. If you click on one list that has a background and then on another that has none. The promise would still finish and then set the (wrong) background.
konrad
commented
Makes sense! Makes sense!
|
||||
backgroundUrl.value = value
|
||||
},
|
||||
)
|
||||
|
||||
backgroundLoading.value = false
|
||||
},
|
||||
{immediate: true},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
return {
|
||||
blurHash,
|
||||
background,
|
||||
backgroundUrl,
|
||||
blurHashUrl,
|
||||
backgroundLoading,
|
||||
}
|
||||
}
|
Reference in New Issue
I might need to readd this. I didn't realize that the info if a background is loaded is necessary.