add notifications

This commit is contained in:
2025-06-03 00:13:45 +02:00
parent 091a2123bb
commit 0f09bf8436
27 changed files with 2105 additions and 1799 deletions

View File

@ -1,10 +1,10 @@
import { defineConfig } from 'drizzle-kit';
import { defineConfig } from 'drizzle-kit'
export default defineConfig({
schema: './src/database/schemas/**.ts',
out: './src/database/migrations',
schema: './src-tauri/database/schemas/**.ts',
out: './src-tauri/database/migrations',
dialect: 'sqlite',
dbCredentials: {
url: './src/database/default.db',
url: './src-tauri/database/vault.db',
},
});
})

View File

@ -2,10 +2,6 @@ import tailwindcss from '@tailwindcss/vite'
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
app: {
baseURL: './',
},
modules: [
'nuxt-zod-i18n',
'@nuxtjs/i18n',

View File

@ -16,35 +16,36 @@
"eslint:fix": "eslint --fix"
},
"dependencies": {
"@libsql/client": "^0.15.7",
"@libsql/client": "^0.15.8",
"@nuxt/eslint": "1.4.1",
"@nuxt/icon": "^1.13.0",
"@nuxtjs/i18n": "^9.5.4",
"@nuxtjs/i18n": "^9.5.5",
"@pinia/nuxt": "^0.11.0",
"@tailwindcss/vite": "^4.1.7",
"@tailwindcss/vite": "^4.1.8",
"@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-dialog": "^2.2.2",
"@tauri-apps/plugin-fs": "^2.3.0",
"@tauri-apps/plugin-http": "~2.4.4",
"@tauri-apps/plugin-notification": "~2.2.2",
"@tauri-apps/plugin-opener": "^2.2.7",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-sql": "~2.2.0",
"@tauri-apps/plugin-store": "^2.2.0",
"@vueuse/core": "^13.2.0",
"@vueuse/nuxt": "^13.2.0",
"@vueuse/core": "^13.3.0",
"@vueuse/nuxt": "^13.3.0",
"drizzle-orm": "^0.43.1",
"eslint": "^9.27.0",
"eslint": "^9.28.0",
"flyonui": "^2.2.0",
"nuxt": "^3.17.4",
"nuxt-snackbar": "1.3.0",
"nuxt-zod-i18n": "^1.11.5",
"tailwindcss": "^4.1.7",
"vue": "^3.5.14",
"tailwindcss": "^4.1.8",
"vue": "^3.5.16",
"vue-router": "^4.5.1",
"zod": "^3.25.21"
"zod": "^3.25.42"
},
"devDependencies": {
"@iconify/json": "^2.2.340",
"@iconify/json": "^2.2.343",
"@iconify/tailwind4": "^1.0.6",
"@tauri-apps/cli": "^2.5.0",
"drizzle-kit": "^0.31.1",

3242
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

69
src-tauri/Cargo.lock generated
View File

@ -1548,6 +1548,7 @@ dependencies = [
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-http",
"tauri-plugin-notification",
"tauri-plugin-opener",
"tauri-plugin-os",
"tauri-plugin-store",
@ -2180,6 +2181,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mac-notification-sys"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b95dfb34071d1592b45622bf93e315e3a72d414b6782aca9a015c12bec367ef"
dependencies = [
"cc",
"objc2 0.6.0",
"objc2-foundation 0.3.0",
"time",
]
[[package]]
name = "markup5ever"
version = "0.11.0"
@ -2328,6 +2341,20 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "notify-rust"
version = "4.11.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6442248665a5aa2514e794af3b39661a8e73033b1cc5e59899e1276117ee4400"
dependencies = [
"futures-lite",
"log",
"mac-notification-sys",
"serde",
"tauri-winrt-notification",
"zbus",
]
[[package]]
name = "num-conv"
version = "0.1.0"
@ -2889,7 +2916,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
dependencies = [
"base64 0.22.1",
"indexmap 2.8.0",
"quick-xml",
"quick-xml 0.32.0",
"serde",
"time",
]
@ -3044,6 +3071,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.37.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
dependencies = [
"memchr",
]
[[package]]
name = "quinn"
version = "0.11.7"
@ -4259,6 +4295,25 @@ dependencies = [
"urlpattern",
]
[[package]]
name = "tauri-plugin-notification"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c474c7cc524385e682ccc1e149e13913a66fd8586ac4c2319cf01b78f070d309"
dependencies = [
"log",
"notify-rust",
"rand 0.8.5",
"serde",
"serde_json",
"serde_repr",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
"time",
"url",
]
[[package]]
name = "tauri-plugin-opener"
version = "2.2.6"
@ -4412,6 +4467,18 @@ dependencies = [
"toml",
]
[[package]]
name = "tauri-winrt-notification"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9"
dependencies = [
"quick-xml 0.37.5",
"thiserror 2.0.12",
"windows 0.61.1",
"windows-version",
]
[[package]]
name = "tempfile"
version = "3.19.1"

View File

@ -40,4 +40,5 @@ tauri-plugin-opener = "2.2"
tauri-plugin-os = "2"
tauri-plugin-store = "2"
tauri-plugin-http = "2.4"
tauri-plugin-notification = "2"
#tauri-plugin-sql = { version = "2", features = ["sqlite"] }

View File

@ -16,6 +16,8 @@
"dialog:default",
"fs:allow-appdata-read-recursive",
"fs:allow-appdata-write-recursive",
"fs:allow-appconfig-read-recursive",
"fs:allow-appconfig-write-recursive",
"fs:allow-read-file",
"fs:allow-resource-read-recursive",
"fs:default",
@ -26,6 +28,10 @@
"opener:default",
"os:default",
"os:allow-hostname",
"store:default"
"store:default",
"notification:default",
"notification:allow-notify",
"notification:allow-create-channel",
"notification:allow-list-channels"
]
}

View File

@ -0,0 +1,11 @@
CREATE TABLE `haex_notofications` (
`id` text PRIMARY KEY NOT NULL,
`title` text,
`text` text,
`type` text NOT NULL,
`read` integer,
`date` text,
`image` text,
`alt` text,
`icon` text
);

View File

@ -0,0 +1,251 @@
{
"version": "6",
"dialect": "sqlite",
"id": "5f413421-18a5-4c1b-9c5b-99f574b10126",
"prevId": "ea3507ca-77bc-4f3c-a605-8426614f5803",
"tables": {
"haex_extensions": {
"name": "haex_extensions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"author": {
"name": "author",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"url": {
"name": "url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_extensions_permissions": {
"name": "haex_extensions_permissions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"extension_id": {
"name": "extension_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"resource": {
"name": "resource",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"operation": {
"name": "operation",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"path": {
"name": "path",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_extensions_permissions_extension_id_resource_operation_path_unique": {
"name": "haex_extensions_permissions_extension_id_resource_operation_path_unique",
"columns": [
"extension_id",
"resource",
"operation",
"path"
],
"isUnique": true
}
},
"foreignKeys": {
"haex_extensions_permissions_extension_id_haex_extensions_id_fk": {
"name": "haex_extensions_permissions_extension_id_haex_extensions_id_fk",
"tableFrom": "haex_extensions_permissions",
"tableTo": "haex_extensions",
"columnsFrom": [
"extension_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_notofications": {
"name": "haex_notofications",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"text": {
"name": "text",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"read": {
"name": "read",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"date": {
"name": "date",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"alt": {
"name": "alt",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_settings": {
"name": "haex_settings",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -22,6 +22,13 @@
"when": 1747583956679,
"tag": "0002_married_bushwacker",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1748873820060,
"tag": "0003_familiar_doctor_faustus",
"breakpoints": true
}
]
}

View File

@ -11,6 +11,8 @@ export const haexSettings = sqliteTable('haex_settings', {
key: text(),
value: text(),
})
export type InsertHaexSettings = typeof haexSettings.$inferInsert
export type SelectHaexSettings = typeof haexSettings.$inferSelect
export const haexExtensions = sqliteTable('haex_extensions', {
id: text().primaryKey(),
@ -21,6 +23,8 @@ export const haexExtensions = sqliteTable('haex_extensions', {
url: text(),
version: text(),
})
export type InsertHaexExtensions = typeof haexExtensions.$inferInsert
export type SelectHaexExtensions = typeof haexExtensions.$inferSelect
export const haexExtensionsPermissions = sqliteTable(
'haex_extensions_permissions',
@ -37,14 +41,21 @@ export const haexExtensionsPermissions = sqliteTable(
unique().on(table.extensionId, table.resource, table.operation, table.path),
],
)
export type InsertHaexSettings = typeof haexSettings.$inferInsert
export type SelectHaexSettings = typeof haexSettings.$inferSelect
export type InsertHaexExtensions = typeof haexExtensions.$inferInsert
export type SelectHaexExtensions = typeof haexExtensions.$inferSelect
export type InsertHaexExtensionsPermissions =
typeof haexExtensionsPermissions.$inferInsert
export type SelectHaexExtensionsPermissions =
typeof haexExtensionsPermissions.$inferSelect
export const haexNotifications = sqliteTable('haex_notofications', {
id: text().primaryKey(),
title: text(),
text: text(),
type: text({ enum: ['error', 'success', 'warning', 'info'] }).notNull(),
read: integer({ mode: 'boolean' }),
date: text(),
image: text(),
alt: text(),
icon: text(),
})
export type InsertHaexNotifications = typeof haexNotifications.$inferInsert
export type SelectHaexNotifications = typeof haexNotifications.$inferSelect

Binary file not shown.

View File

@ -4,11 +4,12 @@ pub mod core;
use rusqlite::{Connection, OpenFlags, Result as RusqliteResult};
use serde_json::Value as JsonValue;
use std::fs;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use tauri::utils::resources::Resource;
use tauri::{path::BaseDirectory, AppHandle, Manager, State, Wry};
use tokio::io::join;
use tauri_plugin_fs::FsExt;
pub struct DbConnection(pub Mutex<Option<Connection>>);
@ -31,6 +32,18 @@ pub async fn sql_execute(
core::execute(sql, params, &state).await
}
// remember to call `.manage(MyState::default())`
#[tauri::command]
pub fn test(app_handle: AppHandle) -> Result<String, String> {
let resource_path = app_handle
.path()
.resolve("database/vault.db", BaseDirectory::Resource)
.map_err(|e| format!("Fehler {}", e));
//let file = app_handle.fs().open(resource_path, {}).unwrap().read();
Ok(String::from(resource_path.unwrap().to_string_lossy()))
/* std::fs::exists(String::from(resource_path.unwrap().to_string_lossy()))
.map_err(|e| format!("Fehler: {}", e)) */
}
/// Erstellt eine verschlüsselte Datenbank
#[tauri::command]
pub fn create_encrypted_database(

View File

@ -199,7 +199,11 @@ pub fn extension_protocol_handler<R: Runtime>(
let segments_iter = path_str.split('/').filter(|s| !s.is_empty());
let resource_segments: Vec<&str> = segments_iter.collect();
let raw_asset_path = resource_segments.join("/");
let asset_to_load = if raw_asset_path.is_empty() { "index.html"} else {&raw_asset_path};
let asset_to_load = if raw_asset_path.is_empty() {
"index.html"
} else {
&raw_asset_path
};
match process_hex_encoded_json(&host) {
Ok(info) => {

View File

@ -12,6 +12,7 @@ pub fn run() {
let protocol_name = "haex-extension";
tauri::Builder::default()
.plugin(tauri_plugin_notification::init())
.register_uri_scheme_protocol(protocol_name, move |context, request| {
match extension::core::extension_protocol_handler(&context, &request) {
Ok(response) => response, // Wenn der Handler Ok ist, gib die Response direkt zurück
@ -58,7 +59,8 @@ pub fn run() {
database::sql_select,
extension::database::extension_sql_execute,
extension::database::extension_sql_select,
extension::copy_directory //browser::create_tab
extension::copy_directory,
database::test
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

View File

@ -29,7 +29,8 @@
"connect-src": [
"'self'",
"http://tauri.localhost",
"ipc:http://ipc.localhost"
"ipc:",
"http://ipc.localhost"
],
"img-src": ["'self'", "http://tauri.localhost", "data:", "blob:"],
"font-src": ["'self'", "http://tauri.localhost"],

View File

@ -1,36 +1,42 @@
<template>
<UiDropdown activator-class="btn btn-text btn-circle " dropdown-class="[--offset:20]">
<UiDropdown offset="[--offset:20]">
<template #activator>
<div class="size-9.5 rounded-full items-center justify-center text-base-content text-base">
<Icon name="mdi:format-list-bulleted" class="size-full p-2" />
<div
class="size-9.5 rounded-full items-center justify-center text-base-content text-base"
>
<Icon
name="mdi:format-list-bulleted"
class="size-full p-2"
/>
</div>
</template>
<!-- <ul class="dropdown-menu dropdown-open:opacity-100 hidden min-w-60" role="menu" aria-orientation="vertical"
aria-labelledby="dropdown-avatar"> -->
<template #items>
<li>
<NuxtLinkLocale class="dropdown-item" :to="{ name: 'haexSettings' }">
<span class="icon-[tabler--settings]"/>
<NuxtLinkLocale
class="dropdown-item"
:to="{ name: 'haexSettings' }"
>
<span class="icon-[tabler--settings]" />
{{ t('settings') }}
</NuxtLinkLocale>
</li>
<li class="dropdown-footer gap-2">
<button class="btn btn-error btn-soft btn-block" @click="onVaultCloseAsync">
<span class="icon-[tabler--logout]"/>
<button
class="btn btn-error btn-soft btn-block"
@click="onVaultCloseAsync"
>
<span class="icon-[tabler--logout]" />
{{ t('vault.close') }}
</button>
</li>
</template>
<!--
</ul> -->
</UiDropdown>
</template>

View File

@ -1,5 +1,8 @@
<template>
<div class="dropdown relative inline-flex">
<div
class="dropdown relative inline-flex"
:class="offset"
>
<button
:id
class="dropdown-toggle"
@ -42,13 +45,12 @@
</template>
<script setup lang="ts" generic="T">
import type { HSDropdown } from 'flyonui/flyonui'
const { itemIs = 'li' } = defineProps<{
const { itemIs = 'li', offset = '[--offset:0]' } = defineProps<{
label?: string
items?: T[]
itemIs?: string
activatorClass?: string
offset?: string
}>()
defineOptions({
@ -58,4 +60,6 @@ defineOptions({
defineEmits<{ select: [T] }>()
const id = useId()
//const offset = '[--offset:30]'
</script>

View File

@ -18,7 +18,7 @@
<UiTextGradient>HaexVault</UiTextGradient>
</template>
</i18n-t>
<p class="text-sm">{{ path }}</p>
<p class="text-sm">{{ database.path }}</p>
</template>
<template #trigger>
@ -63,6 +63,11 @@ const database = reactive<{
type: 'password',
})
watch(
() => props.path,
() => (database.path = props.path),
)
const initDatabase = () => {
database.name = ''
database.password = ''

View File

@ -37,7 +37,7 @@
<div class="navbar-end flex items-center gap-4 me-4">
<div
class="dropdown relative inline-flex [--auto-close:inside] [--offset:8] [--placement:bottom-end]"
class="dropdown relative inline-flex [--auto-close:inside] [--offset:20] [--placement:bottom-end]"
>
<button
id="dropdown-scrollable"
@ -73,7 +73,7 @@
>
<div
v-for="notification in notifications"
:key="notification.date.toDateString()"
:key="notification.id"
class="dropdown-item"
>
<div class="avatar">
@ -94,7 +94,7 @@
{{ notification.title }}
</h6>
<small class="text-base-content/50 truncate">
{{ notification.description }}
{{ notification.text }}
</small>
</div>
</div>

View File

@ -4,11 +4,6 @@
<UiDropdownLocale @select="setLocale" />
</div>
<div class="flex flex-col justify-center items-center gap-5 max-w-3xl">
<!-- <img
:src="convertFileSrc('/logo.svg', 'http')"
class="bg-primary p-3 size-16 rounded-full"
alt="HaexVault Logo"
/> -->
<UiLogoHaexhub class="bg-primary p-3 size-16 rounded-full" />
<span
class="flex flex-wrap font-bold text-pretty text-xl gap-2 justify-center"
@ -26,8 +21,6 @@
v-model:open="passwordPromptOpen"
:path="vaultPath"
/>
<UiButton @click="refresh">Refresh</UiButton>
</div>
<div
@ -83,7 +76,6 @@
<script setup lang="ts">
import { UiLogoHaexhub } from '#components'
import { convertFileSrc } from '@tauri-apps/api/core'
import { openUrl } from '@tauri-apps/plugin-opener'
const refresh = () => location.reload()

View File

@ -14,8 +14,10 @@ definePageMeta({
})
const extensionStore = useExtensionsStore()
const { readNotificationsAsync } = useNotificationStore()
onMounted(async () => {
await extensionStore.loadExtensionsAsync()
await readNotificationsAsync()
})
</script>

View File

@ -26,6 +26,20 @@
</template>
</UiInput>
</div>
<div class="p-2">{{ t('notifications.label') }}</div>
<div class="flex items-center">
<input
type="checkbox"
class="switch switch-primary"
:checked="isNotificationAllowed"
readonly
/>
{{ isNotificationAllowed }}
<UiButton @click="requestNotificationPermissionAsync">
{{ t('notifications.requestPermission') }}
</UiButton>
</div>
</div>
</template>
@ -71,6 +85,10 @@ const onSetVaultNameAsync = async () => {
add({ text: t('vaultName.update.error'), type: 'error' })
}
}
const { isNotificationAllowed } = storeToRefs(useNotificationStore())
const { requestNotificationPermissionAsync } = useNotificationStore()
//const { test } = useLastVaultStore()
</script>
<i18n lang="yaml">
@ -78,6 +96,9 @@ de:
language: Sprache
design: Design
save: Änderung speichern
notifications:
label: Benachrichtigungen
requestPermission: Benachrichtigung erlauben
vaultName:
label: Vaultname
update:
@ -87,6 +108,9 @@ en:
language: Language
design: Design
save: save changes
notifications:
label: Notifications
requestPermission: Grant Permission
vaultName:
label: Vault Name
update:

View File

@ -14,6 +14,7 @@ const logoFileName = 'icon.svg'
export const useExtensionsStore = defineStore('extensionsStore', () => {
const availableExtensions = ref<IHaexHubExtensionLink[]>([])
const { addNotificationAsync } = useNotificationStore()
const extensionLinks = computed<ISidebarItem[]>(() =>
availableExtensions.value
@ -78,6 +79,7 @@ export const useExtensionsStore = defineStore('extensionsStore', () => {
return true
} catch (error) {
console.error(error)
addNotificationAsync({ type: 'error', text: JSON.stringify(error) })
//throw error //new Error(`Keine Leseberechtigung für Ordner ${extensionDirectory}`);
}
}
@ -176,6 +178,7 @@ export const useExtensionsStore = defineStore('extensionsStore', () => {
*/
return manifest
} catch (error) {
addNotificationAsync({ type: 'error', text: JSON.stringify(error) })
console.error('ERROR readManifestFileAsync', error)
}
}
@ -218,7 +221,12 @@ export const useExtensionsStore = defineStore('extensionsStore', () => {
})
console.log('insert extensions', res)
addNotificationAsync({
type: 'success',
text: `${manifest.name} wurde installiert`,
})
} catch (error) {
addNotificationAsync({ type: 'error', text: JSON.stringify(error) })
throw error
/*
const resourcePath = await resourceDir();

View File

@ -1,24 +0,0 @@
export interface IHaexNotication {
title: string
description?: string
icon?: string
image?: string
alt?: string
date: Date
}
export const useNotificationStore = defineStore('notificationStore', () => {
const notifications = ref<IHaexNotication[]>([
{
title: 'huhu',
alt: 'test',
description: 'Ganz was tolles',
image: 'https://cdn.flyonui.com/fy-assets/avatar/avatar-1.png',
date: new Date(),
},
])
return {
notifications,
}
})

View File

@ -59,7 +59,9 @@ export const useLastVaultStore = defineStore('lastVaultStore', () => {
await syncLastVaultsAsync()
}
const test = async () => console.log('test')
return {
test,
addVaultAsync,
syncLastVaultsAsync,
lastVaults,

View File

@ -1 +1,103 @@
export const useNotificationStore = defineStore('notificationStore', () => {})
import { eq } from 'drizzle-orm'
import {
haexNotifications,
type InsertHaexNotifications,
} from '~~/src-tauri/database/schemas/vault'
import {
channels,
isPermissionGranted,
requestPermission,
sendNotification,
} from '@tauri-apps/plugin-notification'
export interface IHaexNotification {
id: string
title: string | null
text?: string | null
icon?: string | null
image?: string | null
alt?: string | null
date: string | null
type?: 'error' | 'success' | 'warning' | 'info' | null
}
export const useNotificationStore = defineStore('notificationStore', () => {
const isNotificationAllowed = ref<boolean>(false)
const requestNotificationPermissionAsync = async () => {
console.log('requestNotificationPermissionAsync')
const permission = await requestPermission()
console.log('got permission', permission)
isNotificationAllowed.value = permission === 'granted'
sendNotification({
title: 'Tauri',
body: 'Tauri is awesome!',
icon: 'dialog-information',
})
/* const existingChannels = await channels()
console.log('existingChannels', existingChannels) */
}
const test = async () => console.log('test')
const checkNotificationAsync = async () => {
isNotificationAllowed.value = await isPermissionGranted()
return isNotificationAllowed.value
}
const notifications = ref<IHaexNotification[]>([])
const readNotificationsAsync = async (read: boolean = false) => {
const { currentVault } = storeToRefs(useVaultStore())
notifications.value = await currentVault.value.drizzle
.select()
.from(haexNotifications)
.where(eq(haexNotifications.read, read))
console.log('readNotificationsAsync', notifications.value)
}
const addNotificationAsync = async (
notification: Partial<InsertHaexNotifications>,
) => {
const { currentVault } = storeToRefs(useVaultStore())
try {
const _notification: InsertHaexNotifications = {
id: crypto.randomUUID(),
type: notification.type || 'info',
alt: notification.alt,
date: new Date().toUTCString(),
icon: notification.icon,
image: notification.image,
read: notification.read || false,
text: notification.text ?? '',
title: notification.title ?? '',
}
await currentVault.value.drizzle
.insert(haexNotifications)
.values(_notification)
await readNotificationsAsync()
if (!isNotificationAllowed.value) {
const permission = await requestPermission()
isNotificationAllowed.value = permission === 'granted'
}
if (isNotificationAllowed.value) {
sendNotification({
title: _notification.title!,
body: _notification.text!,
})
}
} catch (error) {}
}
return {
notifications,
isNotificationAllowed,
checkNotificationAsync,
addNotificationAsync,
readNotificationsAsync,
requestNotificationPermissionAsync,
test,
}
})