feature/feat-useList-composable #2589

Closed
dpschen wants to merge 7 commits from dpschen/frontend:feature/feat-useList-composable into main
9 changed files with 94 additions and 181 deletions
Showing only changes of commit a96c64c74a - Show all commits

View File

@ -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)

View File

@ -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>

View File

@ -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})
}

View File

@ -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>

View File

@ -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,
}
}

View File

@ -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)
}

View File

@ -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

View File

@ -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),

I might need to readd this. I didn't realize that the info if a background is loaded is necessary.

I might need to readd this. I didn't realize that the info _if_ a background is loaded is necessary.
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,

View File

@ -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

fix: type should be returned by update.

fix: type should be returned by update.

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
}

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) => {

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.

When could that be the case?

When could that be the case?

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.

Makes sense!

Makes sense!
backgroundUrl.value = value
},
)
backgroundLoading.value = false
},
{immediate: true},
{ immediate: true },
)
return {
blurHash,
background,
backgroundUrl,
blurHashUrl,
backgroundLoading,
}
}