aboutsummaryrefslogtreecommitdiff
path: root/viewer/src/services/navigation.ts
diff options
context:
space:
mode:
Diffstat (limited to 'viewer/src/services/navigation.ts')
-rw-r--r--viewer/src/services/navigation.ts100
1 files changed, 55 insertions, 45 deletions
diff --git a/viewer/src/services/navigation.ts b/viewer/src/services/navigation.ts
index 5b0716d..fb01169 100644
--- a/viewer/src/services/navigation.ts
+++ b/viewer/src/services/navigation.ts
@@ -1,7 +1,7 @@
1/* ldgallery - A static generator which turns a collection of tagged 1/* ldgallery - A static generator which turns a collection of tagged
2-- pictures into a searchable web gallery. 2-- pictures into a searchable web gallery.
3-- 3--
4-- Copyright (C) 2019-2020 Guillaume FOUET 4-- Copyright (C) 2019-2022 Guillaume FOUET
5-- 5--
6-- This program is free software: you can redistribute it and/or modify 6-- This program is free software: you can redistribute it and/or modify
7-- it under the terms of the GNU Affero General Public License as 7-- it under the terms of the GNU Affero General Public License as
@@ -17,25 +17,43 @@
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
20import { ItemType } from "@/@types/ItemType"; 20import { DirectoryItem, DownloadableItem, Item } from '@/@types/gallery';
21import { ItemType } from '@/@types/itemType';
22import {
23 faFile,
24 faFileAlt,
25 faFileAudio,
26 faFilePdf,
27 faBook,
28 faFileVideo,
29 faFolder,
30 faHome,
31 faImage,
32 IconDefinition,
33} from '@fortawesome/free-solid-svg-icons';
34import { isDirectory } from './itemGuards';
21 35
22export default class Navigation { 36const ICON_BY_TYPE: Record<ItemType, IconDefinition> = {
23 static readonly ICON_BY_TYPE: Record<ItemType, string> = { 37 directory: faFolder,
24 directory: "folder", 38 picture: faImage,
25 picture: "image", 39 plaintext: faFileAlt,
26 plaintext: "file-alt", 40 markdown: faFileAlt,
27 pdf: "file-pdf", 41 pdf: faFilePdf,
28 video: "file-video", 42 epub: faBook,
29 audio: "file-audio", 43 video: faFileVideo,
30 other: "file", 44 audio: faFileAudio,
31 }; 45 other: faFile,
46};
47
48// ---
32 49
50export const useNavigation = () => {
33 // Searches for an item by path from a root item (navigation) 51 // Searches for an item by path from a root item (navigation)
34 public static searchCurrentItemPath(root: Gallery.Item, path: string): Gallery.Item[] { 52 function searchCurrentItemPath(root: Item, path: string): Item[] {
35 if (path === root.path) return [root]; 53 if (path === root.path) return [root];
36 if (root.properties.type === ItemType.DIRECTORY && path.startsWith(root.path)) { 54 if (isDirectory(root) && path.startsWith(root.path)) {
37 const itemChain = root.properties.items 55 const itemChain = root.properties.items
38 .map(item => this.searchCurrentItemPath(item, path)) 56 .map(item => searchCurrentItemPath(item, path))
39 .find(itemChain => itemChain.length > 0); 57 .find(itemChain => itemChain.length > 0);
40 if (itemChain) return [root, ...itemChain]; 58 if (itemChain) return [root, ...itemChain];
41 } 59 }
@@ -43,47 +61,39 @@ export default class Navigation {
43 } 61 }
44 62
45 // Normalize a string to lowercase, no-accents 63 // Normalize a string to lowercase, no-accents
46 public static normalize(value: string) { 64 function normalize(value: string) {
47 return value 65 return value
48 .normalize("NFD") 66 .normalize('NFD')
49 .replace(/[\u0300-\u036f]/g, "") 67 .replace(/[\u0300-\u036f]/g, '')
50 .toLowerCase(); 68 .toLowerCase();
51 } 69 }
52 70
53 // Checks if the type of an item matches 71 function getLastDirectory(itemPath: Item[]): DirectoryItem {
54 public static checkType(item: Gallery.Item | null, type: ItemType | null): boolean {
55 return (item?.properties.type ?? null) === type;
56 }
57
58 public static getLastDirectory(itemPath: Gallery.Item[]): Gallery.Directory {
59 for (let idx = itemPath.length - 1; idx >= 0; idx--) { 72 for (let idx = itemPath.length - 1; idx >= 0; idx--) {
60 const item = itemPath[idx]; 73 const item = itemPath[idx];
61 if (Navigation.checkType(item, ItemType.DIRECTORY)) return item as Gallery.Directory; 74 if (isDirectory(item)) return item;
62 } 75 }
63 throw new Error("No directory found"); 76 throw new Error('No directory found');
64 }
65
66 // Sort a list of items, moving the directories to the beginning of the list
67 public static directoriesFirst(items: Gallery.Item[]) {
68 return [
69 ...items
70 .filter(child => Navigation.checkType(child, ItemType.DIRECTORY))
71 .sort((a, b) => a.title.localeCompare(b.title)),
72
73 ...items.filter(child => !Navigation.checkType(child, ItemType.DIRECTORY)),
74 ];
75 } 77 }
76 78
77 // Get the icon for an item 79 // Get the icon for an item
78 public static getIcon(item: Gallery.Item): string { 80 function getIcon(item: Item): IconDefinition {
79 if (item.path.length <= 1) return "home"; 81 if (item.path.length <= 1) return faHome;
80 return Navigation.ICON_BY_TYPE[item.properties.type]; 82 return ICON_BY_TYPE[item.properties.type];
81 } 83 }
82 84
83 // Get the file name of an item, without its cache timestamp 85 // Get the file name of an item, without its cache timestamp
84 public static getFileName(item: Gallery.Item): string { 86 function getFileName(item: Item): string {
85 if (item.properties.type === ItemType.DIRECTORY) return item.title; 87 if (isDirectory(item)) return item.title;
86 const timeStamped = item.properties.resource.split("/").pop() ?? ""; 88 const timeStamped = (item as DownloadableItem).properties.resource.split('/').pop() ?? '';
87 return timeStamped.split("?")[0]; 89 return timeStamped.split('?')[0];
88 } 90 }
89} 91
92 return {
93 searchCurrentItemPath,
94 normalize,
95 getLastDirectory,
96 getIcon,
97 getFileName,
98 };
99};