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.ts90
1 files changed, 43 insertions, 47 deletions
diff --git a/viewer/src/services/navigation.ts b/viewer/src/services/navigation.ts
index 5dcea88..b2e807b 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,27 +17,31 @@
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 { DirectoryItem, Item } from "@/@types/gallery"; 20import { DirectoryItem, DownloadableItem, Item } from '@/@types/gallery';
21import { ItemType } from "@/@types/ItemType"; 21import { ItemType } from '@/@types/itemType';
22import { faFile, faFileAlt, faFileAudio, faFilePdf, faFileVideo, faFolder, faHome, faImage, IconDefinition } from '@fortawesome/free-solid-svg-icons';
23import { isDirectory } from './itemGuards';
22 24
23export default class Navigation { 25const ICON_BY_TYPE: Record<ItemType, IconDefinition> = {
24 static readonly ICON_BY_TYPE: Record<ItemType, string> = { 26 directory: faFolder,
25 directory: "folder", 27 picture: faImage,
26 picture: "image", 28 plaintext: faFileAlt,
27 plaintext: "file-alt", 29 markdown: faFileAlt,
28 markdown: "file-alt", 30 pdf: faFilePdf,
29 pdf: "file-pdf", 31 video: faFileVideo,
30 video: "file-video", 32 audio: faFileAudio,
31 audio: "file-audio", 33 other: faFile,
32 other: "file", 34};
33 }; 35
36// ---
34 37
38export const useNavigation = () => {
35 // Searches for an item by path from a root item (navigation) 39 // Searches for an item by path from a root item (navigation)
36 public static searchCurrentItemPath(root: Item, path: string): Item[] { 40 function searchCurrentItemPath(root: Item, path: string): Item[] {
37 if (path === root.path) return [root]; 41 if (path === root.path) return [root];
38 if (root.properties.type === ItemType.DIRECTORY && path.startsWith(root.path)) { 42 if (isDirectory(root) && path.startsWith(root.path)) {
39 const itemChain = root.properties.items 43 const itemChain = root.properties.items
40 .map(item => this.searchCurrentItemPath(item, path)) 44 .map(item => searchCurrentItemPath(item, path))
41 .find(itemChain => itemChain.length > 0); 45 .find(itemChain => itemChain.length > 0);
42 if (itemChain) return [root, ...itemChain]; 46 if (itemChain) return [root, ...itemChain];
43 } 47 }
@@ -45,47 +49,39 @@ export default class Navigation {
45 } 49 }
46 50
47 // Normalize a string to lowercase, no-accents 51 // Normalize a string to lowercase, no-accents
48 public static normalize(value: string) { 52 function normalize(value: string) {
49 return value 53 return value
50 .normalize("NFD") 54 .normalize('NFD')
51 .replace(/[\u0300-\u036f]/g, "") 55 .replace(/[\u0300-\u036f]/g, '')
52 .toLowerCase(); 56 .toLowerCase();
53 } 57 }
54 58
55 // Checks if the type of an item matches 59 function getLastDirectory(itemPath: Item[]): DirectoryItem {
56 public static checkType(item: Item | null, type: ItemType | null): boolean {
57 return (item?.properties.type ?? null) === type;
58 }
59
60 public static getLastDirectory(itemPath: Item[]): DirectoryItem {
61 for (let idx = itemPath.length - 1; idx >= 0; idx--) { 60 for (let idx = itemPath.length - 1; idx >= 0; idx--) {
62 const item = itemPath[idx]; 61 const item = itemPath[idx];
63 if (Navigation.checkType(item, ItemType.DIRECTORY)) return item as DirectoryItem; 62 if (isDirectory(item)) return item;
64 } 63 }
65 throw new Error("No directory found"); 64 throw new Error('No directory found');
66 }
67
68 // Sort a list of items, moving the directories to the beginning of the list
69 public static directoriesFirst(items: Item[]) {
70 return [
71 ...items
72 .filter(child => Navigation.checkType(child, ItemType.DIRECTORY))
73 .sort((a, b) => a.title.localeCompare(b.title)),
74
75 ...items.filter(child => !Navigation.checkType(child, ItemType.DIRECTORY)),
76 ];
77 } 65 }
78 66
79 // Get the icon for an item 67 // Get the icon for an item
80 public static getIcon(item: Item): string { 68 function getIcon(item: Item): IconDefinition {
81 if (item.path.length <= 1) return "home"; 69 if (item.path.length <= 1) return faHome;
82 return Navigation.ICON_BY_TYPE[item.properties.type]; 70 return ICON_BY_TYPE[item.properties.type];
83 } 71 }
84 72
85 // Get the file name of an item, without its cache timestamp 73 // Get the file name of an item, without its cache timestamp
86 public static getFileName(item: Item): string { 74 function getFileName(item: Item): string {
87 if (item.properties.type === ItemType.DIRECTORY) return item.title; 75 if (isDirectory(item)) return item.title;
88 const timeStamped = item.properties.resource.split("/").pop() ?? ""; 76 const timeStamped = (item as DownloadableItem).properties.resource.split('/').pop() ?? '';
89 return timeStamped.split("?")[0]; 77 return timeStamped.split('?')[0];
90 } 78 }
91} 79
80 return {
81 searchCurrentItemPath,
82 normalize,
83 getLastDirectory,
84 getIcon,
85 getFileName,
86 };
87};