feat(admin-ui): add tags view state
This commit is contained in:
1 parent
3c8c6490fd
commit
96612607e5
3 files changed
+541
No files matched your search
@@ -0,0 +1,166 @@
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import {
|
||||
addVisitedTag,
|
||||
closeAllTags as closeAllVisitedTags,
|
||||
closeTag,
|
||||
closeTagsToLeft,
|
||||
closeTagsToRight,
|
||||
getTagsViewsKey,
|
||||
HOME_TAG,
|
||||
isVisitedTag,
|
||||
normalizeVisitedTag,
|
||||
type VisitedTag,
|
||||
} from "../lib/tags";
|
||||
|
||||
export type TagsPersistenceOptions = {
|
||||
tagsView: boolean;
|
||||
tagsViewPersist: boolean;
|
||||
};
|
||||
|
||||
function getStorage(): Storage | null {
|
||||
try {
|
||||
return typeof window === "undefined" ? null : window.localStorage;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function readPersistedViews(storageKey: string): VisitedTag[] {
|
||||
try {
|
||||
const serialized = getStorage()?.getItem(storageKey);
|
||||
if (serialized === null || serialized === undefined) return [HOME_TAG];
|
||||
const parsed: unknown = JSON.parse(serialized);
|
||||
if (!Array.isArray(parsed)) return [HOME_TAG];
|
||||
|
||||
const views = parsed
|
||||
.filter(isVisitedTag)
|
||||
.map(normalizeVisitedTag)
|
||||
.filter((view): view is VisitedTag => view !== null)
|
||||
.reduce<VisitedTag[]>((result, view) => addVisitedTag(result, view), []);
|
||||
return [HOME_TAG, ...views.filter((view) => view.fullPath !== HOME_TAG.fullPath && !view.affix)];
|
||||
} catch {
|
||||
return [HOME_TAG];
|
||||
}
|
||||
}
|
||||
|
||||
export const useTagsStore = defineStore("tags", () => {
|
||||
const visitedViews = ref<VisitedTag[]>([{ ...HOME_TAG }]);
|
||||
const activePath = ref(HOME_TAG.fullPath);
|
||||
const tagsView = ref(false);
|
||||
const tagsViewPersist = ref(false);
|
||||
let persistenceScope: string | null = null;
|
||||
|
||||
function storageKey() {
|
||||
return getTagsViewsKey(persistenceScope);
|
||||
}
|
||||
|
||||
function persist() {
|
||||
if (!tagsView.value || !tagsViewPersist.value) return;
|
||||
try {
|
||||
getStorage()?.setItem(storageKey(), JSON.stringify(visitedViews.value));
|
||||
} catch {
|
||||
// Storage may be unavailable or disabled in the current browser context.
|
||||
}
|
||||
}
|
||||
|
||||
function setPersistenceEnabled(options: TagsPersistenceOptions) {
|
||||
tagsView.value = options.tagsView;
|
||||
tagsViewPersist.value = options.tagsViewPersist;
|
||||
}
|
||||
|
||||
function setPersistenceScope(scope: string | null) {
|
||||
persistenceScope = scope;
|
||||
}
|
||||
|
||||
function addView(view: VisitedTag) {
|
||||
visitedViews.value = addVisitedTag(visitedViews.value, view);
|
||||
activePath.value = view.fullPath;
|
||||
persist();
|
||||
}
|
||||
|
||||
function updateView(view: VisitedTag) {
|
||||
const index = visitedViews.value.findIndex((item) => item.fullPath === view.fullPath);
|
||||
if (index < 0) {
|
||||
addView(view);
|
||||
return;
|
||||
}
|
||||
visitedViews.value = visitedViews.value.map((item, itemIndex) => itemIndex === index ? { ...view } : { ...item });
|
||||
activePath.value = view.fullPath;
|
||||
persist();
|
||||
}
|
||||
|
||||
function closeSelectedTag(fullPath = activePath.value): string {
|
||||
const result = closeTag(visitedViews.value, fullPath, activePath.value);
|
||||
visitedViews.value = result.views;
|
||||
activePath.value = result.activePath;
|
||||
persist();
|
||||
return result.activePath;
|
||||
}
|
||||
|
||||
function closeOthersTags(fullPath = activePath.value) {
|
||||
visitedViews.value = visitedViews.value.filter((view) => view.affix || view.fullPath === fullPath).map((view) => ({ ...view }));
|
||||
activePath.value = visitedViews.value.some((view) => view.fullPath === fullPath) ? fullPath : HOME_TAG.fullPath;
|
||||
persist();
|
||||
}
|
||||
|
||||
function closeLeftTags(fullPath = activePath.value) {
|
||||
visitedViews.value = closeTagsToLeft(visitedViews.value, fullPath);
|
||||
if (!visitedViews.value.some((view) => view.fullPath === activePath.value)) {
|
||||
activePath.value = visitedViews.value.some((view) => view.fullPath === fullPath)
|
||||
? fullPath
|
||||
: HOME_TAG.fullPath;
|
||||
}
|
||||
persist();
|
||||
}
|
||||
|
||||
function closeRightTags(fullPath = activePath.value) {
|
||||
visitedViews.value = closeTagsToRight(visitedViews.value, fullPath);
|
||||
if (!visitedViews.value.some((view) => view.fullPath === activePath.value)) {
|
||||
activePath.value = visitedViews.value.some((view) => view.fullPath === fullPath)
|
||||
? fullPath
|
||||
: HOME_TAG.fullPath;
|
||||
}
|
||||
persist();
|
||||
}
|
||||
|
||||
function closeAllTags() {
|
||||
visitedViews.value = closeAllVisitedTags(visitedViews.value);
|
||||
activePath.value = HOME_TAG.fullPath;
|
||||
persist();
|
||||
}
|
||||
|
||||
function refreshSelectedTag(): VisitedTag {
|
||||
const selected = visitedViews.value.find((view) => view.fullPath === activePath.value);
|
||||
if (selected) return selected;
|
||||
const fallback = visitedViews.value.find((view) => view.fullPath === HOME_TAG.fullPath) ?? HOME_TAG;
|
||||
activePath.value = fallback.fullPath;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function restorePersistedViews() {
|
||||
if (!tagsView.value || !tagsViewPersist.value) return;
|
||||
visitedViews.value = readPersistedViews(storageKey());
|
||||
activePath.value = visitedViews.value.some((view) => view.fullPath === activePath.value)
|
||||
? activePath.value
|
||||
: HOME_TAG.fullPath;
|
||||
}
|
||||
|
||||
return {
|
||||
visitedViews,
|
||||
activePath,
|
||||
tagsView,
|
||||
tagsViewPersist,
|
||||
setPersistenceEnabled,
|
||||
setPersistenceScope,
|
||||
addView,
|
||||
updateView,
|
||||
closeSelectedTag,
|
||||
closeOthersTags,
|
||||
closeLeftTags,
|
||||
closeRightTags,
|
||||
closeAllTags,
|
||||
refreshSelectedTag,
|
||||
restorePersistedViews,
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user