logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://anongit.hacktivis.me/git/pleroma-fe.git/
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:

Msrc/boot/after_store.js2++
Msrc/components/draft/draft.vue4++--
Msrc/i18n/en.json3++-
Msrc/lib/persisted_state.js4++--
Asrc/lib/storage.js3+++
Msrc/modules/drafts.js45++++++++++++++++++++++++++++++++++++++++++---
Msrc/sw.js2+-
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'