From 94ef51d0ff0275256440659dc83e5db4a78a64cc Mon Sep 17 00:00:00 2001 From: 4gray Date: Wed, 20 Nov 2024 22:43:29 +0100 Subject: [PATCH] feat: add update mechanism --- package-lock.json | 30 ++ package.json | 5 +- src-tauri/Cargo.lock | 622 +++++++++++++++++++++++++++- src-tauri/Cargo.toml | 3 + src-tauri/capabilities/default.json | 5 +- src-tauri/capabilities/desktop.json | 3 +- src-tauri/src/lib.rs | 3 + src-tauri/tauri.conf.json | 10 +- src/app/app.component.spec.ts | 1 + src/app/app.component.ts | 82 +++- src/m3-theme.scss | 40 +- 11 files changed, 743 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5806f28f..6648c3419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,10 +24,13 @@ "@rx-angular/cdk": "18.0.0", "@rx-angular/template": "18.0.0", "@tauri-apps/api": "2.1.0", + "@tauri-apps/plugin-dialog": "2.0.1", "@tauri-apps/plugin-fs": "2.0.2", "@tauri-apps/plugin-http": "2.0.1", "@tauri-apps/plugin-os": "2.0.0", + "@tauri-apps/plugin-process": "2.0.0", "@tauri-apps/plugin-shell": "2.0.1", + "@tauri-apps/plugin-updater": "2.0.0", "@tauri-apps/plugin-window-state": "2.0.0", "@videojs/http-streaming": "2.15.0", "@yangkghjh/videojs-aspect-ratio-panel": "0.0.1", @@ -8110,6 +8113,15 @@ "node": ">= 10" } }, + "node_modules/@tauri-apps/plugin-dialog": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.0.1.tgz", + "integrity": "sha512-fnUrNr6EfvTqdls/ufusU7h6UbNFzLKvHk/zTuOiBq01R3dTODqwctZlzakdbfSp/7pNwTKvgKTAgl/NAP/Z0Q==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, "node_modules/@tauri-apps/plugin-fs": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-fs/-/plugin-fs-2.0.2.tgz", @@ -8137,6 +8149,15 @@ "@tauri-apps/api": "^2.0.0" } }, + "node_modules/@tauri-apps/plugin-process": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-process/-/plugin-process-2.0.0.tgz", + "integrity": "sha512-OYzi0GnkrF4NAnsHZU7U3tjSoP0PbeAlO7T1Z+vJoBUH9sFQ1NSLqWYWQyf8hcb3gVWe7P1JggjiskO+LST1ug==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, "node_modules/@tauri-apps/plugin-shell": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-shell/-/plugin-shell-2.0.1.tgz", @@ -8146,6 +8167,15 @@ "@tauri-apps/api": "^2.0.0" } }, + "node_modules/@tauri-apps/plugin-updater": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.0.0.tgz", + "integrity": "sha512-N0cl71g7RPr7zK2Fe5aoIwzw14NcdLcz7XMGFWZVjprsqgDRWoxbnUkknyCQMZthjhGkppCd/wN2MIsUz+eAhQ==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, "node_modules/@tauri-apps/plugin-window-state": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-window-state/-/plugin-window-state-2.0.0.tgz", diff --git a/package.json b/package.json index 84dbef453..3fbb0e517 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iptvnator", - "version": "0.16.0", + "version": "1.0.0-beta.2", "description": "IPTV player application.", "homepage": "https://github.com/4gray/iptvnator", "author": { @@ -67,10 +67,13 @@ "@rx-angular/cdk": "18.0.0", "@rx-angular/template": "18.0.0", "@tauri-apps/api": "2.1.0", + "@tauri-apps/plugin-dialog": "2.0.1", "@tauri-apps/plugin-fs": "2.0.2", "@tauri-apps/plugin-http": "2.0.1", "@tauri-apps/plugin-os": "2.0.0", + "@tauri-apps/plugin-process": "2.0.0", "@tauri-apps/plugin-shell": "2.0.1", + "@tauri-apps/plugin-updater": "2.0.0", "@tauri-apps/plugin-window-state": "2.0.0", "@videojs/http-streaming": "2.15.0", "@yangkghjh/videojs-aspect-ratio-panel": "0.0.1", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c979d5996..c756383f1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -12,11 +12,14 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-http", "tauri-plugin-log", "tauri-plugin-os", + "tauri-plugin-process", "tauri-plugin-shell", + "tauri-plugin-updater", "tauri-plugin-window-state", ] @@ -108,12 +111,76 @@ version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "ashpd" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "raw-window-handle", + "serde", + "serde_repr", + "tokio", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + [[package]] name = "atk" version = "0.18.0" @@ -244,7 +311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" dependencies = [ "once_cell", - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.86", @@ -506,6 +573,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -721,6 +797,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -771,6 +858,26 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dlopen2" version = "0.7.0" @@ -794,6 +901,12 @@ dependencies = [ "syn 2.0.86", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dpi" version = "0.1.1" @@ -859,6 +972,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + [[package]] name = "env_filter" version = "0.1.2" @@ -895,6 +1035,33 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + [[package]] name = "fdeflate" version = "0.3.6" @@ -923,6 +1090,18 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + [[package]] name = "fix-path-env" version = "0.0.0" @@ -1300,7 +1479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ "heck 0.4.1", - "proc-macro-crate 2.0.2", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", @@ -1877,6 +2056,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", + "redox_syscall", ] [[package]] @@ -1960,6 +2140,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minisign-verify" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05b5d0594e0cb1ad8cee3373018d2b84e25905dc75b2468114cc9a8e86cfc20" + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2038,6 +2224,19 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", + "memoffset", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2074,7 +2273,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.2", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 2.0.86", @@ -2207,6 +2406,7 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", "block2", + "dispatch", "libc", "objc2", ] @@ -2348,6 +2548,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_info" version = "3.8.2" @@ -2394,6 +2604,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -2589,7 +2805,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", "indexmap 2.6.0", - "quick-xml", + "quick-xml 0.32.0", "serde", "time", ] @@ -2640,14 +2856,22 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2732,6 +2956,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" version = "0.11.5" @@ -2990,6 +3223,29 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "rfd" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f6f80a9b882647d9014673ca9925d30ffc9750f2eed2b4490e189eaebd01e8" +dependencies = [ + "ashpd", + "block2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + [[package]] name = "ring" version = "0.17.8" @@ -3166,6 +3422,12 @@ dependencies = [ "syn 2.0.86", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -3382,6 +3644,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -3485,6 +3756,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.7" @@ -3685,6 +3962,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.12.16" @@ -3821,6 +4109,24 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-dialog" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4307310e1d2c09ab110235834722e7c2b85099b683e1eb7342ab351b0be5ada3" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror", + "url", +] + [[package]] name = "tauri-plugin-fs" version = "2.0.3" @@ -3904,6 +4210,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "tauri-plugin-process" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae06a00087c148962a52814a2d7265b1a0505bced5ffb74f8c284a5f96a4d03d" +dependencies = [ + "tauri", + "tauri-plugin", +] + [[package]] name = "tauri-plugin-shell" version = "2.0.2" @@ -3925,6 +4241,36 @@ dependencies = [ "tokio", ] +[[package]] +name = "tauri-plugin-updater" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd3d2fe0f02bf52eebb5a9d23b987fffac6684646ab6fd683d706dafb18da87" +dependencies = [ + "base64 0.22.1", + "dirs", + "flate2", + "futures-util", + "http", + "infer", + "minisign-verify", + "percent-encoding", + "reqwest", + "semver", + "serde", + "serde_json", + "tar", + "tauri", + "tauri-plugin", + "tempfile", + "thiserror", + "time", + "tokio", + "url", + "windows-sys 0.59.0", + "zip", +] + [[package]] name = "tauri-plugin-window-state" version = "2.0.2" @@ -4031,6 +4377,19 @@ dependencies = [ "toml 0.7.8", ] +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "tendril" version = "0.4.3" @@ -4127,8 +4486,10 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", + "tracing", "windows-sys 0.52.0", ] @@ -4193,9 +4554,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -4210,7 +4571,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -4223,7 +4584,18 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime", + "winnow 0.6.20", ] [[package]] @@ -4239,9 +4611,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.86", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -4290,6 +4674,17 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "unic-char-property" version = "0.9.0" @@ -4585,6 +4980,66 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" +dependencies = [ + "bitflags 2.6.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" +dependencies = [ + "bitflags 2.6.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" +dependencies = [ + "proc-macro2", + "quick-xml 0.36.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.72" @@ -5045,6 +5500,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.52.0" @@ -5126,6 +5590,84 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys", + "rustix", +] + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "zbus" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1162094dc63b1629fcc44150bcceeaa80798cd28bcbe7fa987b65a034c258608" +dependencies = [ + "async-broadcast", + "async-recursion", + "async-trait", + "enumflags2", + "event-listener", + "futures-core", + "futures-util", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow 0.6.20", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd2dcdce3e2727f7d74b7e33b5a89539b3cc31049562137faf7ae4eb86cd16d" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.86", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.6.20", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -5152,3 +5694,61 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zip" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "indexmap 2.6.0", + "memchr", + "thiserror", +] + +[[package]] +name = "zvariant" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "winnow 0.6.20", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.86", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn 2.0.86", + "winnow 0.6.20", +] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6d9dd48f2..a9003ecd0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -28,6 +28,9 @@ tauri-plugin-shell = "2" fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } tauri-plugin-os = "2" tauri-plugin-fs = "2" +tauri-plugin-process = "2" +tauri-plugin-dialog = "2" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] +tauri-plugin-updater = "2" tauri-plugin-window-state = "2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 298d0faec..fcd9eeb76 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -36,6 +36,9 @@ "http:default", "window-state:default", "os:default", - "fs:default" + "fs:default", + "updater:default", + "dialog:default", + "process:default" ] } diff --git a/src-tauri/capabilities/desktop.json b/src-tauri/capabilities/desktop.json index de53dc6c2..2e0d4ccd8 100644 --- a/src-tauri/capabilities/desktop.json +++ b/src-tauri/capabilities/desktop.json @@ -6,6 +6,7 @@ "linux" ], "permissions": [ - "window-state:default" + "window-state:default", + "updater:default" ] } \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a8fcde000..3151cf083 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -81,6 +81,9 @@ async fn open_in_vlc(url: String, path: String) -> Result<(), String> { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_process::init()) + .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_window_state::Builder::new().build()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7a7bb4f6b..18593098a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,14 @@ "beforeDevCommand": "npm run ng:serve", "beforeBuildCommand": "npm run ng:build" }, - "plugins": {}, + "plugins": { + "updater": { + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDkwNkIxNzBGQzMxNDdCClJXUjdGTU1QRjJ1UUFIVjgrSk9jVjFxeVFBOXFzVlZ1M0RQbnFGM0gvZEluY0MxQzBibGtlVU5HCg==", + "endpoints": [ + "https://github.com/4gray/iptvnator/releases/latest/download/latest.json" + ] + } + }, "app": { "windows": [ { @@ -73,6 +80,7 @@ } }, "bundle": { + "createUpdaterArtifacts": true, "active": true, "targets": "all", "icon": [ diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index dae2626dd..58d1515e9 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -74,6 +74,7 @@ describe('AppComponent', () => { // TODO: investigate in detail component.triggerAutoUpdateMechanism = jest.fn(); component.modals = []; + component.checkForUpdates = jest.fn(); fixture.detectChanges(); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 08244bd00..a2a9c59e8 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,6 +3,9 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; +import { ask } from '@tauri-apps/plugin-dialog'; +import { relaunch } from '@tauri-apps/plugin-process'; +import { check } from '@tauri-apps/plugin-updater'; import { ModalWindow } from 'ngx-whats-new/lib/modal-window.interface'; import { firstValueFrom } from 'rxjs'; import * as semver from 'semver'; @@ -28,9 +31,7 @@ import { Settings } from './settings/settings.interface'; import { Theme } from './settings/theme.enum'; import { STORE_KEY } from './shared/enums/store-keys.enum'; import * as PlaylistActions from './state/actions'; -/** - * AppComponent - */ + @Component({ selector: 'app-root', templateUrl: './app.component.html', @@ -63,7 +64,7 @@ export class AppComponent { listeners = []; constructor( - private electronService: DataService, + private dataService: DataService, private epgService: EpgService, private ngZone: NgZone, private playlistService: PlaylistsService, @@ -75,19 +76,19 @@ export class AppComponent { private whatsNewService: WhatsNewService ) { if ( - ((this.electronService.isElectron && - this.electronService?.remote?.process.platform === 'linux') || - this.electronService?.remote?.process.platform === 'win32') && - this.electronService.remote.process.argv.length > 2 + ((this.dataService.isElectron && + this.dataService?.remote?.process.platform === 'linux') || + this.dataService?.remote?.process.platform === 'win32') && + this.dataService.remote.process.argv.length > 2 ) { - const filePath = this.electronService.remote.process.argv.find( + const filePath = this.dataService.remote.process.argv.find( (filepath) => filepath.endsWith('.m3u') || filepath.endsWith('.m3u8') ); if (filePath) { const filePathsArray = filePath.split('/'); const fileName = filePathsArray[filePathsArray.length - 1]; - this.electronService.sendIpcEvent(OPEN_FILE, { + this.dataService.sendIpcEvent(OPEN_FILE, { filePath, fileName, }); @@ -104,15 +105,56 @@ export class AppComponent { this.handleWhatsNewDialog(); this.triggerAutoUpdateMechanism(); + this.checkForUpdates(); + } + + async checkForUpdates() { + const update = await check(); + if (update?.available) { + console.log( + `found update ${update.version} from ${update.date} with notes ${update.body}` + ); + let downloaded = 0; + let contentLength = 0; + + const wantsUpdate = await ask( + `New version ${update.version} is available. Do you want to update now?` + ); + + if (wantsUpdate) { + await update.downloadAndInstall((event) => { + switch (event.event) { + case 'Started': + contentLength = event.data.contentLength; + console.log( + `started downloading ${event.data.contentLength} bytes` + ); + break; + case 'Progress': + downloaded += event.data.chunkLength; + console.log( + `downloaded ${downloaded} from ${contentLength}` + ); + break; + case 'Finished': + console.log('download finished'); + break; + } + }); + + console.log('update installed'); + await relaunch(); + } + } } async triggerAutoUpdateMechanism() { - if (this.electronService.isElectron) { + if (this.dataService.isElectron) { const playlistForAutoUpdate = await firstValueFrom( this.playlistService.getPlaylistsForAutoUpdate() ); if (playlistForAutoUpdate && playlistForAutoUpdate.length > 0) - this.electronService.sendIpcEvent( + this.dataService.sendIpcEvent( AUTO_UPDATE_PLAYLISTS, playlistForAutoUpdate ); @@ -124,8 +166,8 @@ export class AppComponent { */ setRendererListeners(): void { this.commandsList.forEach((command) => { - if (this.electronService.isElectron) { - this.electronService.listenOn(command.id, () => + if (this.dataService.isElectron) { + this.dataService.listenOn(command.id, () => this.ngZone.run((data) => command.callback(data)) ); } else { @@ -134,7 +176,7 @@ export class AppComponent { command.callback(response.data); } }; - this.electronService.listenOn(command.id, cb); + this.dataService.listenOn(command.id, cb); this.listeners.push(cb); } }); @@ -149,7 +191,7 @@ export class AppComponent { .getValueFromLocalStorage(STORE_KEY.Settings) .subscribe((settings: Settings) => { if (settings && Object.keys(settings).length > 0) { - this.electronService.sendIpcEvent(SETTINGS_UPDATE, settings); + this.dataService.sendIpcEvent(SETTINGS_UPDATE, settings); this.translate.use(settings.language ?? this.DEFAULT_LANG); if ( settings.epgUrl?.length > 0 && @@ -188,7 +230,7 @@ export class AppComponent { * Checks the actual version of the application and shows the "what is new" dialog if the updated version was detected */ handleWhatsNewDialog(): void { - const actualVersion = this.electronService.getAppVersion(); + const actualVersion = this.dataService.getAppVersion(); this.settingsService .getValueFromLocalStorage(STORE_KEY.Version) .subscribe((version: string) => { @@ -231,7 +273,7 @@ export class AppComponent { */ showWhatsNewDialog(): void { this.modals = this.whatsNewService.getModalsByVersion( - this.electronService.getAppVersion() + this.dataService.getAppVersion() ); this.setDialogVisibility(true); } @@ -250,9 +292,9 @@ export class AppComponent { * Removes all ipc command listeners on component destroy */ ngOnDestroy(): void { - if (this.electronService.isElectron) { + if (this.dataService.isElectron) { this.commandsList.forEach((command) => - this.electronService.removeAllListeners(command.id) + this.dataService.removeAllListeners(command.id) ); } else { this.listeners.forEach((listener) => diff --git a/src/m3-theme.scss b/src/m3-theme.scss index f87615eec..d8e557876 100644 --- a/src/m3-theme.scss +++ b/src/m3-theme.scss @@ -11,20 +11,20 @@ $my-typography: mat.m2-define-typography-config(); $_palettes: ( primary: ( 0: #000000, - 10: #1a1c1c, - 20: #2f3131, - 25: #3a3c3c, - 30: #454747, - 35: #515353, - 40: #5d5f5f, - 50: #767777, - 60: #909191, - 70: #aaabab, - 80: #c6c6c7, - 90: #e2e2e2, - 95: #f0f1f1, - 98: #f9f9f9, - 99: #fcfcfc, + 10: #001b3d, + 20: #002f63, + 25: #003875, + 30: #004288, + 35: #004c9b, + 40: #0057af, + 50: #226fc8, + 60: #4787dc, + 70: #669ef0, + 80: #98b9ff, + 90: #cde0ff, + 95: #e6f0ff, + 98: #f6f9ff, + 99: #fcfcff, 100: #ffffff, ), secondary: ( @@ -160,16 +160,4 @@ html { .dark-theme { @include mat.all-component-colors($dark-theme); } - - /* // Apply the dark theme by default - @include mat.core-theme($dark-theme); - @include mat.button-theme($dark-theme); - - // Apply the light theme only when the user prefers light themes. - @media (prefers-color-scheme: light) { - // Use the `-color` mixins to only apply color styles without reapplying the same - // typography and density styles. - @include mat.core-color($light-theme); - @include mat.button-color($light-theme); - } */ } \ No newline at end of file