From 5180cc060fbfc96122c1848c0d4a867498640a1c Mon Sep 17 00:00:00 2001 From: Daniel Kesselberg Date: Tue, 14 Oct 2025 19:08:55 +0200 Subject: [PATCH 1/2] fix: avoid fetching the user's addressbooks per component instance Signed-off-by: Daniel Kesselberg --- src/oca.ts | 3 +- src/store/addressbooks.js | 4 +-- src/store/readOnlyContactDetails.ts | 44 ++++++++++++++++++++++++++++ src/views/ReadOnlyContactDetails.vue | 9 +++--- 4 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/store/readOnlyContactDetails.ts diff --git a/src/oca.ts b/src/oca.ts index 3726ffd58..fa696b6d9 100644 --- a/src/oca.ts +++ b/src/oca.ts @@ -15,6 +15,8 @@ import './css/contacts.scss' // Dialogs css import '@nextcloud/dialogs/style.css' +const pinia = createPinia() + declare global { interface Window { OCA: { @@ -42,7 +44,6 @@ window.OCA.Contacts = { contactEmailAddress, }) - const pinia = createPinia() app.use(pinia) app.use(store) diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js index b84437f4d..06a4ce6f7 100644 --- a/src/store/addressbooks.js +++ b/src/store/addressbooks.js @@ -252,6 +252,8 @@ const actions = { return context.getters.getAddressbooks } + context.state.addressbooksFetched = true + const addressbooks = await client.addressBookHomes[0] .findAllAddressBooks() .then((addressbooks) => { @@ -267,8 +269,6 @@ const actions = { context.commit('resortAddressbooks') - context.state.addressbooksFetched = true - return addressbooks }, diff --git a/src/store/readOnlyContactDetails.ts b/src/store/readOnlyContactDetails.ts new file mode 100644 index 000000000..e9df925d8 --- /dev/null +++ b/src/store/readOnlyContactDetails.ts @@ -0,0 +1,44 @@ +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { defineStore } from 'pinia' +import client from '../services/cdav.js' +import store from './index.js' +import usePrincipalsStore from './principals.js' + +export default defineStore('readOnlyContactDetails', { + state: () => ({ + promise: null, + fetched: false, + }), + + actions: { + async init() { + if (this.fetched) { + return Promise.resolve() + } + + if (this.promise) { + return this.promise + } + + this.promise = (async () => { + await client.connect({ enableCardDAV: true }) + const principalsStore = usePrincipalsStore() + principalsStore.setCurrentUserPrincipal(client) + await store.dispatch('getAddressbooks') + })() + + try { + await this.promise + this.fetched = true + } finally { + this.promise = null + } + + return this.promise + }, + }, +}) diff --git a/src/views/ReadOnlyContactDetails.vue b/src/views/ReadOnlyContactDetails.vue index fd81e8f7b..3de0c73ac 100644 --- a/src/views/ReadOnlyContactDetails.vue +++ b/src/views/ReadOnlyContactDetails.vue @@ -61,6 +61,7 @@ import rfcProps from '../models/rfcProps.js' import client from '../services/cdav.js' import validate from '../services/validate.js' import usePrincipalsStore from '../store/principals.js' +import useReadOnlyContactDetailsStore from '../store/readOnlyContactDetails.ts' const { profileEnabled } = loadState('user_status', 'profileEnabled', false) @@ -211,11 +212,9 @@ export default { }, async beforeMount() { - // Init client and stores - await client.connect({ enableCardDAV: true }) - const principalsStore = usePrincipalsStore() - principalsStore.setCurrentUserPrincipal(client) - await this.$store.dispatch('getAddressbooks') + // Init store + const store = useReadOnlyContactDetailsStore() + await store.init() // Fetch contact await this.fetchContact() From 7bbe9697f30406f08d22de6b114f1a423a2dd1a1 Mon Sep 17 00:00:00 2001 From: Daniel Kesselberg Date: Tue, 14 Oct 2025 19:42:56 +0200 Subject: [PATCH 2/2] fixup! fix: avoid fetching the user's addressbooks per component instance --- src/store/addressbooks.js | 4 ++-- src/views/ReadOnlyContactDetails.vue | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js index 06a4ce6f7..b84437f4d 100644 --- a/src/store/addressbooks.js +++ b/src/store/addressbooks.js @@ -252,8 +252,6 @@ const actions = { return context.getters.getAddressbooks } - context.state.addressbooksFetched = true - const addressbooks = await client.addressBookHomes[0] .findAllAddressBooks() .then((addressbooks) => { @@ -269,6 +267,8 @@ const actions = { context.commit('resortAddressbooks') + context.state.addressbooksFetched = true + return addressbooks }, diff --git a/src/views/ReadOnlyContactDetails.vue b/src/views/ReadOnlyContactDetails.vue index 3de0c73ac..b15dcd1e7 100644 --- a/src/views/ReadOnlyContactDetails.vue +++ b/src/views/ReadOnlyContactDetails.vue @@ -58,9 +58,7 @@ import ContactDetailsProperty from '../components/ContactDetails/ContactDetailsP import IsMobileMixin from '../mixins/IsMobileMixin.ts' import Contact from '../models/contact.js' import rfcProps from '../models/rfcProps.js' -import client from '../services/cdav.js' import validate from '../services/validate.js' -import usePrincipalsStore from '../store/principals.js' import useReadOnlyContactDetailsStore from '../store/readOnlyContactDetails.ts' const { profileEnabled } = loadState('user_status', 'profileEnabled', false)