From 3f39fde8276cb659dd63670c26dcc99b40298528 Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Wed, 30 Oct 2024 02:58:22 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=8C=E6=B6=88=E3=81=88=E3=82=8B=E3=81=93=E3=81=A8?= =?UTF-8?q?=E3=81=8C=E3=81=82=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/messageInputState/useMessageInputState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/composables/messageInputState/useMessageInputState.ts b/src/composables/messageInputState/useMessageInputState.ts index f88b501d60..32fc72518b 100644 --- a/src/composables/messageInputState/useMessageInputState.ts +++ b/src/composables/messageInputState/useMessageInputState.ts @@ -32,7 +32,7 @@ const useMessageInputState = (channelId: MessageInputStateKey) => { v => { setStore(channelId, v) }, - { deep: true } + { deep: true, immediate: true } ) const isTextEmpty = computed(() => state.text === '') From 69f14340e1cb4290319a37d02de6d82b214665df Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Wed, 30 Oct 2024 21:44:56 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E4=B8=8B=E6=9B=B8=E3=81=8D=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E3=82=92=E7=94=BB=E9=9D=A2=E3=82=92=E9=96=89=E3=81=98?= =?UTF-8?q?=E3=81=A6=E3=82=82=E4=BF=9D=E6=8C=81=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/utils/useIndexedDbValue.ts | 3 +- src/lib/basic/reactive.ts | 8 +++++- src/store/ui/messageInputStateStore.ts | 33 +++++++++++++++++----- src/views/MainPage.vue | 16 ----------- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/composables/utils/useIndexedDbValue.ts b/src/composables/utils/useIndexedDbValue.ts index 6dc8c06774..c69b1b8a19 100644 --- a/src/composables/utils/useIndexedDbValue.ts +++ b/src/composables/utils/useIndexedDbValue.ts @@ -37,9 +37,8 @@ const useIndexedDbValue = ( watch( value, - async () => { + async v => { if (restoring.value) return - // indexedDBにはproxyされたobjectは入らないのでtoRawする await set(key, toRawDeep(value), store) }, diff --git a/src/lib/basic/reactive.ts b/src/lib/basic/reactive.ts index 1700dc8688..493ab905cf 100644 --- a/src/lib/basic/reactive.ts +++ b/src/lib/basic/reactive.ts @@ -14,7 +14,11 @@ export const toRawDeep = (value: any, map = new WeakMap()) => { return map.get(value) } - if (!Array.isArray(value) && !isPlainObject(value)) { + if ( + !Array.isArray(value) && + !isPlainObject(value) && + !(value instanceof Map) + ) { return value } @@ -25,6 +29,8 @@ export const toRawDeep = (value: any, map = new WeakMap()) => { for (let i = 0; i < newValue.length; i++) { newValue[i] = toRawDeep(newValue[i], map) } + } else if (newValue instanceof Map) { + newValue.forEach((v, k) => newValue.set(k, toRawDeep(v, map))) } else { for (const k of Object.keys(newValue)) { newValue[k] = toRawDeep(newValue[k], map) diff --git a/src/store/ui/messageInputStateStore.ts b/src/store/ui/messageInputStateStore.ts index 6d7ca633db..2d474d6412 100644 --- a/src/store/ui/messageInputStateStore.ts +++ b/src/store/ui/messageInputStateStore.ts @@ -1,9 +1,11 @@ import { defineStore, acceptHMRUpdate } from 'pinia' import type { Ref } from 'vue' -import { reactive, computed, unref } from 'vue' +import { computed, unref, toRef } from 'vue' import type { AttachmentType } from '/@/lib/basic/file' import { convertToRefsStore } from '/@/store/utils/convertToRefsStore' import type { ChannelId } from '/@/types/entity-ids' +import useIndexedDbValue, { key } from '/@/composables/utils/useIndexedDbValue' +import { promisifyRequest } from 'idb-keyval' /** * 基本的に直接利用しないで`/@/composables/messageInputState`を利用する @@ -36,24 +38,41 @@ export const createDefaultValue = () => ({ text: '', attachments: [] }) const useMessageInputStateStorePinia = defineStore( 'ui/messageInputStateStore', () => { - const states = reactive( - new Map() + const initialValue = { + messageInputState: new Map< + ChannelId | VirtualChannelId, + MessageInputState + >() + } + + const [state, restoring, restoringPromise] = useIndexedDbValue( + 'store/ui/messageInputStateStore', + 1, + { + 1: async getStore => { + const store = getStore() + const setReq = store.put(initialValue, key) + await promisifyRequest(setReq) + } + }, + initialValue ) + const states = toRef(() => state.messageInputState) const inputChannels = computed(() => - [...states].filter(([id]) => !virtualIds.has(id)) + [...states.value].filter(([id]) => !virtualIds.has(id)) ) const hasInputChannel = computed(() => inputChannels.value.length > 0) - const getStore = (cId: MessageInputStateKey) => states.get(unref(cId)) + const getStore = (cId: MessageInputStateKey) => states.value.get(unref(cId)) const setStore = (cId: MessageInputStateKey, v: MessageInputState) => { // 空のときは削除、空でないときはセット if (v && (v.text !== '' || v.attachments.length > 0)) { // コピーしないと参照が変わらないから上書きされる // toRawしちゃうとreactiveで包めなくなるので、そうはしない - states.set(unref(cId), { ...v }) + states.value.set(unref(cId), { ...v }) } else { - states.delete(unref(cId)) + states.value.delete(unref(cId)) } } diff --git a/src/views/MainPage.vue b/src/views/MainPage.vue index ec8265c191..897f2488b5 100644 --- a/src/views/MainPage.vue +++ b/src/views/MainPage.vue @@ -57,7 +57,6 @@ import useMainViewLayout from './composables/useMainViewLayout' import useRouteWatcher from './composables/useRouteWatcher' import useInitialFetch from './composables/useInitialFetch' import { useToastStore } from '/@/store/ui/toast' -import { useMessageInputStateStore } from '/@/store/ui/messageInputStateStore' import { useCommandPalette } from '/@/store/app/commandPalette' const useStyles = ( @@ -73,19 +72,6 @@ const useStyles = ( })) }) -const useDraftConfirmer = () => { - const { hasInputChannel } = useMessageInputStateStore() - window.addEventListener('beforeunload', event => { - if (hasInputChannel.value) { - const unloadMessage = - 'このまま終了すると下書きが削除されます。本当に終了しますか?' - event.preventDefault() - event.returnValue = unloadMessage - return unloadMessage - } - }) -} - const useCommandPaletteShortcutKey = () => { const { mode, openCommandPalette, closeCommandPalette } = useCommandPalette() @@ -163,8 +149,6 @@ const hideOuter = computed( () => isMobile.value && isNavCompletelyAppeared.value ) -useDraftConfirmer() - const { routeWatcherState, triggerRouteParamChange } = useRouteWatcher() useInitialFetch(() => { connectFirebase(onClick => { From 552b74342b2a9660d6c0895421ba5aaa68ca27a0 Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Mon, 4 Nov 2024 14:00:54 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E8=A8=98?= =?UTF-8?q?=E8=BF=B0=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/utils/useIndexedDbValue.ts | 2 +- src/store/app/rtcSettings.ts | 2 +- src/store/domain/me.ts | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/composables/utils/useIndexedDbValue.ts b/src/composables/utils/useIndexedDbValue.ts index c69b1b8a19..22441ac8ea 100644 --- a/src/composables/utils/useIndexedDbValue.ts +++ b/src/composables/utils/useIndexedDbValue.ts @@ -37,7 +37,7 @@ const useIndexedDbValue = ( watch( value, - async v => { + async () => { if (restoring.value) return // indexedDBにはproxyされたobjectは入らないのでtoRawする await set(key, toRawDeep(value), store) diff --git a/src/store/app/rtcSettings.ts b/src/store/app/rtcSettings.ts index ced6a3227d..5f4bc6134f 100644 --- a/src/store/app/rtcSettings.ts +++ b/src/store/app/rtcSettings.ts @@ -38,7 +38,7 @@ const useRtcSettingsPinia = defineStore('app/rtcSettings', () => { isMute: false } - const [state, restoring, restoringPromise] = useIndexedDbValue( + const [state] = useIndexedDbValue( 'store/app/rtcSettings', 3, { diff --git a/src/store/domain/me.ts b/src/store/domain/me.ts index 447a4dd367..2e110056ec 100644 --- a/src/store/domain/me.ts +++ b/src/store/domain/me.ts @@ -18,12 +18,7 @@ const useMeStorePinia = defineStore('domain/me', () => { } // TODO: ログインチェック時にrestoreを待つ必要があるかもしれない - const [state, restoring, restoringPromise] = useIndexedDbValue( - 'store/domain/me', - 1, - {}, - initialValue - ) + const [state] = useIndexedDbValue('store/domain/me', 1, {}, initialValue) const myId = computed(() => state.detail?.id)