+8
.idea/.gitignore
+8
.idea/.gitignore
+11
.idea/miwiwi.iml
+11
.idea/miwiwi.iml
···
1
+
<?xml version="1.0" encoding="UTF-8"?>
2
+
<module type="EMPTY_MODULE" version="4">
3
+
<component name="NewModuleRootManager">
4
+
<content url="file://$MODULE_DIR$">
5
+
<sourceFolder url="file://$MODULE_DIR$/src-tauri/src" isTestSource="false" />
6
+
<excludeFolder url="file://$MODULE_DIR$/src-tauri/target" />
7
+
</content>
8
+
<orderEntry type="inheritedJdk" />
9
+
<orderEntry type="sourceFolder" forTests="false" />
10
+
</component>
11
+
</module>
+8
.idea/modules.xml
+8
.idea/modules.xml
+6
.idea/vcs.xml
+6
.idea/vcs.xml
+2
-1
.vscode/settings.json
+2
-1
.vscode/settings.json
+33
deno.lock
+33
deno.lock
···
1
1
{
2
2
"version": "5",
3
3
"specifiers": {
4
+
"jsr:@std/async@^1.0.14": "1.0.14",
5
+
"npm:@deno/vite-plugin@^1.0.5": "1.0.5_vite@6.3.5__picomatch@4.0.3",
4
6
"npm:@sveltejs/adapter-static@^3.0.6": "3.0.9_@sveltejs+kit@2.36.2__@sveltejs+vite-plugin-svelte@5.1.1___svelte@5.38.3____acorn@8.15.0___vite@6.3.5____picomatch@4.0.3__svelte@5.38.3___acorn@8.15.0__vite@6.3.5___picomatch@4.0.3__acorn@8.15.0_@sveltejs+vite-plugin-svelte@5.1.1__svelte@5.38.3___acorn@8.15.0__vite@6.3.5___picomatch@4.0.3_svelte@5.38.3__acorn@8.15.0_vite@6.3.5__picomatch@4.0.3",
5
7
"npm:@sveltejs/kit@^2.9.0": "2.36.2_@sveltejs+vite-plugin-svelte@5.1.1__svelte@5.38.3___acorn@8.15.0__vite@6.3.5___picomatch@4.0.3_svelte@5.38.3__acorn@8.15.0_vite@6.3.5__picomatch@4.0.3_acorn@8.15.0",
6
8
"npm:@sveltejs/vite-plugin-svelte@5": "5.1.1_svelte@5.38.3__acorn@8.15.0_vite@6.3.5__picomatch@4.0.3",
···
8
10
"npm:@tauri-apps/api@2": "2.8.0",
9
11
"npm:@tauri-apps/cli@2": "2.8.2",
10
12
"npm:@tauri-apps/plugin-opener@2": "2.5.0",
13
+
"npm:@tauri-apps/plugin-positioner@2.3": "2.3.0",
14
+
"npm:@tauri-apps/plugin-window-state@2.4": "2.4.0",
11
15
"npm:svelte-check@4": "4.3.1_svelte@5.38.3__acorn@8.15.0_typescript@5.6.3",
12
16
"npm:svelte@5": "5.38.3_acorn@8.15.0",
13
17
"npm:tailwindcss@^4.1.12": "4.1.12",
14
18
"npm:typescript@~5.6.2": "5.6.3",
15
19
"npm:vite@^6.0.3": "6.3.5_picomatch@4.0.3"
16
20
},
21
+
"jsr": {
22
+
"@std/async@1.0.14": {
23
+
"integrity": "62e954a418652c704d37563a3e54a37d4cf0268a9dcaeac1660cc652880b5326"
24
+
}
25
+
},
17
26
"npm": {
27
+
"@deno/vite-plugin@1.0.5_vite@6.3.5__picomatch@4.0.3": {
28
+
"integrity": "sha512-tLja5n4dyMhcze1NzvSs2iiriBymfBlDCZIrjMTxb9O2ru0gvmV6mn5oBD2teNw5Sd92cj3YJzKwsAs8tMJXlg==",
29
+
"dependencies": [
30
+
"vite"
31
+
]
32
+
},
18
33
"@emnapi/core@1.4.5": {
19
34
"integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==",
20
35
"dependencies": [
···
558
573
"@tauri-apps/api"
559
574
]
560
575
},
576
+
"@tauri-apps/plugin-positioner@2.3.0": {
577
+
"integrity": "sha512-YMRcvA+WcULnAS+UjqGLP9ekWAgmBCgvkzT2OTkE8TWcu9jVo/Z79K0nEJhDuhZO/O0b77X0Opd+wDkEDYPeDw==",
578
+
"dependencies": [
579
+
"@tauri-apps/api"
580
+
]
581
+
},
582
+
"@tauri-apps/plugin-window-state@2.4.0": {
583
+
"integrity": "sha512-hRSzPNi2NG0lPFthfVY0V5C1MyWN/gGaQtQYw7i9zZhLzrhZveHZ2omHG1rIiIsjfTGbO7fhjydSoeTTK9GqLw==",
584
+
"dependencies": [
585
+
"@tauri-apps/api"
586
+
]
587
+
},
561
588
"@tybys/wasm-util@0.10.0": {
562
589
"integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
563
590
"dependencies": [
···
957
984
}
958
985
},
959
986
"workspace": {
987
+
"dependencies": [
988
+
"jsr:@std/async@^1.0.14"
989
+
],
960
990
"packageJson": {
961
991
"dependencies": [
992
+
"npm:@deno/vite-plugin@^1.0.5",
962
993
"npm:@sveltejs/adapter-static@^3.0.6",
963
994
"npm:@sveltejs/kit@^2.9.0",
964
995
"npm:@sveltejs/vite-plugin-svelte@5",
···
966
997
"npm:@tauri-apps/api@2",
967
998
"npm:@tauri-apps/cli@2",
968
999
"npm:@tauri-apps/plugin-opener@2",
1000
+
"npm:@tauri-apps/plugin-positioner@2.3",
1001
+
"npm:@tauri-apps/plugin-window-state@2.4",
969
1002
"npm:svelte-check@4",
970
1003
"npm:svelte@5",
971
1004
"npm:tailwindcss@^4.1.12",
+3
package.json
+3
package.json
···
13
13
},
14
14
"license": "MIT",
15
15
"dependencies": {
16
+
"@deno/vite-plugin": "^1.0.5",
16
17
"@tailwindcss/vite": "^4.1.12",
17
18
"@tauri-apps/api": "^2",
18
19
"@tauri-apps/plugin-opener": "^2",
20
+
"@tauri-apps/plugin-positioner": "~2.3.0",
21
+
"@tauri-apps/plugin-window-state": "~2.4.0",
19
22
"tailwindcss": "^4.1.12"
20
23
},
21
24
"devDependencies": {
+32
src-tauri/Cargo.lock
+32
src-tauri/Cargo.lock
···
2023
2023
"tauri",
2024
2024
"tauri-build",
2025
2025
"tauri-plugin-opener",
2026
+
"tauri-plugin-positioner",
2026
2027
"tauri-plugin-single-instance",
2028
+
"tauri-plugin-window-state",
2027
2029
]
2028
2030
2029
2031
[[package]]
···
3727
3729
]
3728
3730
3729
3731
[[package]]
3732
+
name = "tauri-plugin-positioner"
3733
+
version = "2.3.0"
3734
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3735
+
checksum = "3a01e373ea3f3f5f46d40f434ba13bd12fa4833aabab50dfc09f6362bad27c95"
3736
+
dependencies = [
3737
+
"log",
3738
+
"serde",
3739
+
"serde_json",
3740
+
"serde_repr",
3741
+
"tauri",
3742
+
"tauri-plugin",
3743
+
"thiserror 2.0.16",
3744
+
]
3745
+
3746
+
[[package]]
3730
3747
name = "tauri-plugin-single-instance"
3731
3748
version = "2.3.3"
3732
3749
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3739
3756
"tracing",
3740
3757
"windows-sys 0.60.2",
3741
3758
"zbus",
3759
+
]
3760
+
3761
+
[[package]]
3762
+
name = "tauri-plugin-window-state"
3763
+
version = "2.4.0"
3764
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3765
+
checksum = "2d5f6fe3291bfa609c7e0b0ee3bedac294d94c7018934086ce782c1d0f2a468e"
3766
+
dependencies = [
3767
+
"bitflags 2.9.3",
3768
+
"log",
3769
+
"serde",
3770
+
"serde_json",
3771
+
"tauri",
3772
+
"tauri-plugin",
3773
+
"thiserror 2.0.16",
3742
3774
]
3743
3775
3744
3776
[[package]]
+2
src-tauri/Cargo.toml
+2
src-tauri/Cargo.toml
+15
src-tauri/capabilities/desktop.json
+15
src-tauri/capabilities/desktop.json
+60
-28
src-tauri/src/lib.rs
+60
-28
src-tauri/src/lib.rs
···
1
-
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
2
-
#[tauri::command]
3
-
fn greet(name: &str) -> String {
4
-
format!("Hello, {}! You've been greeted from Rust!", name)
5
-
}
6
-
7
-
#[cfg_attr(mobile, tauri::mobile_entry_point)]
8
-
pub fn run() {
9
-
let mut builder = tauri::Builder::default();
10
-
11
-
#[cfg(desktop)]
12
-
{
13
-
builder = builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
14
-
use tauri::Manager;
15
-
16
-
let _ = app
17
-
.get_webview_window("main")
18
-
.expect("no main window")
19
-
.set_focus();
20
-
}));
21
-
}
22
-
23
-
builder
24
-
.plugin(tauri_plugin_opener::init())
25
-
.invoke_handler(tauri::generate_handler![greet])
26
-
.run(tauri::generate_context!())
27
-
.expect("error while running tauri application");
28
-
}
1
+
use tauri::{WebviewUrl, WebviewWindowBuilder};
2
+
use tauri_plugin_positioner::{Position, WindowExt};
3
+
use tauri_plugin_window_state::{StateFlags, WindowExt as StateWindowExt};
4
+
5
+
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
6
+
#[tauri::command]
7
+
fn greet(name: &str) -> String {
8
+
format!("Hello, {}! You've been greeted from Rust!", name)
9
+
}
10
+
11
+
#[cfg_attr(mobile, tauri::mobile_entry_point)]
12
+
pub fn run() {
13
+
let mut builder = tauri::Builder::default()
14
+
.plugin(tauri_plugin_opener::init())
15
+
.plugin(tauri_plugin_window_state::Builder::new().build())
16
+
.plugin(tauri_plugin_positioner::init());
17
+
18
+
#[cfg(desktop)]
19
+
{
20
+
builder = builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
21
+
use tauri::Manager;
22
+
23
+
let _ = app
24
+
.get_webview_window("main")
25
+
.expect("no main window")
26
+
.set_focus();
27
+
}));
28
+
}
29
+
30
+
builder
31
+
.setup(|app| {
32
+
let mut win_builder =
33
+
WebviewWindowBuilder::new(app, "main", WebviewUrl::default()).title("miwiwi");
34
+
35
+
#[cfg(desktop)]
36
+
{
37
+
win_builder = win_builder
38
+
.inner_size(600.0, 800.0)
39
+
.decorations(false)
40
+
.always_on_top(true)
41
+
.visible(false)
42
+
.maximizable(false);
43
+
}
44
+
45
+
let window = win_builder.build().expect("failed to build window");
46
+
47
+
window
48
+
.move_window(Position::BottomRight)
49
+
.expect("could not move window");
50
+
51
+
window
52
+
.restore_state(StateFlags::all())
53
+
.expect("could not restore window state");
54
+
55
+
Ok(())
56
+
})
57
+
.invoke_handler(tauri::generate_handler![greet])
58
+
.run(tauri::generate_context!())
59
+
.expect("error while running tauri application");
60
+
}
+1
-7
src-tauri/tauri.conf.json
+1
-7
src-tauri/tauri.conf.json
+9
src/routes/+layout.ts
+9
src/routes/+layout.ts
···
1
1
import "../app.css";
2
+
import { debounce } from "@std/async";
3
+
import { saveWindowState, StateFlags } from "@tauri-apps/plugin-window-state";
4
+
import { listen, type Event, TauriEvent } from "@tauri-apps/api/event";
2
5
3
6
// Tauri doesn't have a Node.js server to do proper SSR
4
7
// so we use adapter-static with a fallback to index.html to put the site in SPA mode
5
8
// See: https://svelte.dev/docs/kit/single-page-apps
6
9
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
7
10
export const ssr = false;
11
+
12
+
const debounced = debounce((_: Event<TauriEvent.WINDOW_RESIZED>) => {
13
+
saveWindowState(StateFlags.ALL);
14
+
}, 250);
15
+
16
+
listen("tauri://resize", debounced);
+3
-2
vite.config.js
+3
-2
vite.config.js
···
1
1
import { defineConfig } from "vite";
2
2
import { sveltekit } from "@sveltejs/kit/vite";
3
+
import deno from "@deno/vite-plugin";
3
4
import tailwindcss from "@tailwindcss/vite";
4
5
5
6
// @ts-expect-error process is a nodejs global
6
-
const host = process.env.TAURI_DEV_HOST;
7
+
const host = Deno.env.get("TAURI_DEV_HOST");
7
8
8
9
// https://vite.dev/config/
9
10
export default defineConfig(async () => ({
10
-
plugins: [sveltekit(), tailwindcss()],
11
+
plugins: [sveltekit(), tailwindcss(), deno()],
11
12
12
13
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
13
14
//