mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-17 06:30:50 +01:00
zwischenstand
This commit is contained in:
@ -1,38 +1,38 @@
|
||||
export interface ResourceRequestDetails {
|
||||
url: string;
|
||||
resourceType: string;
|
||||
tabId?: string;
|
||||
frameId?: number;
|
||||
url: string
|
||||
resourceType: string
|
||||
tabId?: string
|
||||
frameId?: number
|
||||
}
|
||||
|
||||
export interface ResourceRequestResult {
|
||||
cancel: boolean;
|
||||
redirectUrl?: string;
|
||||
cancel: boolean
|
||||
redirectUrl?: string
|
||||
}
|
||||
|
||||
export interface ContentScript {
|
||||
code: string;
|
||||
matches?: string[];
|
||||
runAt?: 'document_start' | 'document_end' | 'document_idle';
|
||||
code: string
|
||||
matches?: string[]
|
||||
runAt?: 'document_start' | 'document_end' | 'document_idle'
|
||||
}
|
||||
|
||||
export interface Extension {
|
||||
id: string;
|
||||
name: string;
|
||||
version: string;
|
||||
description?: string;
|
||||
processNavigation?: (url: string) => boolean;
|
||||
id: string
|
||||
name: string
|
||||
version: string
|
||||
description?: string
|
||||
processNavigation?: (url: string) => boolean
|
||||
processResourceRequest?: (
|
||||
details: ResourceRequestDetails
|
||||
) => ResourceRequestResult;
|
||||
contentScripts?: ContentScript[];
|
||||
details: ResourceRequestDetails,
|
||||
) => ResourceRequestResult
|
||||
contentScripts?: ContentScript[]
|
||||
}
|
||||
|
||||
export const useBrowserExtensionStore = defineStore(
|
||||
'useBrowserExtensionStore',
|
||||
() => {
|
||||
const extensions = ref<Extension[]>([]);
|
||||
const isInitialized = ref<boolean>(false);
|
||||
const extensions = ref<Extension[]>([])
|
||||
const isInitialized = ref<boolean>(false)
|
||||
|
||||
return {
|
||||
extensions,
|
||||
@ -40,28 +40,28 @@ export const useBrowserExtensionStore = defineStore(
|
||||
initializeAsync,
|
||||
processNavigation,
|
||||
injectContentScripts,
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const initializeAsync = async () => {
|
||||
const { isInitialized } = storeToRefs(useBrowserExtensionStore());
|
||||
const { isInitialized } = storeToRefs(useBrowserExtensionStore())
|
||||
return
|
||||
if (isInitialized.value) return;
|
||||
if (isInitialized.value) return
|
||||
|
||||
// Lade Erweiterungen aus dem Erweiterungsverzeichnis
|
||||
try {
|
||||
const extensions = await loadExtensionsAsync();
|
||||
const extensions = await loadExtensionsAsync()
|
||||
for (const extension of extensions) {
|
||||
registerExtension(extension);
|
||||
registerExtension(extension)
|
||||
}
|
||||
|
||||
isInitialized.value = true;
|
||||
console.log(`${extensions.length} Erweiterungen geladen`);
|
||||
isInitialized.value = true
|
||||
console.log(`${extensions.length} Erweiterungen geladen`)
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Erweiterungen:', error);
|
||||
console.error('Fehler beim Laden der Erweiterungen:', error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const loadExtensionsAsync = async (): Promise<Extension[]> => {
|
||||
// In einer realen Implementierung würden Sie hier Erweiterungen aus einem Verzeichnis laden
|
||||
@ -69,23 +69,23 @@ const loadExtensionsAsync = async (): Promise<Extension[]> => {
|
||||
/* const adBlocker = (await import('./ad-blocker')).default;
|
||||
const trackerBlocker = (await import('./tracker-blocker')).default; */
|
||||
|
||||
return [];
|
||||
};
|
||||
return []
|
||||
}
|
||||
|
||||
const registerExtension = (extension: Extension): boolean => {
|
||||
const { extensions } = storeToRefs(useBrowserExtensionStore());
|
||||
const { extensions } = storeToRefs(useBrowserExtensionStore())
|
||||
if (!extension.id || !extension.name) {
|
||||
console.error('Ungültige Erweiterung:', extension);
|
||||
return false;
|
||||
console.error('Ungültige Erweiterung:', extension)
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`Erweiterung registriert: ${extension.name}`);
|
||||
extensions.value.push(extension);
|
||||
return true;
|
||||
};
|
||||
console.log(`Erweiterung registriert: ${extension.name}`)
|
||||
extensions.value.push(extension)
|
||||
return true
|
||||
}
|
||||
|
||||
const processNavigation = (url: string) => {
|
||||
return true;
|
||||
};
|
||||
const processNavigation = () => {
|
||||
return true
|
||||
}
|
||||
|
||||
const injectContentScripts = (t: string) => { };
|
||||
const injectContentScripts = () => {}
|
||||
|
||||
@ -1,116 +1,145 @@
|
||||
import { convertFileSrc, invoke } from "@tauri-apps/api/core";
|
||||
import { appDataDir, join } from "@tauri-apps/api/path";
|
||||
import { exists, readDir, readTextFile, remove } from "@tauri-apps/plugin-fs";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { appDataDir, join } from '@tauri-apps/api/path'
|
||||
import { exists, readDir, readTextFile, remove } from '@tauri-apps/plugin-fs'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import type {
|
||||
IHaexHubExtension,
|
||||
IHaexHubExtensionLink,
|
||||
IHaexHubExtensionManifest,
|
||||
} from "~/types/haexhub";
|
||||
import { haexExtensions } from "~~/src-tauri/database/schemas/vault";
|
||||
} from '~/types/haexhub'
|
||||
import { haexExtensions } from '~~/src-tauri/database/schemas/vault'
|
||||
|
||||
const manifestFileName = "manifest.json";
|
||||
const logoFileName = "logo.svg";
|
||||
const manifestFileName = 'manifest.json'
|
||||
const logoFileName = 'icon.svg'
|
||||
|
||||
export const useExtensionsStore = defineStore("extensionsStore", () => {
|
||||
const availableExtensions = ref<IHaexHubExtensionLink[]>([]);
|
||||
export const useExtensionsStore = defineStore('extensionsStore', () => {
|
||||
const availableExtensions = ref<IHaexHubExtensionLink[]>([])
|
||||
|
||||
const extensionLinks = computed<ISidebarItem[]>(() =>
|
||||
availableExtensions.value
|
||||
.filter((extension) => extension.enabled && extension.installed)
|
||||
.map((extension) => ({
|
||||
icon: extension.icon ?? "",
|
||||
icon: extension.icon ?? '',
|
||||
id: extension.id,
|
||||
name: extension.name ?? "",
|
||||
tooltip: extension.name ?? "",
|
||||
to: { name: "haexExtension", params: { extensionId: extension.id } },
|
||||
}))
|
||||
);
|
||||
name: extension.name ?? '',
|
||||
tooltip: extension.name ?? '',
|
||||
to: { name: 'haexExtension', params: { extensionId: extension.id } },
|
||||
})),
|
||||
)
|
||||
|
||||
const currentRoute = useRouter().currentRoute;
|
||||
const currentRoute = useRouter().currentRoute
|
||||
|
||||
const isActive = (id: string) =>
|
||||
computed(
|
||||
() => currentRoute.value.name === "extension" && currentRoute.value.params.extensionId === id
|
||||
);
|
||||
() =>
|
||||
currentRoute.value.name === 'extension' &&
|
||||
currentRoute.value.params.extensionId === id,
|
||||
)
|
||||
|
||||
const currentExtension = computed(() => {
|
||||
console.log("computed currentExtension", currentRoute.value.params);
|
||||
if (currentRoute.value.meta.name !== "haexExtension") return;
|
||||
console.log('computed currentExtension', currentRoute.value.params)
|
||||
if (currentRoute.value.meta.name !== 'haexExtension') return
|
||||
|
||||
const extensionId = getSingleRouteParam(currentRoute.value.params.extensionId);
|
||||
console.log("extensionId from param", extensionId);
|
||||
if (!extensionId) return;
|
||||
const extensionId = getSingleRouteParam(
|
||||
currentRoute.value.params.extensionId,
|
||||
)
|
||||
console.log('extensionId from param', extensionId)
|
||||
if (!extensionId) return
|
||||
|
||||
const extension = availableExtensions.value.find((extension) => extension.id === extensionId);
|
||||
console.log("currentExtension", extension);
|
||||
return extension;
|
||||
});
|
||||
const extension = availableExtensions.value.find(
|
||||
(extension) => extension.id === extensionId,
|
||||
)
|
||||
console.log('currentExtension', extension)
|
||||
return extension
|
||||
})
|
||||
|
||||
const getExtensionPathAsync = async (extensionId?: string, version?: string) => {
|
||||
if (!extensionId || !version) return "";
|
||||
return await join(await appDataDir(), "extensions", extensionId, version);
|
||||
};
|
||||
const getExtensionPathAsync = async (
|
||||
extensionId?: string,
|
||||
version?: string,
|
||||
) => {
|
||||
if (!extensionId || !version) return ''
|
||||
return await join(await appDataDir(), 'extensions', extensionId, version)
|
||||
}
|
||||
|
||||
const checkSourceExtensionDirectoryAsync = async (extensionDirectory: string) => {
|
||||
const checkSourceExtensionDirectoryAsync = async (
|
||||
extensionDirectory: string,
|
||||
) => {
|
||||
try {
|
||||
const dir = await readDir(extensionDirectory);
|
||||
const manifest = dir.find((entry) => entry.name === manifestFileName && entry.isFile);
|
||||
if (!manifest) throw new Error("Kein Manifest für Erweiterung gefunden");
|
||||
const dir = await readDir(extensionDirectory)
|
||||
const manifest = dir.find(
|
||||
(entry) => entry.name === manifestFileName && entry.isFile,
|
||||
)
|
||||
if (!manifest) throw new Error('Kein Manifest für Erweiterung gefunden')
|
||||
|
||||
const logo = dir.find((item) => item.isFile && item.name === logoFileName);
|
||||
if (!logo) throw new Error("Logo fehlt");
|
||||
const logo = dir.find((item) => item.isFile && item.name === logoFileName)
|
||||
if (!logo) throw new Error('Logo fehlt')
|
||||
console.log('found icon', logo)
|
||||
|
||||
return true;
|
||||
return true
|
||||
} catch (error) {
|
||||
throw new Error(`Keine Leseberechtigung für Ordner ${extensionDirectory}`);
|
||||
console.error(error)
|
||||
//throw error //new Error(`Keine Leseberechtigung für Ordner ${extensionDirectory}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const isExtensionInstalledAsync = async (extension: Partial<IHaexHubExtension>) => {
|
||||
const isExtensionInstalledAsync = async (
|
||||
extension: Partial<IHaexHubExtension>,
|
||||
) => {
|
||||
try {
|
||||
const extensionPath = await getExtensionPathAsync(extension.id, `${extension.version}`);
|
||||
console.log(`extension ${extension.id} is installed ${await exists(extensionPath)}`);
|
||||
return await exists(extensionPath);
|
||||
const extensionPath = await getExtensionPathAsync(
|
||||
extension.id,
|
||||
`${extension.version}`,
|
||||
)
|
||||
console.log(
|
||||
`extension ${extension.id} is installed ${await exists(extensionPath)}`,
|
||||
)
|
||||
return await exists(extensionPath)
|
||||
} catch (error) {
|
||||
return false;
|
||||
console.error(error)
|
||||
return false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const checkManifest = (manifestFile: unknown): manifestFile is IHaexHubExtensionManifest => {
|
||||
const errors = [];
|
||||
const checkManifest = (
|
||||
manifestFile: unknown,
|
||||
): manifestFile is IHaexHubExtensionManifest => {
|
||||
const errors = []
|
||||
|
||||
if (typeof manifestFile !== "object" || manifestFile === null) {
|
||||
errors.push("Manifest ist falsch");
|
||||
return false;
|
||||
if (typeof manifestFile !== 'object' || manifestFile === null) {
|
||||
errors.push('Manifest ist falsch')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!("id" in manifestFile) || typeof manifestFile.id !== "string")
|
||||
errors.push("Keine ID vergeben");
|
||||
if (!('id' in manifestFile) || typeof manifestFile.id !== 'string')
|
||||
errors.push('Keine ID vergeben')
|
||||
|
||||
if (!("name" in manifestFile) || typeof manifestFile.name !== "string")
|
||||
errors.push("Name fehlt");
|
||||
if (!('name' in manifestFile) || typeof manifestFile.name !== 'string')
|
||||
errors.push('Name fehlt')
|
||||
|
||||
if (!("entry" in manifestFile) || typeof manifestFile.entry !== "string")
|
||||
errors.push("Entry fehlerhaft");
|
||||
if (!('entry' in manifestFile) || typeof manifestFile.entry !== 'string')
|
||||
errors.push('Entry fehlerhaft')
|
||||
|
||||
if (!("author" in manifestFile) || typeof manifestFile.author !== "string")
|
||||
errors.push("Author fehlt");
|
||||
if (!('author' in manifestFile) || typeof manifestFile.author !== 'string')
|
||||
errors.push('Author fehlt')
|
||||
|
||||
if (!("url" in manifestFile) || typeof manifestFile.url !== "string") errors.push("Url fehlt");
|
||||
|
||||
if (!("version" in manifestFile) || typeof manifestFile.version !== "string")
|
||||
errors.push("Version fehlt");
|
||||
if (!('url' in manifestFile) || typeof manifestFile.url !== 'string')
|
||||
errors.push('Url fehlt')
|
||||
|
||||
if (
|
||||
!("permissions" in manifestFile) ||
|
||||
typeof manifestFile.permissions !== "object" ||
|
||||
!('version' in manifestFile) ||
|
||||
typeof manifestFile.version !== 'string'
|
||||
)
|
||||
errors.push('Version fehlt')
|
||||
|
||||
if (
|
||||
!('permissions' in manifestFile) ||
|
||||
typeof manifestFile.permissions !== 'object' ||
|
||||
manifestFile.permissions === null
|
||||
) {
|
||||
errors.push("Berechtigungen fehlen");
|
||||
errors.push('Berechtigungen fehlen')
|
||||
}
|
||||
|
||||
if (errors.length) throw errors;
|
||||
if (errors.length) throw errors
|
||||
|
||||
/* const permissions = manifestFile.permissions as Partial<IHaexHubExtensionManifest["permissions"]>;
|
||||
if (
|
||||
@ -122,59 +151,75 @@ export const useExtensionsStore = defineStore("extensionsStore", () => {
|
||||
return false;
|
||||
} */
|
||||
|
||||
return true;
|
||||
};
|
||||
return true
|
||||
}
|
||||
|
||||
const readManifestFileAsync = async (extensionId: string, version: string) => {
|
||||
const readManifestFileAsync = async (
|
||||
extensionId: string,
|
||||
version: string,
|
||||
) => {
|
||||
try {
|
||||
if (!(await isExtensionInstalledAsync({ id: extensionId, version }))) return null;
|
||||
if (!(await isExtensionInstalledAsync({ id: extensionId, version })))
|
||||
return null
|
||||
|
||||
const extensionPath = await getExtensionPathAsync(extensionId, `${version}`);
|
||||
const manifestPath = await join(extensionPath, manifestFileName);
|
||||
const extensionPath = await getExtensionPathAsync(
|
||||
extensionId,
|
||||
`${version}`,
|
||||
)
|
||||
const manifestPath = await join(extensionPath, manifestFileName)
|
||||
const manifest = (await JSON.parse(
|
||||
await readTextFile(manifestPath)
|
||||
)) as IHaexHubExtensionManifest;
|
||||
await readTextFile(manifestPath),
|
||||
)) as IHaexHubExtensionManifest
|
||||
|
||||
/*
|
||||
TODO implement check, that manifest has valid data
|
||||
*/
|
||||
return manifest;
|
||||
return manifest
|
||||
} catch (error) {
|
||||
console.error("ERROR readManifestFileAsync", error);
|
||||
console.error('ERROR readManifestFileAsync', error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const installAsync = async (extensionDirectory: string | null, global: boolean = true) => {
|
||||
const installAsync = async (extensionDirectory: string | null) => {
|
||||
try {
|
||||
if (!extensionDirectory) throw new Error("Kein Ordner für Erweiterung angegeben");
|
||||
const manifestPath = await join(extensionDirectory, manifestFileName);
|
||||
if (!extensionDirectory)
|
||||
throw new Error('Kein Ordner für Erweiterung angegeben')
|
||||
const manifestPath = await join(extensionDirectory, manifestFileName)
|
||||
const manifest = (await JSON.parse(
|
||||
await readTextFile(manifestPath)
|
||||
)) as IHaexHubExtensionManifest;
|
||||
await readTextFile(manifestPath),
|
||||
)) as IHaexHubExtensionManifest
|
||||
|
||||
const destination = await getExtensionPathAsync(manifest.id, manifest.version);
|
||||
const destination = await getExtensionPathAsync(
|
||||
manifest.id,
|
||||
manifest.version,
|
||||
)
|
||||
|
||||
await checkSourceExtensionDirectoryAsync(extensionDirectory);
|
||||
await checkSourceExtensionDirectoryAsync(extensionDirectory)
|
||||
|
||||
await invoke("copy_directory", { source: extensionDirectory, destination });
|
||||
await invoke('copy_directory', {
|
||||
source: extensionDirectory,
|
||||
destination,
|
||||
})
|
||||
|
||||
const logoFilePath = await join(destination, "logo.svg");
|
||||
const logoSvg = await readTextFile(logoFilePath);
|
||||
const logoFilePath = await join(destination, logoFileName)
|
||||
const logo = await readTextFile(logoFilePath)
|
||||
|
||||
const { currentVault } = storeToRefs(useVaultStore());
|
||||
const res = await currentVault.value?.drizzle.insert(haexExtensions).values({
|
||||
id: manifest.id,
|
||||
name: manifest.name,
|
||||
author: manifest.author,
|
||||
enabled: true,
|
||||
url: manifest.url,
|
||||
version: manifest.version,
|
||||
icon: logoSvg,
|
||||
});
|
||||
const { currentVault } = storeToRefs(useVaultStore())
|
||||
const res = await currentVault.value?.drizzle
|
||||
.insert(haexExtensions)
|
||||
.values({
|
||||
id: manifest.id,
|
||||
name: manifest.name,
|
||||
author: manifest.author,
|
||||
enabled: true,
|
||||
url: manifest.url,
|
||||
version: manifest.version,
|
||||
icon: logo,
|
||||
})
|
||||
|
||||
console.log("insert extensions", res);
|
||||
console.log('insert extensions', res)
|
||||
} catch (error) {
|
||||
throw error;
|
||||
throw error
|
||||
/*
|
||||
const resourcePath = await resourceDir();
|
||||
//const manifestPath = await join(extensionDirectory, 'manifest.json');
|
||||
@ -280,7 +325,7 @@ export const useExtensionsStore = defineStore("extensionsStore", () => {
|
||||
|
||||
console.log(`Plugin ${manifest.name} geladen.`); */
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const extensionEntry = computedAsync(
|
||||
async () => {
|
||||
@ -289,153 +334,79 @@ export const useExtensionsStore = defineStore("extensionsStore", () => {
|
||||
const regex = /((href|src)=["'])([^"']+)(["'])/g; */
|
||||
|
||||
if (!currentExtension.value?.id || !currentExtension.value.version) {
|
||||
console.log("extension id or entry missing", currentExtension.value);
|
||||
return ""// "no mani: " + currentExtension.value;
|
||||
console.log('extension id or entry missing', currentExtension.value)
|
||||
return '' // "no mani: " + currentExtension.value;
|
||||
}
|
||||
|
||||
const extensionPath = await getExtensionPathAsync(
|
||||
currentExtension.value?.id,
|
||||
currentExtension.value?.version
|
||||
); //await join(await resourceDir(), currentExtension.value.. extensionDir, entryFileName);
|
||||
currentExtension.value?.version,
|
||||
) //await join(await resourceDir(), currentExtension.value.. extensionDir, entryFileName);
|
||||
|
||||
console.log("extensionEntry extensionPath", extensionPath);
|
||||
console.log('extensionEntry extensionPath', extensionPath)
|
||||
const manifest = await readManifestFileAsync(
|
||||
currentExtension.value.id,
|
||||
currentExtension.value.version
|
||||
);
|
||||
currentExtension.value.version,
|
||||
)
|
||||
|
||||
if (!manifest) return ""//"no manifest readable";
|
||||
if (!manifest) return '' //"no manifest readable";
|
||||
|
||||
const entryPath = await join(extensionPath, manifest.entry);
|
||||
//const entryPath = await join(extensionPath, manifest.entry)
|
||||
|
||||
const hexName = stringToHex(
|
||||
JSON.stringify({
|
||||
id: currentExtension.value.id,
|
||||
version: currentExtension.value.version,
|
||||
})
|
||||
);
|
||||
}),
|
||||
)
|
||||
|
||||
return `haex-extension://${hexName}`;
|
||||
return convertFileSrc(entryPath); //`asset://localhost/${entryPath}`;
|
||||
let entryHtml = await readTextFile(entryPath);
|
||||
|
||||
console.log("entryHtml", entryHtml);
|
||||
const replacements = [];
|
||||
let match;
|
||||
/* while ((match = regex.exec(entryHtml)) !== null) {
|
||||
const [fullMatch, prefix, attr, resource, suffix] = match;
|
||||
if (!resource.startsWith("http")) {
|
||||
replacements.push({ match: fullMatch, resource, prefix, suffix });
|
||||
}
|
||||
} */
|
||||
|
||||
for (const { match, resource, prefix, suffix } of replacements) {
|
||||
const srcFile = convertFileSrc(await join(extensionPath, resource));
|
||||
entryHtml = entryHtml.replace(match, `${prefix}${srcFile}${suffix}`);
|
||||
}
|
||||
|
||||
console.log("entryHtml", entryHtml);
|
||||
|
||||
const blob = new Blob([entryHtml], { type: "text/html" });
|
||||
const iframeSrc = URL.createObjectURL(blob);
|
||||
|
||||
console.log("iframeSrc", iframeSrc);
|
||||
|
||||
/* const path = convertFileSrc(extensionDir, manifest.entry);
|
||||
console.log("final path", path); */
|
||||
//manifest.entry = iframeSrc;
|
||||
return iframeSrc;
|
||||
/* await join(
|
||||
path, //`file:/${extensionDirectory}`,
|
||||
manifest.entry
|
||||
); */
|
||||
// Modul-Datei laden
|
||||
//const modulePathFull = await join(basePath, manifest.main);
|
||||
/* const manifest: PluginManifest = await invoke('load_plugin', {
|
||||
manifestPath,
|
||||
}); */
|
||||
/* const iframe = document.createElement('iframe');
|
||||
iframe.src = manifest.entry;
|
||||
iframe.setAttribute('sandbox', 'allow-scripts');
|
||||
iframe.style.width = '100%';
|
||||
iframe.style.height = '100%';
|
||||
iframe.style.border = 'none'; */
|
||||
/* const addonApi = {
|
||||
db_execute: async (sql: string, params: string[] = []) => {
|
||||
return invoke('db_execute', {
|
||||
addonId: manifest.name,
|
||||
sql,
|
||||
params,
|
||||
});
|
||||
},
|
||||
db_select: async (sql: string, params: string[] = []) => {
|
||||
return invoke('db_select', {
|
||||
addonId: manifest.name,
|
||||
sql,
|
||||
params,
|
||||
});
|
||||
},
|
||||
}; */
|
||||
/* iframe.onload = () => {
|
||||
iframe.contentWindow?.postMessage(
|
||||
{ type: 'init', payload: addonApi },
|
||||
'*'
|
||||
);
|
||||
};
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source === iframe.contentWindow) {
|
||||
const { type } = event.data;
|
||||
if (type === 'ready') {
|
||||
console.log(`Plugin ${manifest.name} ist bereit`);
|
||||
}
|
||||
}
|
||||
}); */
|
||||
/* plugins.value.push({ name: manifest.name, entry: manifest.entry });
|
||||
|
||||
console.log(`Plugin ${manifest.name} geladen.`); */
|
||||
return `haex-extension://${hexName}`
|
||||
} catch (error) {
|
||||
console.error("ERROR extensionEntry", error);
|
||||
console.error('ERROR extensionEntry', error)
|
||||
}
|
||||
},
|
||||
null,
|
||||
{ lazy: true }
|
||||
);
|
||||
{ lazy: true },
|
||||
)
|
||||
|
||||
const loadExtensionsAsync = async () => {
|
||||
const { currentVault } = storeToRefs(useVaultStore());
|
||||
const { currentVault } = storeToRefs(useVaultStore())
|
||||
|
||||
const extensions = (await currentVault.value?.drizzle.select().from(haexExtensions)) ?? [];
|
||||
const extensions =
|
||||
(await currentVault.value?.drizzle.select().from(haexExtensions)) ?? []
|
||||
|
||||
//if (!extensions?.length) return false;
|
||||
|
||||
const installedExtensions = await filterAsync(extensions, isExtensionInstalledAsync);
|
||||
console.log("loadExtensionsAsync installedExtensions", installedExtensions);
|
||||
const installedExtensions = await filterAsync(
|
||||
extensions,
|
||||
isExtensionInstalledAsync,
|
||||
)
|
||||
console.log('loadExtensionsAsync installedExtensions', installedExtensions)
|
||||
|
||||
availableExtensions.value =
|
||||
extensions.map((extension) => ({
|
||||
id: extension.id,
|
||||
name: extension.name ?? "",
|
||||
icon: extension.icon ?? "",
|
||||
author: extension.author ?? "",
|
||||
version: extension.version ?? "",
|
||||
name: extension.name ?? '',
|
||||
icon: extension.icon ?? '',
|
||||
author: extension.author ?? '',
|
||||
version: extension.version ?? '',
|
||||
enabled: extension.enabled ? true : false,
|
||||
installed: installedExtensions.includes(extension),
|
||||
})) ?? [];
|
||||
})) ?? []
|
||||
|
||||
console.log("loadExtensionsAsync", availableExtensions.value);
|
||||
return true;
|
||||
};
|
||||
console.log('loadExtensionsAsync', availableExtensions.value)
|
||||
return true
|
||||
}
|
||||
|
||||
const removeExtensionAsync = async (id: string, version: string) => {
|
||||
try {
|
||||
console.log("remove extension", id, version);
|
||||
await removeExtensionFromVaultAsync(id, version);
|
||||
await removeExtensionFilesAsync(id, version);
|
||||
console.log('remove extension', id, version)
|
||||
await removeExtensionFromVaultAsync(id, version)
|
||||
await removeExtensionFilesAsync(id, version)
|
||||
} catch (error) {
|
||||
throw new Error(JSON.stringify(error));
|
||||
throw new Error(JSON.stringify(error))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
availableExtensions,
|
||||
@ -445,48 +416,63 @@ export const useExtensionsStore = defineStore("extensionsStore", () => {
|
||||
extensionLinks,
|
||||
installAsync,
|
||||
isActive,
|
||||
isExtensionInstalledAsync,
|
||||
loadExtensionsAsync,
|
||||
readManifestFileAsync,
|
||||
removeExtensionAsync,
|
||||
getExtensionPathAsync,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
const getMimeType = (file: string) => {
|
||||
if (file.endsWith(".css")) return "text/css";
|
||||
if (file.endsWith(".js")) return "text/javascript";
|
||||
return "text/plain";
|
||||
};
|
||||
/* const getMimeType = (file: string) => {
|
||||
if (file.endsWith('.css')) return 'text/css'
|
||||
if (file.endsWith('.js')) return 'text/javascript'
|
||||
return 'text/plain'
|
||||
} */
|
||||
|
||||
const removeExtensionFromVaultAsync = async (id: string | null, version: string | null) => {
|
||||
if (!id) throw new Error("Erweiterung kann nicht gelöscht werden. Es keine ID angegeben");
|
||||
const removeExtensionFromVaultAsync = async (
|
||||
id: string | null,
|
||||
version: string | null,
|
||||
) => {
|
||||
if (!id)
|
||||
throw new Error(
|
||||
'Erweiterung kann nicht gelöscht werden. Es keine ID angegeben',
|
||||
)
|
||||
|
||||
if (!version)
|
||||
throw new Error("Erweiterung kann nicht gelöscht werden. Es wurde keine Version angegeben");
|
||||
throw new Error(
|
||||
'Erweiterung kann nicht gelöscht werden. Es wurde keine Version angegeben',
|
||||
)
|
||||
|
||||
const { currentVault } = useVaultStore();
|
||||
const { currentVault } = useVaultStore()
|
||||
const removedExtensions = await currentVault?.drizzle
|
||||
.delete(haexExtensions)
|
||||
.where(and(eq(haexExtensions.id, id), eq(haexExtensions.version, version)));
|
||||
return removedExtensions;
|
||||
};
|
||||
.where(and(eq(haexExtensions.id, id), eq(haexExtensions.version, version)))
|
||||
return removedExtensions
|
||||
}
|
||||
|
||||
const removeExtensionFilesAsync = async (id: string | null, version: string | null) => {
|
||||
const removeExtensionFilesAsync = async (
|
||||
id: string | null,
|
||||
version: string | null,
|
||||
) => {
|
||||
try {
|
||||
const { getExtensionPathAsync } = useExtensionsStore();
|
||||
if (!id) throw new Error("Erweiterung kann nicht gelöscht werden. Es keine ID angegeben");
|
||||
const { getExtensionPathAsync } = useExtensionsStore()
|
||||
if (!id)
|
||||
throw new Error(
|
||||
'Erweiterung kann nicht gelöscht werden. Es keine ID angegeben',
|
||||
)
|
||||
|
||||
if (!version)
|
||||
throw new Error("Erweiterung kann nicht gelöscht werden. Es wurde keine Version angegeben");
|
||||
throw new Error(
|
||||
'Erweiterung kann nicht gelöscht werden. Es wurde keine Version angegeben',
|
||||
)
|
||||
|
||||
const extensionDirectory = await getExtensionPathAsync(id, version);
|
||||
const extensionDirectory = await getExtensionPathAsync(id, version)
|
||||
await remove(extensionDirectory, {
|
||||
recursive: true,
|
||||
});
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("ERROR removeExtensionFilesAsync", error);
|
||||
throw new Error(JSON.stringify(error));
|
||||
console.error('ERROR removeExtensionFilesAsync', error)
|
||||
throw new Error(JSON.stringify(error))
|
||||
}
|
||||
};
|
||||
|
||||
const replaceUrlWithAssetProtocolAsync = () => { };
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
export interface IHaexNotication {
|
||||
title: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
image?: string;
|
||||
alt?: string;
|
||||
title: string
|
||||
description?: string
|
||||
icon?: string
|
||||
image?: string
|
||||
alt?: string
|
||||
date: Date
|
||||
}
|
||||
|
||||
export const useNotificationStore = defineStore('notificationStore', () => {
|
||||
@ -13,10 +14,11 @@ export const useNotificationStore = defineStore('notificationStore', () => {
|
||||
alt: 'test',
|
||||
description: 'Ganz was tolles',
|
||||
image: 'https://cdn.flyonui.com/fy-assets/avatar/avatar-1.png',
|
||||
date: new Date(),
|
||||
},
|
||||
]);
|
||||
])
|
||||
|
||||
return {
|
||||
notifications,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
import type { RouteLocationAsRelativeGeneric } from "vue-router";
|
||||
import type { RouteLocationAsRelativeGeneric } from 'vue-router'
|
||||
|
||||
export interface ISidebarItem {
|
||||
name: string;
|
||||
icon: string;
|
||||
tooltip?: string;
|
||||
id: string;
|
||||
to?: RouteLocationAsRelativeGeneric;
|
||||
iconType?: "icon" | "svg";
|
||||
name: string
|
||||
icon: string
|
||||
tooltip?: string
|
||||
id: string
|
||||
to?: RouteLocationAsRelativeGeneric
|
||||
iconType?: 'icon' | 'svg'
|
||||
}
|
||||
|
||||
export const useSidebarStore = defineStore("sidebarStore", () => {
|
||||
const isVisible = ref(true);
|
||||
export const useSidebarStore = defineStore('sidebarStore', () => {
|
||||
const isVisible = ref(true)
|
||||
|
||||
const menu = ref<ISidebarItem[]>([
|
||||
{
|
||||
id: "haex-extensions-add",
|
||||
name: "Haex Extensions",
|
||||
icon: "gg:extension",
|
||||
to: { name: "extensionOverview" },
|
||||
id: 'haex-pass',
|
||||
name: 'HaexPass',
|
||||
icon: 'mdi:safe',
|
||||
to: { name: 'haexpassOverview' },
|
||||
},
|
||||
]);
|
||||
{
|
||||
id: 'haex-extensions',
|
||||
name: 'Haex Extensions',
|
||||
icon: 'gg:extension',
|
||||
to: { name: 'extensionOverview' },
|
||||
},
|
||||
])
|
||||
|
||||
/* const loadAsync = async (id: string) => {
|
||||
extensions.value.some(async (extension) => {
|
||||
@ -36,5 +42,5 @@ export const useSidebarStore = defineStore("sidebarStore", () => {
|
||||
menu,
|
||||
isVisible,
|
||||
//loadAsync,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,66 +1,76 @@
|
||||
|
||||
import * as schema from "@/../src-tauri/database/schemas/vault";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { platform } from "@tauri-apps/plugin-os";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { drizzle, SqliteRemoteDatabase } from "drizzle-orm/sqlite-proxy";
|
||||
import * as schema from '@/../src-tauri/database/schemas/vault'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy'
|
||||
import { drizzle } from 'drizzle-orm/sqlite-proxy'
|
||||
|
||||
interface IVault {
|
||||
name: string;
|
||||
drizzle: SqliteRemoteDatabase<typeof schema>;
|
||||
name: string
|
||||
drizzle: SqliteRemoteDatabase<typeof schema>
|
||||
}
|
||||
interface IOpenVaults {
|
||||
[vaultId: string]: IVault;
|
||||
[vaultId: string]: IVault
|
||||
}
|
||||
|
||||
export const useVaultStore = defineStore("vaultStore", () => {
|
||||
|
||||
export const useVaultStore = defineStore('vaultStore', () => {
|
||||
const currentVaultId = computed<string | undefined>({
|
||||
get: () => getSingleRouteParam(useRouter().currentRoute.value.params.vaultId),
|
||||
get: () =>
|
||||
getSingleRouteParam(useRouter().currentRoute.value.params.vaultId),
|
||||
set: (newVaultId) => {
|
||||
useRouter().currentRoute.value.params.vaultId = newVaultId ?? "";
|
||||
useRouter().currentRoute.value.params.vaultId = newVaultId ?? ''
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const defaultVaultName = ref("HaexHub")
|
||||
const defaultVaultName = ref('HaexHub')
|
||||
const currentVaultName = ref(defaultVaultName.value)
|
||||
|
||||
const read_only = computed<boolean>({
|
||||
get: () => {
|
||||
console.log("query showSidebar", useRouter().currentRoute.value.query.readonly);
|
||||
console.log(
|
||||
'query showSidebar',
|
||||
useRouter().currentRoute.value.query.readonly,
|
||||
)
|
||||
return JSON.parse(
|
||||
getSingleRouteParam(useRouter().currentRoute.value.query.readonly) || "false"
|
||||
);
|
||||
getSingleRouteParam(useRouter().currentRoute.value.query.readonly) ||
|
||||
'false',
|
||||
)
|
||||
},
|
||||
set: (readonly) => {
|
||||
const router = useRouter();
|
||||
const router = useRouter()
|
||||
router.replace({
|
||||
query: {
|
||||
...router.currentRoute.value.query,
|
||||
readonly: JSON.stringify(readonly ? true : false),
|
||||
},
|
||||
});
|
||||
})
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const openVaults = ref<IOpenVaults>({});
|
||||
const openVaults = ref<IOpenVaults>({})
|
||||
|
||||
const currentVault = computed(() => openVaults.value?.[currentVaultId.value ?? ""])
|
||||
const currentVault = computed(
|
||||
() => openVaults.value?.[currentVaultId.value ?? ''],
|
||||
)
|
||||
|
||||
|
||||
|
||||
const openAsync = async ({ path = "", password }: { path: string; password: string }) => {
|
||||
const openAsync = async ({
|
||||
path = '',
|
||||
password,
|
||||
}: {
|
||||
path: string
|
||||
password: string
|
||||
}) => {
|
||||
try {
|
||||
const result = await invoke<string>("open_encrypted_database", {
|
||||
const result = await invoke<string>('open_encrypted_database', {
|
||||
path,
|
||||
key: password,
|
||||
});
|
||||
})
|
||||
|
||||
if (result !== "success") throw new Error(result);
|
||||
if (result !== 'success') throw new Error(result)
|
||||
|
||||
const vaultId = await getVaultIdAsync(path);
|
||||
const seperator = platform() === "windows" ? "\\" : "/";
|
||||
const fileName = path.split(seperator).pop();
|
||||
const vaultId = await getVaultIdAsync(path)
|
||||
const seperator = platform() === 'windows' ? '\\' : '/'
|
||||
const fileName = path.split(seperator).pop()
|
||||
|
||||
openVaults.value = {
|
||||
...openVaults.value,
|
||||
@ -68,53 +78,65 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
name: fileName ?? path,
|
||||
drizzle: drizzle<typeof schema>(
|
||||
async (sql, params: unknown[], method) => {
|
||||
let rows: any = [];
|
||||
let results = [];
|
||||
let rows: unknown[] = []
|
||||
let results: any = []
|
||||
|
||||
// If the query is a SELECT, use the select method
|
||||
if (isSelectQuery(sql)) {
|
||||
console.log("sql_select", sql, params);
|
||||
rows = await invoke("sql_select", { sql, params }).catch((e) => {
|
||||
console.error("SQL select Error:", e, sql, params);
|
||||
return [];
|
||||
});
|
||||
console.log("select", rows);
|
||||
console.log('sql_select', sql, params)
|
||||
rows = await invoke<unknown[]>('sql_select', {
|
||||
sql,
|
||||
params,
|
||||
}).catch((e) => {
|
||||
console.error('SQL select Error:', e, sql, params)
|
||||
return []
|
||||
})
|
||||
console.log('select', rows)
|
||||
} else {
|
||||
// Otherwise, use the execute method
|
||||
rows = await invoke("sql_execute", { sql, params }).catch((e) => {
|
||||
console.error("SQL execute Error:", e, sql, params);
|
||||
return [];
|
||||
});
|
||||
return { rows: [] };
|
||||
rows = await invoke<unknown[]>('sql_execute', {
|
||||
sql,
|
||||
params,
|
||||
}).catch((e) => {
|
||||
console.error('SQL execute Error:', e, sql, params)
|
||||
return []
|
||||
})
|
||||
return { rows: [] }
|
||||
}
|
||||
|
||||
results = method === "all" ? rows : rows[0];
|
||||
results = method === 'all' ? rows : rows[0]
|
||||
|
||||
return { rows: results };
|
||||
return { rows: results }
|
||||
},
|
||||
{ schema: schema, logger: true }
|
||||
{ schema: schema, logger: true },
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const { addVaultAsync } = useLastVaultStore();
|
||||
const { addVaultAsync } = useLastVaultStore()
|
||||
await addVaultAsync({ path })
|
||||
|
||||
return vaultId;
|
||||
return vaultId
|
||||
} catch (error) {
|
||||
console.error("Error openAsync ", error);
|
||||
return false;
|
||||
console.error('Error openAsync ', error)
|
||||
return false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const refreshDatabaseAsync = async () => {
|
||||
console.log("refreshDatabaseAsync");
|
||||
console.log('refreshDatabaseAsync')
|
||||
/* if (!currentVault.value?.database.close) {
|
||||
return navigateTo(useLocaleRoute()({ name: 'vaultOpen' }));
|
||||
} */
|
||||
};
|
||||
}
|
||||
|
||||
const createAsync = async ({ path, password }: { path: string; password: string }) => {
|
||||
const createAsync = async ({
|
||||
path,
|
||||
password,
|
||||
}: {
|
||||
path: string
|
||||
password: string
|
||||
}) => {
|
||||
/* const existDb = await exists('default.db', {
|
||||
baseDir: BaseDirectory.Resource,
|
||||
}); */
|
||||
@ -122,16 +144,16 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
/* const existDb = await resolveResource('resources/default.db');
|
||||
if (!existDb) throw new Error('Keine Datenbank da');
|
||||
await copyFile(existDb, path); */
|
||||
const result = await invoke("create_encrypted_database", {
|
||||
const result = await invoke('create_encrypted_database', {
|
||||
path,
|
||||
key: password,
|
||||
});
|
||||
console.log("create_encrypted_database", result);
|
||||
return await openAsync({ path, password });
|
||||
};
|
||||
})
|
||||
console.log('create_encrypted_database', result)
|
||||
return await openAsync({ path, password })
|
||||
}
|
||||
|
||||
const closeAsync = async () => {
|
||||
if (!currentVaultId.value) return;
|
||||
if (!currentVaultId.value) return
|
||||
|
||||
/* if (
|
||||
typeof openVaults.value?.[currentVaultId.value]?.database?.close ===
|
||||
@ -140,8 +162,8 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
console.log('close db', openVaults.value?.[currentVaultId.value]);
|
||||
return openVaults.value?.[currentVaultId.value]?.database?.close();
|
||||
} */
|
||||
delete openVaults.value?.[currentVaultId.value];
|
||||
};
|
||||
delete openVaults.value?.[currentVaultId.value]
|
||||
}
|
||||
|
||||
const syncLocaleAsync = async () => {
|
||||
try {
|
||||
@ -154,21 +176,25 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
|
||||
if (currentLocaleRow?.[0]?.value) {
|
||||
const currentLocale = app.$i18n.availableLocales.find(
|
||||
(locale) => locale === currentLocaleRow[0].value
|
||||
(locale) => locale === currentLocaleRow[0].value,
|
||||
)
|
||||
await app.$i18n.setLocale(currentLocale ?? app.$i18n.defaultLocale)
|
||||
} else {
|
||||
await currentVault.value?.drizzle
|
||||
.insert(schema.haexSettings)
|
||||
.values({ id: crypto.randomUUID(), key: 'locale', value: app.$i18n.locale.value })
|
||||
await currentVault.value?.drizzle.insert(schema.haexSettings).values({
|
||||
id: crypto.randomUUID(),
|
||||
key: 'locale',
|
||||
value: app.$i18n.locale.value,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("ERROR syncLocaleAsync", error)
|
||||
console.log('ERROR syncLocaleAsync', error)
|
||||
}
|
||||
}
|
||||
|
||||
const syncThemeAsync = async () => {
|
||||
const { availableThemes, defaultTheme, currentTheme } = storeToRefs(useUiStore())
|
||||
const { availableThemes, defaultTheme, currentTheme } = storeToRefs(
|
||||
useUiStore(),
|
||||
)
|
||||
const currentThemeRow = await currentVault.value?.drizzle
|
||||
.select()
|
||||
.from(schema.haexSettings)
|
||||
@ -176,7 +202,7 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
|
||||
if (currentThemeRow?.[0]?.value) {
|
||||
const theme = availableThemes.value.find(
|
||||
(theme) => theme.name === currentThemeRow[0].value
|
||||
(theme) => theme.name === currentThemeRow[0].value,
|
||||
)
|
||||
currentTheme.value = theme ?? defaultTheme.value
|
||||
} else {
|
||||
@ -195,7 +221,8 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
.where(eq(schema.haexSettings.key, 'vaultName'))
|
||||
|
||||
if (currentVaultNameRow?.[0]?.value) {
|
||||
currentVaultName.value = currentVaultNameRow.at(0)?.value ?? defaultVaultName.value
|
||||
currentVaultName.value =
|
||||
currentVaultNameRow.at(0)?.value ?? defaultVaultName.value
|
||||
} else {
|
||||
await currentVault.value?.drizzle.insert(schema.haexSettings).values({
|
||||
id: crypto.randomUUID(),
|
||||
@ -206,8 +233,11 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
}
|
||||
|
||||
const updateVaultNameAsync = async (newVaultName?: string | null) => {
|
||||
console.log("set new vaultName", newVaultName)
|
||||
return currentVault.value?.drizzle.update(schema.haexSettings).set({ value: newVaultName ?? defaultVaultName.value }).where(eq(schema.haexSettings.key, "vaultName"))
|
||||
console.log('set new vaultName', newVaultName)
|
||||
return currentVault.value?.drizzle
|
||||
.update(schema.haexSettings)
|
||||
.set({ value: newVaultName ?? defaultVaultName.value })
|
||||
.where(eq(schema.haexSettings.key, 'vaultName'))
|
||||
}
|
||||
|
||||
return {
|
||||
@ -224,24 +254,21 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
||||
syncThemeAsync,
|
||||
syncVaultNameAsync,
|
||||
updateVaultNameAsync,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
const getVaultIdAsync = async (path: string) => {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(path);
|
||||
const encoder = new TextEncoder()
|
||||
const data = encoder.encode(path)
|
||||
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array
|
||||
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); // convert bytes to hex string
|
||||
console.log("vaultId", hashHex);
|
||||
return hashHex;
|
||||
};
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer)) // convert buffer to byte array
|
||||
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('') // convert bytes to hex string
|
||||
console.log('vaultId', hashHex)
|
||||
return hashHex
|
||||
}
|
||||
|
||||
const isSelectQuery = (sql: string) => {
|
||||
const selectRegex = /^\s*SELECT\b/i;
|
||||
return selectRegex.test(sql);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const selectRegex = /^\s*SELECT\b/i
|
||||
return selectRegex.test(sql)
|
||||
}
|
||||
|
||||
@ -1,63 +1,63 @@
|
||||
import { load, Store } from '@tauri-apps/plugin-store';
|
||||
import { load } from '@tauri-apps/plugin-store'
|
||||
|
||||
interface ILastVault {
|
||||
lastUsed: Date;
|
||||
name: string;
|
||||
path: string;
|
||||
lastUsed: Date
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
|
||||
export const useLastVaultStore = defineStore('lastVaultStore', () => {
|
||||
const {
|
||||
public: { haexVault },
|
||||
} = useRuntimeConfig();
|
||||
} = useRuntimeConfig()
|
||||
|
||||
const lastVaults = ref<ILastVault[]>([]);
|
||||
const lastVaults = ref<ILastVault[]>([])
|
||||
|
||||
const keyName = 'lastVaults';
|
||||
const keyName = 'lastVaults'
|
||||
|
||||
const getStoreAsync = async () => {
|
||||
return await load(haexVault.lastVaultFileName);
|
||||
};
|
||||
return await load(haexVault.lastVaultFileName)
|
||||
}
|
||||
|
||||
const syncLastVaultsAsync = async () => {
|
||||
const store = await getStoreAsync();
|
||||
const store = await getStoreAsync()
|
||||
lastVaults.value =
|
||||
(await store.get<ILastVault[]>(keyName))?.sort(
|
||||
(a, b) => +new Date(b.lastUsed) - +new Date(a.lastUsed)
|
||||
) ?? [];
|
||||
(a, b) => +new Date(b.lastUsed) - +new Date(a.lastUsed),
|
||||
) ?? []
|
||||
|
||||
return lastVaults.value;
|
||||
};
|
||||
return lastVaults.value
|
||||
}
|
||||
|
||||
const addVaultAsync = async ({
|
||||
name,
|
||||
path,
|
||||
}: {
|
||||
name?: string;
|
||||
path: string;
|
||||
name?: string
|
||||
path: string
|
||||
}) => {
|
||||
if (!lastVaults.value) await syncLastVaultsAsync();
|
||||
if (!lastVaults.value) await syncLastVaultsAsync()
|
||||
|
||||
const saveName = name || getFileNameFromPath(path);
|
||||
lastVaults.value = lastVaults.value.filter((vault) => vault.path !== path);
|
||||
lastVaults.value.push({ lastUsed: new Date(), name: saveName, path });
|
||||
await saveLastVaultsAsync();
|
||||
};
|
||||
const saveName = name || getFileNameFromPath(path)
|
||||
lastVaults.value = lastVaults.value.filter((vault) => vault.path !== path)
|
||||
lastVaults.value.push({ lastUsed: new Date(), name: saveName, path })
|
||||
await saveLastVaultsAsync()
|
||||
}
|
||||
|
||||
const removeVaultAsync = async (vaultPath: string) => {
|
||||
console.log('remove', vaultPath, lastVaults.value);
|
||||
console.log('remove', vaultPath, lastVaults.value)
|
||||
lastVaults.value = lastVaults.value.filter(
|
||||
(vault) => vault.path !== vaultPath
|
||||
);
|
||||
await saveLastVaultsAsync();
|
||||
};
|
||||
(vault) => vault.path !== vaultPath,
|
||||
)
|
||||
await saveLastVaultsAsync()
|
||||
}
|
||||
|
||||
const saveLastVaultsAsync = async () => {
|
||||
const store = await getStoreAsync();
|
||||
console.log('save lastVaults', keyName, lastVaults.value);
|
||||
await store.set(keyName, lastVaults.value);
|
||||
await syncLastVaultsAsync();
|
||||
};
|
||||
const store = await getStoreAsync()
|
||||
console.log('save lastVaults', keyName, lastVaults.value)
|
||||
await store.set(keyName, lastVaults.value)
|
||||
await syncLastVaultsAsync()
|
||||
}
|
||||
|
||||
return {
|
||||
addVaultAsync,
|
||||
@ -65,16 +65,16 @@ export const useLastVaultStore = defineStore('lastVaultStore', () => {
|
||||
lastVaults,
|
||||
removeVaultAsync,
|
||||
saveLastVaultsAsync,
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
const getFileNameFromPath = (path: string) => {
|
||||
const lastBackslashIndex = path.lastIndexOf('\\');
|
||||
const lastSlashIndex = path.lastIndexOf('/');
|
||||
const lastBackslashIndex = path.lastIndexOf('\\')
|
||||
const lastSlashIndex = path.lastIndexOf('/')
|
||||
|
||||
const lastIndex = Math.max(lastBackslashIndex, lastSlashIndex);
|
||||
const lastIndex = Math.max(lastBackslashIndex, lastSlashIndex)
|
||||
|
||||
const fileName = path.substring(lastIndex + 1);
|
||||
const fileName = path.substring(lastIndex + 1)
|
||||
|
||||
return fileName;
|
||||
};
|
||||
return fileName
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user