diff options
Diffstat (limited to 'viewer/src/store')
-rw-r--r-- | viewer/src/store/galleryStore.ts | 180 | ||||
-rw-r--r-- | viewer/src/store/index.ts | 13 | ||||
-rw-r--r-- | viewer/src/store/uiStore.ts | 40 |
3 files changed, 118 insertions, 115 deletions
diff --git a/viewer/src/store/galleryStore.ts b/viewer/src/store/galleryStore.ts index c4a039f..0cffdd9 100644 --- a/viewer/src/store/galleryStore.ts +++ b/viewer/src/store/galleryStore.ts | |||
@@ -18,93 +18,105 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | import { createModule, mutation, action } from "vuex-class-component"; | 20 | import { createModule, mutation, action } from "vuex-class-component"; |
21 | import IndexFactory from "@/services/indexfactory"; | ||
22 | import Navigation from "@/services/navigation"; | ||
21 | 23 | ||
22 | const VuexModule = createModule({ | 24 | const VuexModule = createModule({ |
23 | namespaced: "galleryStore", | 25 | namespaced: "galleryStore", |
24 | strict: true | 26 | strict: true |
25 | }) | 27 | }) |
26 | 28 | ||
27 | export default class GalleryStore extends VuexModule { | 29 | export default class GalleryStore extends VuexModule { |
28 | 30 | ||
29 | galleryItemsRoot: Gallery.Item | null = null; | 31 | config: Gallery.Config | null = null; |
30 | tags: Tag.Index = {}; | 32 | galleryIndex: Gallery.Index | null = null; |
31 | currentPath: string = "/"; | 33 | tagsIndex: Tag.Index = {}; |
32 | 34 | tagsCategories: Tag.Category[] = []; | |
33 | // --- | 35 | currentPath: string = "/"; |
34 | 36 | currentSearch: Tag.Search[] = []; | |
35 | @mutation setGalleryItemsRoot(galleryItemsRoot: Gallery.Item) { | 37 | |
36 | this.galleryItemsRoot = galleryItemsRoot; | 38 | // --- |
37 | } | 39 | |
38 | 40 | @mutation private setConfig(config: Gallery.Config) { | |
39 | @mutation private setTags(tags: Tag.Index) { | 41 | this.config = config; |
40 | this.tags = tags; | 42 | } |
41 | } | 43 | |
42 | 44 | @mutation setGalleryIndex(galleryIndex: Gallery.Index) { | |
43 | @mutation setCurrentPath(currentPath: string) { | 45 | this.galleryIndex = Object.freeze(galleryIndex); |
44 | this.currentPath = currentPath; | 46 | } |
45 | } | 47 | |
46 | 48 | @mutation private setTagsIndex(tagsIndex: Tag.Index) { | |
47 | get currentItemPath(): Gallery.Item[] { | 49 | this.tagsIndex = Object.freeze(tagsIndex); |
48 | const galleryItemsRoot = this.galleryItemsRoot; | 50 | } |
49 | if (galleryItemsRoot) | 51 | |
50 | return GalleryStore.searchCurrentItemPath(galleryItemsRoot, this.currentPath); | 52 | @mutation private setTagsCategories(tagsCategories: Tag.Category[]) { |
51 | return []; | 53 | this.tagsCategories = tagsCategories; |
52 | } | 54 | } |
53 | 55 | ||
54 | get currentItem(): Gallery.Item | null { | 56 | @mutation setCurrentPath(currentPath: string) { |
55 | const currentItemPath = this.currentItemPath; | 57 | this.currentPath = currentPath; |
56 | return currentItemPath.length > 0 ? currentItemPath[currentItemPath.length - 1] : null; | 58 | } |
57 | } | 59 | |
58 | 60 | @mutation setCurrentSearch(currentSearch: Tag.Search[]) { | |
59 | // --- | 61 | this.currentSearch = currentSearch; |
60 | 62 | } | |
61 | // Fetches the gallery's JSON metadata | 63 | |
62 | @action async fetchGalleryItems(url: string) { | 64 | // --- |
63 | fetch(url) | 65 | |
64 | .then(response => response.json()) | 66 | get currentItemPath(): Gallery.Item[] { |
65 | .then(this.setGalleryItemsRoot) | 67 | const root = this.galleryIndex?.tree; |
66 | .then(this.indexTags); | 68 | if (root) |
67 | } | 69 | return Navigation.searchCurrentItemPath(root, this.currentPath); |
68 | 70 | return []; | |
69 | // Indexes the gallery | 71 | } |
70 | @action async indexTags() { | 72 | |
71 | let index = {}; | 73 | get currentItem(): Gallery.Item | null { |
72 | if (this.galleryItemsRoot) | 74 | const path = this.currentItemPath; |
73 | GalleryStore.pushTagsForItem(index, this.galleryItemsRoot); | 75 | return path.length > 0 ? path[path.length - 1] : null; |
74 | console.log("Index: ", index); | 76 | } |
75 | this.setTags(index); | 77 | |
76 | } | 78 | get galleryTitle(): string { |
77 | 79 | return this.galleryIndex?.properties.galleryTitle ?? "ldgallery"; | |
78 | // --- | 80 | } |
79 | 81 | ||
80 | // Pushes all tags for a root item (and its children) to the index | 82 | // --- |
81 | private static pushTagsForItem(index: Tag.Index, item: Gallery.Item) { | 83 | |
82 | console.log("IndexingTagsFor: ", item.path); | 84 | // Fetches the gallery's JSON config |
83 | if (item.properties.type === "directory") { | 85 | @action async fetchConfig() { |
84 | item.properties.items.forEach(item => this.pushTagsForItem(index, item)); | 86 | return fetch(`${process.env.VUE_APP_DATA_URL}config.json`, { cache: "no-cache" }) |
85 | return; // Directories are not indexed | 87 | .then(response => response.json()) |
86 | } | 88 | .then(this.setConfig); |
87 | for (const tag of item.tags) { | 89 | } |
88 | const parts = tag.split('.'); | 90 | |
89 | let lastPart: string | null = null; | 91 | // Fetches the gallery's JSON metadata |
90 | for (const part of parts) { | 92 | @action async fetchGalleryItems() { |
91 | if (!index[part]) index[part] = { tag: part, items: [], children: {} }; | 93 | const root = this.config?.galleryRoot ?? ""; |
92 | if (!index[part].items.includes(item)) index[part].items.push(item); | 94 | return fetch(`${process.env.VUE_APP_DATA_URL}${root}index.json`, { cache: "no-cache" }) |
93 | if (lastPart) index[lastPart].children[part] = index[part]; | 95 | .then(response => response.json()) |
94 | lastPart = part; | 96 | .then(this.setGalleryIndex) |
95 | } | 97 | .then(this.indexTags) |
96 | } | 98 | .then(this.indexTagCategories); |
97 | } | 99 | } |
98 | 100 | ||
99 | // Searches for an item by path from a root item (navigation) | 101 | // Indexes the gallery |
100 | private static searchCurrentItemPath(item: Gallery.Item, path: string): Gallery.Item[] { | 102 | @action async indexTags() { |
101 | if (path === item.path) return [item]; | 103 | const root = this.galleryIndex?.tree ?? null; |
102 | if (item.properties.type === "directory" && path.startsWith(item.path)) { | 104 | const index = IndexFactory.generateTags(root); |
103 | const itemChain = item.properties.items | 105 | this.setTagsIndex(index); |
104 | .map(item => this.searchCurrentItemPath(item, path)) | 106 | return index; |
105 | .find(itemChain => itemChain.length > 0); | 107 | } |
106 | if (itemChain) return [item, ...itemChain]; | 108 | |
107 | } | 109 | // Indexes the proposed categories |
108 | return []; | 110 | @action async indexTagCategories() { |
109 | } | 111 | const categories = IndexFactory.generateCategories(this.tagsIndex, this.galleryIndex?.properties.tagCategories); |
110 | } \ No newline at end of file | 112 | this.setTagsCategories(categories); |
113 | return categories; | ||
114 | } | ||
115 | |||
116 | // Searches for tags | ||
117 | @action async search(filters: string[]) { | ||
118 | const results = filters.flatMap(filter => IndexFactory.searchTags(this.tagsIndex, filter, true)); | ||
119 | this.setCurrentSearch(results); | ||
120 | return results; | ||
121 | } | ||
122 | } | ||
diff --git a/viewer/src/store/index.ts b/viewer/src/store/index.ts index 0277fa4..d5339e8 100644 --- a/viewer/src/store/index.ts +++ b/viewer/src/store/index.ts | |||
@@ -17,12 +17,12 @@ | |||
17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. | 17 | -- along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | import Vue from 'vue' | 20 | import Vue from "vue" |
21 | import Vuex from 'vuex' | 21 | import Vuex from "vuex" |
22 | import { extractVuexModule } from "vuex-class-component"; | 22 | import { extractVuexModule } from "vuex-class-component"; |
23 | import { createProxy } from "vuex-class-component"; | 23 | import { createProxy } from "vuex-class-component"; |
24 | import UIStore from '@/store/uiStore'; | 24 | import UIStore from "@/store/uiStore"; |
25 | import GalleryStore from '@/store/galleryStore'; | 25 | import GalleryStore from "@/store/galleryStore"; |
26 | 26 | ||
27 | Vue.use(Vuex) | 27 | Vue.use(Vuex) |
28 | 28 | ||
@@ -30,13 +30,14 @@ const store = new Vuex.Store({ | |||
30 | modules: { | 30 | modules: { |
31 | ...extractVuexModule(UIStore), | 31 | ...extractVuexModule(UIStore), |
32 | ...extractVuexModule(GalleryStore) | 32 | ...extractVuexModule(GalleryStore) |
33 | } | 33 | }, |
34 | strict: process.env.NODE_ENV !== "production", | ||
34 | }); | 35 | }); |
35 | 36 | ||
36 | Vue.use((vue) => vue.prototype.$uiStore = createProxy(store, UIStore)); | 37 | Vue.use((vue) => vue.prototype.$uiStore = createProxy(store, UIStore)); |
37 | Vue.use((vue) => vue.prototype.$galleryStore = createProxy(store, GalleryStore)); | 38 | Vue.use((vue) => vue.prototype.$galleryStore = createProxy(store, GalleryStore)); |
38 | 39 | ||
39 | declare module 'vue/types/vue' { | 40 | declare module "vue/types/vue" { |
40 | interface Vue { | 41 | interface Vue { |
41 | $uiStore: UIStore, | 42 | $uiStore: UIStore, |
42 | $galleryStore: GalleryStore | 43 | $galleryStore: GalleryStore |
diff --git a/viewer/src/store/uiStore.ts b/viewer/src/store/uiStore.ts index 6bcc538..892d35e 100644 --- a/viewer/src/store/uiStore.ts +++ b/viewer/src/store/uiStore.ts | |||
@@ -20,37 +20,27 @@ | |||
20 | import { createModule, mutation, action } from "vuex-class-component"; | 20 | import { createModule, mutation, action } from "vuex-class-component"; |
21 | 21 | ||
22 | const VuexModule = createModule({ | 22 | const VuexModule = createModule({ |
23 | namespaced: "uiStore", | 23 | namespaced: "uiStore", |
24 | strict: false | 24 | strict: true |
25 | }) | 25 | }) |
26 | 26 | ||
27 | export default class UIStore extends VuexModule { | 27 | export default class UIStore extends VuexModule { |
28 | 28 | ||
29 | fullscreen: boolean = false; | 29 | fullscreen: boolean = false; |
30 | mode: "navigation" | "search" = "navigation"; | 30 | fullWidth: boolean = window.innerWidth < Number(process.env.VUE_APP_FULLWIDTH_LIMIT); |
31 | currentTags: Tag.Search[] = []; | 31 | searchMode: boolean = false; |
32 | 32 | ||
33 | // --- | 33 | // --- |
34 | 34 | ||
35 | get isModeSearch() { | 35 | @mutation toggleFullscreen(value?: boolean) { |
36 | return this.mode === "sear |