diff --git a/.github/workflows/discussions_dump.yml b/.github/workflows/discussions_dump.yml
index ad2f916..e1f5e6a 100644
--- a/.github/workflows/discussions_dump.yml
+++ b/.github/workflows/discussions_dump.yml
@@ -16,7 +16,7 @@ jobs:
cache: 'npm'
cache-dependency-path: 'package-lock.json'
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_TOKEN: ${{ github.token }}
run: |
cd ./scripts
npm ci
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e6f439c..8cfe586 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,5 +1,6 @@
name: 'Publish Cross Platform Builds'
on:
+ workflow_dispatch:
push:
branches:
- release
@@ -32,6 +33,8 @@ jobs:
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
+ TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
tagName: v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version
releaseName: 'Simple Android Debloater v__VERSION__'
diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml
new file mode 100644
index 0000000..67c74cf
--- /dev/null
+++ b/.github/workflows/updater.yml
@@ -0,0 +1,56 @@
+name: Update Manifest Workflow
+
+on:
+ workflow_dispatch:
+ inputs:
+ user_input_version:
+ description: 'Version /tag to target'
+ release:
+ types: [created]
+
+jobs:
+ generate_updater_json:
+ runs-on: ubuntu-latest
+ steps:
+ - run: |
+ # https://dev.to/mrmike/github-action-handling-input-default-value-5f2g
+ USER_INPUT_VERSION=${{ github.event.inputs.user_input_version }}
+ echo "user_input_version=${USER_INPUT_VERSION:-"latest"}" >> "$GITHUB_OUTPUT"
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: 'npm'
+ cache-dependency-path: 'package-lock.json'
+ - env:
+ GH_TOKEN: ${{ github.token }}
+ RELEASE_EVENT: ${{github.event.release}}
+ RELEASE_TAG: ${{github.event.inputs.user_input_version}}
+ run: |
+ cd ./scripts
+ npm ci
+ ls -lahtr
+ node ./updater_template.js
+ - uses: actions/upload-artifact@v3.1.2
+ with:
+ name: sad_updater.json
+ path: ./scripts/sad_updater.json
+ if-no-files-found: error
+
+ upload_updater_json_to_s3:
+ runs-on: ubuntu-latest
+ needs: [generate_updater_json]
+ # These permissions are needed to interact with GitHub's OIDC Token endpoint.
+ permissions:
+ id-token: write
+ contents: read
+ steps:
+ - uses: actions/download-artifact@v2.1.1
+ - run: ls -lahtr
+ - run: pwd
+ - uses: aws-actions/configure-aws-credentials@v3
+ with:
+ aws-region: us-east-1
+ role-to-assume: ${{ secrets.AWS_SAD_UPLOADER_ROLE }}
+ # use recursive: https://github.com/aws/aws-cli/issues/2929
+ - run: aws s3 cp sad_updater.json s3://simple-android-debloater --recursive
diff --git a/.gitignore b/.gitignore
index 14a42be..920df89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,4 +11,5 @@ vite.config.ts.timestamp-*
*.db
*.db-shm
*.db-wal
-discussions_dump.json
\ No newline at end of file
+discussions_dump.json
+sad_updater.json
\ No newline at end of file
diff --git a/README.md b/README.md
index 8bb1def..36b31e3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
This software is in beta 🚧
-Simpl Android Debloater is a free and open source project to disable unwanted system apps that careers / OEMs force install in our mobile phones.
+Simple Android Debloater is a free and open source project to disable unwanted system apps that careers / OEMs force install in our mobile phones.
This is an attempt like [Universal Android Debloater](https://github.com/0x192/universal-android-debloater/) built with [Tauri](https://tauri.app/) and [Sveltekit](https://kit.svelte.dev/).
diff --git a/scripts/package-lock.json b/scripts/package-lock.json
index aab82aa..244699f 100644
--- a/scripts/package-lock.json
+++ b/scripts/package-lock.json
@@ -9,9 +9,107 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
+ "@octokit/core": "^5.0.0",
"node-fetch": "^3.3.2"
}
},
+ "node_modules/@octokit/auth-token": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
+ "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/core": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz",
+ "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==",
+ "dependencies": {
+ "@octokit/auth-token": "^4.0.0",
+ "@octokit/graphql": "^7.0.0",
+ "@octokit/request": "^8.0.2",
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^11.0.0",
+ "before-after-hook": "^2.2.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/endpoint": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz",
+ "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==",
+ "dependencies": {
+ "@octokit/types": "^11.0.0",
+ "is-plain-object": "^5.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/graphql": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz",
+ "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==",
+ "dependencies": {
+ "@octokit/request": "^8.0.1",
+ "@octokit/types": "^11.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz",
+ "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw=="
+ },
+ "node_modules/@octokit/request": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz",
+ "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==",
+ "dependencies": {
+ "@octokit/endpoint": "^9.0.0",
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^11.1.0",
+ "is-plain-object": "^5.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/request-error": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz",
+ "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==",
+ "dependencies": {
+ "@octokit/types": "^11.0.0",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/types": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz",
+ "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==",
+ "dependencies": {
+ "@octokit/openapi-types": "^18.0.0"
+ }
+ },
+ "node_modules/before-after-hook": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
+ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
+ },
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@@ -20,6 +118,11 @@
"node": ">= 12"
}
},
+ "node_modules/deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
+ },
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
@@ -53,6 +156,14 @@
"node": ">=12.20.0"
}
},
+ "node_modules/is-plain-object": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
@@ -88,6 +199,19 @@
"url": "https://opencollective.com/node-fetch"
}
},
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/universal-user-agent": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
+ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
+ },
"node_modules/web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
@@ -95,6 +219,11 @@
"engines": {
"node": ">= 8"
}
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}
diff --git a/scripts/package.json b/scripts/package.json
index 84e3637..026121b 100644
--- a/scripts/package.json
+++ b/scripts/package.json
@@ -9,6 +9,7 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "@octokit/core": "^5.0.0",
"node-fetch": "^3.3.2"
},
"type": "module"
diff --git a/scripts/updater_template.js b/scripts/updater_template.js
new file mode 100644
index 0000000..edef041
--- /dev/null
+++ b/scripts/updater_template.js
@@ -0,0 +1,161 @@
+import { Octokit } from '@octokit/core';
+import fs from 'fs';
+import fetch from 'node-fetch';
+
+let template_json = {
+ version: '0.5.0',
+ notes: 'Test version',
+ pub_date: '2023-06-22T19:25:57Z',
+ platforms: {
+ // 'darwin-x86_64': {
+ // signature: 'Content of app.tar.gz.sig',
+ // url: 'https://github.com/username/reponame/releases/download/v1.0.0/app-x86_64.app.tar.gz'
+ // },
+ // 'darwin-aarch64': {
+ // signature: 'Content of app.tar.gz.sig',
+ // url: 'https://github.com/username/reponame/releases/download/v1.0.0/app-aarch64.app.tar.gz'
+ // },
+ // 'linux-x86_64': {
+ // signature: 'Content of app.AppImage.tar.gz.sig',
+ // url: 'https://github.com/username/reponame/releases/download/v1.0.0/app-amd64.AppImage.tar.gz'
+ // },
+ // 'windows-x86_64': {
+ // signature: 'Content of app-setup.nsis.sig or app.msi.sig, depending on the chosen format',
+ // url: 'https://github.com/username/reponame/releases/download/v1.0.0/app-x64-setup.nsis.zip'
+ // }
+ }
+};
+
+const octokit = new Octokit({
+ auth: process.env.GH_TOKEN
+});
+
+async function getReleaseForTag(tag) {
+ let json = await octokit.request(
+ 'GET /repos/thulasi-ram/simple_android_debloater/releases/tags/{tag}',
+ {
+ tag: tag,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-GitHub-Api-Version': '2022-11-28'
+ }
+ }
+ );
+
+ let data = json.data;
+
+ if (!data) {
+ console.log(json);
+ throw new Error('Error in response json');
+ }
+
+ return data;
+}
+
+async function getSignatureAssetContent(sig_url) {
+ const response = await fetch(sig_url);
+ let sig_content = await response.text();
+
+ return sig_content;
+}
+
+async function getReleaseFromEventOrTag() {
+ const releaseEvent = process.env.RELEASE_EVENT;
+ const releaseTag = process.env.RELEASE_TAG;
+
+ if (releaseEvent && releaseTag) {
+ throw new Error('one of releaseTag or releaseEvent is expected. Got both');
+ }
+
+ if (!releaseEvent && !releaseTag) {
+ throw new Error('one of releaseTag or releaseEvent is expected. Got neither');
+ }
+
+ console.log('release event and tag', releaseEvent, releaseTag);
+
+ let release = {
+ id: '',
+ tag: '',
+ body: '',
+ assets: [],
+ published_at: ''
+ };
+
+ if (releaseEvent) {
+ let releaseData = JSON.parse(releaseEvent);
+ console.log('release by event', releaseData.id);
+
+ release = {
+ id: releaseData.id,
+ tag: releaseData.tag_name,
+ body: releaseData.body,
+ assets: releaseData.assets,
+ published_at: releaseData.published_at
+ };
+ }
+
+ if (releaseTag != '') {
+ let releaseData = await getReleaseForTag(releaseTag);
+ console.log('release by tag', releaseData.id);
+
+ release = {
+ id: releaseData.id,
+ tag: releaseData.tag_name,
+ body: releaseData.body,
+ assets: releaseData.assets,
+ published_at: releaseData.published_at
+ };
+ }
+
+ let version = release.tag;
+ if (version.charAt(0) === 'v') {
+ version = version.substring(1); // remove first letter
+ }
+
+ let asset_url_map = release.assets.reduce((map, a) => {
+ map[a.name] = a.browser_download_url;
+ return map;
+ }, {});
+
+ let extensions = {
+ linux: 'amd64.AppImage.tar.gz',
+ darwin: '.app.tar.gz',
+ windows: 'x64-setup.nsis.zip'
+ };
+
+ let platform_sig_template = {};
+
+ for (let [platform, ext] of Object.entries(extensions)) {
+ for (let [name, url] of Object.entries(asset_url_map)) {
+ if (name.endsWith(ext)) {
+ let sig_url = asset_url_map[`${name}.sig`];
+ let sig_content = await getSignatureAssetContent(sig_url);
+
+ platform_sig_template[`${platform}-x86_64`] = {
+ signature: sig_content,
+ url: url
+ };
+
+ if (platform == 'darwin') {
+ // apple silicon chips
+ platform_sig_template[`${platform}-aarch64`] = {
+ signature: sig_content,
+ url: url
+ };
+ }
+ }
+ }
+ }
+
+ template_json.version = version;
+ template_json.notes = release.body;
+ template_json.pub_date = release.published_at;
+ template_json.platforms = platform_sig_template;
+
+ fs.writeFile('sad_updater.json', JSON.stringify(template_json), 'utf8', function (err) {
+ if (err) throw err;
+ console.log('Dumped sad_updater.json');
+ });
+}
+
+getReleaseFromEventOrTag();
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index fc8c3fe..0ee3932 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -2126,6 +2126,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+[[package]]
+name = "minisign-verify"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
+
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -3938,6 +3944,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e"
dependencies = [
"anyhow",
+ "base64 0.21.2",
"bytes",
"cocoa",
"dirs-next",
@@ -3951,6 +3958,7 @@ dependencies = [
"heck 0.4.1",
"http",
"ignore",
+ "minisign-verify",
"notify-rust",
"objc",
"once_cell",
@@ -3974,12 +3982,14 @@ dependencies = [
"tauri-utils",
"tempfile",
"thiserror",
+ "time",
"tokio",
"url",
"uuid",
"webkit2gtk",
"webview2-com",
"windows 0.39.0",
+ "zip",
]
[[package]]
@@ -5285,6 +5295,17 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+[[package]]
+name = "zip"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
+dependencies = [
+ "byteorder",
+ "crc32fast",
+ "crossbeam-utils",
+]
+
[[package]]
name = "zvariant"
version = "3.15.0"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 5c19316..1ecfc30 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -18,7 +18,7 @@ dotenvy= "0.15.7"
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
-tauri = { version = "1.4.0", features = [ "fs-read-file", "fs-write-file", "dialog-all", "shell-open", "http-request", "path-all", "app-all", "notification-all", "devtools"] }
+tauri = { version = "1.4.0", features = [ "updater", "process-all", "fs-read-file", "fs-write-file", "dialog-all", "shell-open", "http-request", "path-all", "app-all", "notification-all", "devtools"] }
thiserror = "1.0"
anyhow = "*"
tokio = { version = "*", features = ["full"] }
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 188264b..752fa89 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -8,7 +8,7 @@
},
"package": {
"productName": "Simple Android Debloater",
- "version": "0.4.0"
+ "version": "0.5.0"
},
"tauri": {
"allowlist": {
@@ -21,7 +21,29 @@
"fs": {
"readFile": true,
"writeFile": true,
- "scope": ["**"]
+ "scope": [
+ "$APP",
+ "$APP/*",
+ "$APP/**",
+ "$DESKTOP",
+ "$DESKTOP/*",
+ "$DESKTOP/**",
+ "$DOCUMENT",
+ "$DOCUMENT/*",
+ "$DOCUMENT/**",
+ "$DOWNLOAD",
+ "$DOWNLOAD/*",
+ "$DOWNLOAD/**",
+ "$HOME",
+ "$HOME/*",
+ "$HOME/**",
+ "$PICTURE",
+ "$PICTURE/*",
+ "$PICTURE/**",
+ "$PUBLIC",
+ "$PUBLIC/*",
+ "$PUBLIC/**"
+ ]
},
"http": {
"request": true,
@@ -30,6 +52,9 @@
"path": {
"all": true
},
+ "process": {
+ "all": true
+ },
"notification": {
"all": true
},
@@ -74,7 +99,10 @@
"csp": null
},
"updater": {
- "active": false
+ "active": true,
+ "endpoints": ["https://d31d7prv3kbkn6.cloudfront.net/sad_updater.json"],
+ "dialog": true,
+ "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDdCNkMwNEMyNzA2NjRCNkUKUldSdVMyWnd3Z1JzZTVjRHRhdENCSEtDNzIvT2tqazJsL3djQlNzOHB4cmFuRDFQZ21ZVjExUXcK"
},
"windows": [
{
diff --git a/src/lib/Sidebar.svelte b/src/lib/Sidebar.svelte
index e7cf0c6..c7fddad 100644
--- a/src/lib/Sidebar.svelte
+++ b/src/lib/Sidebar.svelte
@@ -5,11 +5,28 @@
IconDownload,
IconFileExport,
IconInfoSquareRounded,
- IconSettings
+ IconMoon,
+ IconMoonFilled,
+ IconRefresh,
+ IconSettings,
+ IconSun,
+ IconSunFilled
} from '@tabler/icons-svelte';
- import { DarkMode, Sidebar, SidebarGroup, SidebarItem, SidebarWrapper } from 'flowbite-svelte';
+ import {
+ Button,
+ DarkMode,
+ Hr,
+ Sidebar,
+ SidebarGroup,
+ SidebarItem,
+ SidebarWrapper
+ } from 'flowbite-svelte';
+ import { relaunch } from '@tauri-apps/api/process';
$: activeUrl = $page.url.pathname;
+
+ let darkModeBtnClass =
+ 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg text-xl p-3';
app version: {version}
{/await} + +