commit: b6f1178ea3936a9cc6dea7af24f8be8822ba8b6a
parent 98bbb4eeef0364b42a9ac626eddc0bf7081fa3b5
Author: tusooa <tusooa@kazv.moe>
Date: Fri, 10 Mar 2023 21:37:03 -0500
Save drafts permanently in local storage
Diffstat:
7 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
@@ -362,6 +362,8 @@ const afterStoreSetup = async ({ store, i18n }) => {
getInstanceConfig({ store })
])
+ await store.dispatch('loadDrafts')
+
// Start fetching things that don't need to block the UI
store.dispatch('fetchMutes')
store.dispatch('startFetchingAnnouncements')
diff --git a/src/components/draft/draft.vue b/src/components/draft/draft.vue
@@ -31,12 +31,12 @@
class="faint-link"
:to="{ name: 'conversation', params: { id: draft.refId } }"
>
- {{ refStatus.external_url }}
+ {{ refStatus ? refStatus.external_url : $t('drafts.unavailable') }}
</router-link>
</template>
</i18n-t>
<StatusContent
- v-if="draft.refId"
+ v-if="draft.refId && refStatus"
class="status-content"
:status="refStatus"
:compact="true"
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -1412,6 +1412,7 @@
"abandon_confirm_accept_button": "Abandon",
"abandon_confirm_cancel_button": "Keep",
"replying": "Replying to {statusLink}",
- "editing": "Editing {statusLink}"
+ "editing": "Editing {statusLink}",
+ "unavailable": "(unavailable)"
}
}
diff --git a/src/lib/persisted_state.js b/src/lib/persisted_state.js
@@ -1,6 +1,6 @@
import merge from 'lodash.merge'
-import localforage from 'localforage'
import { each, get, set, cloneDeep } from 'lodash'
+import { storage } from './storage.js'
let loaded = false
@@ -26,7 +26,7 @@ const saveImmedeatelyActions = [
]
const defaultStorage = (() => {
- return localforage
+ return storage
})()
export default function createPersistedState ({
diff --git a/src/lib/storage.js b/src/lib/storage.js
@@ -0,0 +1,3 @@
+import localforage from 'localforage'
+
+export const storage = localforage
diff --git a/src/modules/drafts.js b/src/modules/drafts.js
@@ -1,3 +1,4 @@
+import { storage } from 'src/lib/storage.js'
export const defaultState = {
drafts: {}
@@ -9,17 +10,55 @@ export const mutations = {
},
abandonDraft (state, { id }) {
delete state.drafts[id]
+ },
+ loadDrafts (state, data) {
+ state.drafts = data
}
}
+const storageKey = 'pleroma-fe-drafts'
+
+/*
+ * Note: we do not use the persist state plugin because
+ * it is not impossible for a user to have two windows at
+ * the same time. The persist state plugin is just overriding
+ * everything with the current state. This isn't good because
+ * if a draft is created in one window and another draft is
+ * created in another, the draft in the first window will just
+ * be overriden.
+ * Here, we can't guarantee 100% atomicity unless one uses
+ * different keys, which will just pollute the whole storage.
+ * It is indeed best to have backend support for this.
+ */
+const getStorageData = async () => ((await storage.getItem(storageKey)) || {})
+
+const saveDraftToStorage = async (draft) => {
+ const currentData = await getStorageData()
+ currentData[draft.id] = JSON.parse(JSON.stringify(draft))
+ await storage.setItem(storageKey, currentData)
+}
+
+const deleteDraftFromStorage = async (id) => {
+ const currentData = await getStorageData()
+ delete currentData[id]
+ await storage.setItem(storageKey, currentData)
+}
+
export const actions = {
- addOrSaveDraft (store, { draft }) {
+ async addOrSaveDraft (store, { draft }) {
const id = draft.id || (new Date().getTime()).toString()
- store.commit('addOrSaveDraft', { draft: { ...draft, id } })
+ const draftWithId = { ...draft, id }
+ store.commit('addOrSaveDraft', { draft: draftWithId })
+ await saveDraftToStorage(draftWithId)
return id
},
- abandonDraft (store, { id }) {
+ async abandonDraft (store, { id }) {
store.commit('abandonDraft', { id })
+ await deleteDraftFromStorage(id)
+ },
+ async loadDrafts (store) {
+ const currentData = await getStorageData()
+ store.commit('loadDrafts', currentData)
}
}
diff --git a/src/sw.js b/src/sw.js
@@ -1,6 +1,6 @@
/* eslint-env serviceworker */
-import localForage from 'localforage'
+import { storage } from 'src/lib/storage.js'
import { parseNotification } from './services/entity_normalizer/entity_normalizer.service.js'
import { prepareNotificationObject } from './services/notification_utils/notification_utils.js'
import { createI18n } from 'vue-i18n'