aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-01-11 18:45:31 -0800
committerFuwn <[email protected]>2024-01-11 18:45:31 -0800
commit1b71b6a1197967271528fd0d5b9ff5fc9a1f3c26 (patch)
tree5261f5d00e22b53e89420c3c1b5fa97d60253d6e
parentrefactor(routes): move shortcuts to hooks (diff)
downloaddue.moe-1b71b6a1197967271528fd0d5b9ff5fc9a1f3c26.tar.xz
due.moe-1b71b6a1197967271528fd0d5b9ff5fc9a1f3c26.zip
feat: notifications
-rwxr-xr-xbun.lockbbin146196 -> 146577 bytes
-rw-r--r--package.json89
-rw-r--r--src/lib/Notification/Notification.svelte112
-rw-r--r--src/lib/Notification/options.ts19
-rw-r--r--src/lib/Settings/Categories/Debug.svelte26
-rw-r--r--src/routes/+layout.svelte28
6 files changed, 216 insertions, 58 deletions
diff --git a/bun.lockb b/bun.lockb
index 4ebec509..84953bea 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/package.json b/package.json
index f5282881..764d1209 100644
--- a/package.json
+++ b/package.json
@@ -1,46 +1,47 @@
{
- "name": "due.moe",
- "version": "0.0.0",
- "private": true,
- "scripts": {
- "dev": "vite dev",
- "build": "vite build",
- "preview": "vite preview",
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
- "lint": "prettier --plugin-search-dir . --check . && eslint .",
- "format": "prettier --plugin-search-dir . --write ."
- },
- "devDependencies": {
- "@sveltejs/adapter-vercel": "next",
- "@sveltejs/kit": "^1.20.4",
- "@types/fast-levenshtein": "^0.0.4",
- "@types/jsdom": "^21.1.6",
- "@types/string-similarity": "^4.0.2",
- "@typescript-eslint/eslint-plugin": "^5.45.0",
- "@typescript-eslint/parser": "^5.45.0",
- "eslint": "^8.28.0",
- "eslint-config-prettier": "^8.5.0",
- "eslint-plugin-svelte": "^2.30.0",
- "prettier": "^2.8.0",
- "prettier-plugin-svelte": "^2.10.1",
- "sass": "^1.69.7",
- "svelte": "^4.0.5",
- "svelte-check": "^3.4.3",
- "sveltekit-rate-limiter": "^0.4.2",
- "tslib": "^2.4.1",
- "typescript": "^5.0.0",
- "vite": "^4.4.2"
- },
- "type": "module",
- "dependencies": {
- "@vercel/postgres": "^0.5.1",
- "dexie": "^4.0.1-alpha.25",
- "jsdom": "^23.0.1",
- "lz-string": "^1.5.0",
- "modern-screenshot": "^4.4.33",
- "rss-parser": "^3.13.0",
- "string-similarity": "^4.0.4",
- "wanakana": "^5.3.1"
- }
+ "name": "due.moe",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --plugin-search-dir . --check . && eslint .",
+ "format": "prettier --plugin-search-dir . --write ."
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-vercel": "next",
+ "@sveltejs/kit": "^1.20.4",
+ "@types/fast-levenshtein": "^0.0.4",
+ "@types/jsdom": "^21.1.6",
+ "@types/string-similarity": "^4.0.2",
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
+ "@typescript-eslint/parser": "^5.45.0",
+ "eslint": "^8.28.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-svelte": "^2.30.0",
+ "prettier": "^2.8.0",
+ "prettier-plugin-svelte": "^2.10.1",
+ "sass": "^1.69.7",
+ "svelte": "^4.0.5",
+ "svelte-check": "^3.4.3",
+ "sveltekit-rate-limiter": "^0.4.2",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^4.4.2"
+ },
+ "type": "module",
+ "dependencies": {
+ "@vercel/postgres": "^0.5.1",
+ "dexie": "^4.0.1-alpha.25",
+ "jsdom": "^23.0.1",
+ "lz-string": "^1.5.0",
+ "modern-screenshot": "^4.4.33",
+ "rss-parser": "^3.13.0",
+ "string-similarity": "^4.0.4",
+ "svelte-notifications": "^0.9.98",
+ "wanakana": "^5.3.1"
+ }
}
diff --git a/src/lib/Notification/Notification.svelte b/src/lib/Notification/Notification.svelte
new file mode 100644
index 00000000..9612d526
--- /dev/null
+++ b/src/lib/Notification/Notification.svelte
@@ -0,0 +1,112 @@
+<script lang="ts">
+ import { onMount } from 'svelte';
+
+ export let notification: { [key: string]: any } = {};
+ export let onRemove: () => void = () => {
+ return;
+ };
+ export let removed = false;
+
+ onMount(() => setTimeout(remove, notification.duration));
+
+ const remove = () => {
+ removed = true;
+
+ setTimeout(onRemove, 150);
+ };
+</script>
+
+<div id="notification-container" class={removed ? 'fade-out' : 'fade-in'}>
+ {#if notification.description}
+ <details open id="notification">
+ <summary>{@html notification.heading}</summary>
+
+ {@html notification.description}
+
+ <br />
+
+ <div class="button-container">
+ <button on:click={remove} class="button-hide">Hide</button>
+ </div>
+ </details>
+ {:else}
+ <div class="card" id="notification">
+ {@html notification.heading}
+
+ &nbsp; &nbsp;
+
+ <div class="button-container">
+ <button on:click={remove} class="button-hide">Hide</button>
+ </div>
+ </div>
+ {/if}
+</div>
+
+<style>
+ #notification-container {
+ margin: 1rem 1rem 0 0;
+ float: right;
+ }
+
+ #notification {
+ background-color: var(--base001);
+ box-shadow: rgba(0, 0, 11, 0.2) 0px 7px 29px 0px, 0 0 0 4px var(--base0E);
+
+ widows: 100%;
+ }
+
+ .button-container {
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ #notification > div {
+ display: inline;
+ }
+
+ .button-hide {
+ float: right;
+ }
+
+ .button-container::after {
+ content: '';
+ clear: both;
+ display: table;
+ }
+
+ .fade-in {
+ animation: fadeInAnimation ease 300ms;
+ animation-iteration-count: 1;
+ animation-fill-mode: forwards;
+ }
+
+ .fade-out {
+ animation: fadeOutAnimation ease 150ms;
+ animation-iteration-count: 1;
+ animation-fill-mode: forwards;
+ }
+
+ @keyframes fadeInAnimation {
+ 100% {
+ opacity: 1;
+ }
+ 1% {
+ opacity: 0.01;
+ }
+ 0% {
+ opacity: 0;
+ }
+ }
+
+ @keyframes fadeOutAnimation {
+ 0% {
+ opacity: 1;
+ }
+ 99% {
+ opacity: 0.01;
+ }
+ 100% {
+ opacity: 0;
+ }
+ }
+</style>
diff --git a/src/lib/Notification/options.ts b/src/lib/Notification/options.ts
new file mode 100644
index 00000000..f14e0d25
--- /dev/null
+++ b/src/lib/Notification/options.ts
@@ -0,0 +1,19 @@
+type Position = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
+
+interface Options {
+ heading: string | number;
+ description: string | number | undefined;
+ position: Position;
+ duration: number;
+ id: string;
+}
+
+export const options = (preferences: { [key: string]: number | string }): Options => {
+ return {
+ position: (preferences.position || 'top-right') as Position,
+ duration: Number(preferences.duration || 3000),
+ heading: preferences.heading || 'Notification',
+ description: preferences.description || undefined,
+ id: Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
+ };
+};
diff --git a/src/lib/Settings/Categories/Debug.svelte b/src/lib/Settings/Categories/Debug.svelte
index 5f6be96b..c21b6dd7 100644
--- a/src/lib/Settings/Categories/Debug.svelte
+++ b/src/lib/Settings/Categories/Debug.svelte
@@ -1,16 +1,38 @@
<script lang="ts">
import settings from '$stores/settings';
+ import { getNotificationsContext } from 'svelte-notifications';
import SettingHint from '../SettingHint.svelte';
+ import { options } from '$lib/Notification/options';
+
+ const { addNotification } = getNotificationsContext();
</script>
-<button on:click={settings.reset}>Reset <b>ALL</b> settings</button>
+<button
+ on:click={() => {
+ settings.reset();
+ addNotification(
+ options({
+ heading: 'All settings successfully reset'
+ })
+ );
+ }}>Reset <b>ALL</b> settings</button
+>
<SettingHint lineBreak>
Resets all settings present on this page to their default values
</SettingHint>
<p />
-<button on:click={() => localStorage.clear()}>Clear <code>localStorage</code></button>
+<button
+ on:click={() => {
+ localStorage.clear();
+ addNotification(
+ options({
+ heading: '<code>localStorage</code> successfully cleared'
+ })
+ );
+ }}>Clear <code>localStorage</code></button
+>
<SettingHint lineBreak>
Resets all of your settings to their default values and clears both AniList media list and manga
data caches
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index e1df9c9d..52d1b8ba 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -10,6 +10,8 @@
import { fly } from 'svelte/transition';
import { readable, type Readable } from 'svelte/store';
import { navigating } from '$app/stores';
+ import Notifications from 'svelte-notifications';
+ import Notification from '$lib/Notification/Notification.svelte';
export let data;
@@ -99,18 +101,20 @@
<p />
- {#key data.url}
- <div
- in:fly={{
- x: way,
- duration: animationDelay,
- delay: animationDelay
- }}
- out:fly={{ x: -way, duration: animationDelay }}
- >
- <slot />
- </div>
- {/key}
+ <Notifications item={Notification} zIndex={5000}>
+ {#key data.url}
+ <div
+ in:fly={{
+ x: way,
+ duration: animationDelay,
+ delay: animationDelay
+ }}
+ out:fly={{ x: -way, duration: animationDelay }}
+ >
+ <slot />
+ </div>
+ {/key}
+ </Notifications>
</div>
<style>