feat(vpn-ui): init frontend NC-134 (#4160)
This commit is contained in:
@@ -35,7 +35,7 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --lib --features custom-protocol
|
||||
args: --manifest-path ${{ env.CARGOTOML_PATH }} --features custom-protocol
|
||||
|
||||
# - name: Run all tests
|
||||
# uses: actions-rs/cargo@v1
|
||||
|
||||
@@ -80,18 +80,6 @@ Generated TS types will be located in `src-tauri/bindings/`
|
||||
|
||||
## Build
|
||||
|
||||
To build as a **shared library**
|
||||
|
||||
```
|
||||
yarn build && cd src-tauri && cargo build --release --lib --features custom-protocol
|
||||
|
||||
#alias
|
||||
yarn build:app
|
||||
```
|
||||
|
||||
You can build for a different platform using [Cross](https://github.com/cross-rs/cross).
|
||||
For example, to build for Windows on Linux:
|
||||
|
||||
```
|
||||
cross build --target x86_64-pc-windows-gnu --release --lib --features custom-protocol
|
||||
```
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Tauri + React + TS</title>
|
||||
<title>NymVPN</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root" class="bg-gray-900"></div>
|
||||
<body class="h-screen">
|
||||
<div id="root" class="h-full bg-gray-900 text-gray-400"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+10
-6
@@ -8,7 +8,7 @@
|
||||
"dev:app": "RUST_LOG=nymvpn_ui=trace tauri dev",
|
||||
"dev:browser": "vite --mode dev-browser",
|
||||
"build": "tsc && vite build",
|
||||
"build:app": "yarn build && cd src-tauri && cargo build --release --lib --features custom-protocol",
|
||||
"build:app": "yarn tauri build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint --ext .ts,.tsx src/",
|
||||
"lint:fix": "eslint --ext .js,.ts --fix src/",
|
||||
@@ -18,17 +18,21 @@
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mui/base": "^5.0.0-beta.20",
|
||||
"@mui/base": "^5.0.0-beta.24",
|
||||
"@mui/material": "^5.14.14",
|
||||
"@tauri-apps/api": "^1.5.0",
|
||||
"clsx": "^2.0.0",
|
||||
"i18next": "^23.7.6",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^13.5.0",
|
||||
"react-router-dom": "^6.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^1.5.0",
|
||||
"@types/react": "^18.2.31",
|
||||
"@types/react-dom": "^18.2.14",
|
||||
"@types/react": "^18.2.37",
|
||||
"@types/react-dom": "^18.2.15",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
||||
"@typescript-eslint/parser": "^6.8.0",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
@@ -42,6 +46,6 @@
|
||||
"prettier": "^3.0.3",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5"
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+504
-1
@@ -206,6 +206,9 @@ name = "bytes"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
@@ -615,7 +618,7 @@ dependencies = [
|
||||
"rustc_version",
|
||||
"toml 0.8.5",
|
||||
"vswhom",
|
||||
"winreg",
|
||||
"winreg 0.51.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -779,6 +782,12 @@ dependencies = [
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.28"
|
||||
@@ -792,8 +801,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
@@ -1105,6 +1117,25 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap 1.9.3",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@@ -1183,12 +1214,72 @@ dependencies = [
|
||||
"itoa 1.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa 1.0.9",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
@@ -1308,6 +1399,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
@@ -1540,6 +1637,18 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[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"
|
||||
@@ -1550,6 +1659,35 @@ dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.6.0"
|
||||
@@ -1690,6 +1828,17 @@ dependencies = [
|
||||
"objc_exception",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
@@ -1733,6 +1882,50 @@ dependencies = [
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@@ -2206,6 +2399,70 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-util",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"winreg 0.50.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfd"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea"
|
||||
dependencies = [
|
||||
"block",
|
||||
"dispatch",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gtk-sys",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"raw-window-handle",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows 0.37.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
@@ -2261,6 +2518,15 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
@@ -2273,6 +2539,29 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "selectors"
|
||||
version = "0.22.0"
|
||||
@@ -2353,6 +2642,18 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa 1.0.9",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.4.0"
|
||||
@@ -2461,6 +2762,26 @@ version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soup2"
|
||||
version = "0.2.1"
|
||||
@@ -2558,6 +2879,27 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "5.0.0"
|
||||
@@ -2666,6 +3008,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.5",
|
||||
"bytes",
|
||||
"cocoa",
|
||||
"dirs-next",
|
||||
"embed_plist",
|
||||
@@ -2678,6 +3022,7 @@ dependencies = [
|
||||
"heck 0.4.1",
|
||||
"http",
|
||||
"ignore",
|
||||
"minisign-verify",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"open",
|
||||
@@ -2685,6 +3030,8 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"raw-window-handle",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rfd",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -2698,12 +3045,14 @@ dependencies = [
|
||||
"tauri-utils",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"url",
|
||||
"uuid",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"windows 0.39.0",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2967,8 +3316,36 @@ checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2 0.5.5",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3039,6 +3416,12 @@ dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
@@ -3109,6 +3492,12 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "7.0.0"
|
||||
@@ -3199,6 +3588,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.0.11"
|
||||
@@ -3247,6 +3642,15 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
@@ -3284,6 +3688,18 @@ dependencies = [
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.87"
|
||||
@@ -3313,6 +3729,29 @@ version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webkit2gtk"
|
||||
version = "0.18.2"
|
||||
@@ -3429,6 +3868,19 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.37.0",
|
||||
"windows_i686_gnu 0.37.0",
|
||||
"windows_i686_msvc 0.37.0",
|
||||
"windows_x86_64_gnu 0.37.0",
|
||||
"windows_x86_64_msvc 0.37.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.39.0"
|
||||
@@ -3544,6 +3996,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.39.0"
|
||||
@@ -3562,6 +4020,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.39.0"
|
||||
@@ -3580,6 +4044,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.39.0"
|
||||
@@ -3598,6 +4068,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.39.0"
|
||||
@@ -3628,6 +4104,12 @@ version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.39.0"
|
||||
@@ -3655,6 +4137,16 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.51.0"
|
||||
@@ -3732,3 +4224,14 @@ checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
@@ -7,14 +7,11 @@ license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.5", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1.5.2", features = ["shell-open"] }
|
||||
tauri = { version = "1.5.2", features = [ "updater", "shell-open"] }
|
||||
tokio = { version = "1.33", features = ["rt", "sync", "time", "fs"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use tauri::State;
|
||||
use tauri::{Manager, State};
|
||||
use tokio::time::sleep;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
@@ -9,7 +9,14 @@ use crate::{
|
||||
states::{app::ConnectionState, SharedAppState},
|
||||
};
|
||||
|
||||
#[instrument]
|
||||
const EVENT_CONNECTION: &str = "connection-state";
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
struct EventPayload {
|
||||
state: ConnectionState,
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[tauri::command]
|
||||
pub async fn get_connection_state(
|
||||
state: State<'_, SharedAppState>,
|
||||
@@ -19,8 +26,12 @@ pub async fn get_connection_state(
|
||||
Ok(app_state.state)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[tauri::command]
|
||||
pub async fn connect(state: State<'_, SharedAppState>) -> Result<ConnectionState, CommandError> {
|
||||
pub async fn connect(
|
||||
app: tauri::AppHandle,
|
||||
state: State<'_, SharedAppState>,
|
||||
) -> Result<ConnectionState, CommandError> {
|
||||
debug!("connect");
|
||||
let mut app_state = state.lock().await;
|
||||
let ConnectionState::Disconnected = app_state.state else {
|
||||
@@ -30,23 +41,46 @@ pub async fn connect(state: State<'_, SharedAppState>) -> Result<ConnectionState
|
||||
)));
|
||||
};
|
||||
|
||||
// switch to "Connecting" state
|
||||
app_state.state = ConnectionState::Connecting;
|
||||
// unlock the mutex
|
||||
drop(app_state);
|
||||
app.emit_all(
|
||||
EVENT_CONNECTION,
|
||||
EventPayload {
|
||||
state: ConnectionState::Connecting,
|
||||
},
|
||||
)
|
||||
.ok();
|
||||
|
||||
// TODO fake some delay to establish connection
|
||||
let app_state_cloned = state.inner().clone();
|
||||
let task = tokio::spawn(async move {
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
trace!("connected");
|
||||
app_state_cloned.lock().await.state = ConnectionState::Connected;
|
||||
debug!("sending event [{}]: connected", EVENT_CONNECTION);
|
||||
app.emit_all(
|
||||
EVENT_CONNECTION,
|
||||
EventPayload {
|
||||
state: ConnectionState::Connected,
|
||||
},
|
||||
)
|
||||
.ok();
|
||||
});
|
||||
|
||||
let _ = task.await;
|
||||
|
||||
app_state.state = ConnectionState::Connecting;
|
||||
let app_state = state.lock().await;
|
||||
Ok(app_state.state)
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
#[instrument(skip_all)]
|
||||
#[tauri::command]
|
||||
pub async fn disconnect(state: State<'_, SharedAppState>) -> Result<ConnectionState, CommandError> {
|
||||
pub async fn disconnect(
|
||||
app: tauri::AppHandle,
|
||||
state: State<'_, SharedAppState>,
|
||||
) -> Result<ConnectionState, CommandError> {
|
||||
debug!("disconnect");
|
||||
let mut app_state = state.lock().await;
|
||||
let ConnectionState::Connected = app_state.state else {
|
||||
@@ -56,6 +90,36 @@ pub async fn disconnect(state: State<'_, SharedAppState>) -> Result<ConnectionSt
|
||||
)));
|
||||
};
|
||||
|
||||
// switch to "Disconnecting" state
|
||||
app_state.state = ConnectionState::Disconnecting;
|
||||
// unlock the mutex
|
||||
drop(app_state);
|
||||
app.emit_all(
|
||||
EVENT_CONNECTION,
|
||||
EventPayload {
|
||||
state: ConnectionState::Disconnecting,
|
||||
},
|
||||
)
|
||||
.ok();
|
||||
|
||||
// TODO fake some delay to confirm disconnection
|
||||
let app_state_cloned = state.inner().clone();
|
||||
let task = tokio::spawn(async move {
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
trace!("disconnected");
|
||||
app_state_cloned.lock().await.state = ConnectionState::Disconnected;
|
||||
debug!("sending event [{}]: disconnected", EVENT_CONNECTION);
|
||||
app.emit_all(
|
||||
EVENT_CONNECTION,
|
||||
EventPayload {
|
||||
state: ConnectionState::Disconnected,
|
||||
},
|
||||
)
|
||||
.ok();
|
||||
});
|
||||
|
||||
let _ = task.await;
|
||||
|
||||
let app_state = state.lock().await;
|
||||
Ok(app_state.state)
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn run_tauri() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![greet])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
@@ -26,7 +26,7 @@ const APP_DATA_FILE: &str = "app-data.toml";
|
||||
const APP_CONFIG_FILE: &str = "config.toml";
|
||||
|
||||
fn main() -> Result<()> {
|
||||
dotenvy::dotenv()?;
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
// uses RUST_LOG value for logging level
|
||||
// eg. RUST_LOG=tauri=debug,nymvpn_ui=trace
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
"fullscreen": false,
|
||||
"resizable": true,
|
||||
"title": "NymVPN",
|
||||
"width": 200,
|
||||
"height": 200
|
||||
"width": 400,
|
||||
"height": 600
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+23
-46
@@ -1,54 +1,31 @@
|
||||
import React, { useState } from 'react';
|
||||
import { invoke } from '@tauri-apps/api/tauri';
|
||||
import { Button as BaseButton, ButtonProps } from '@mui/base/Button';
|
||||
import clsx from 'clsx';
|
||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
||||
import { Home, Settings, Error, PageLayout } from './pages';
|
||||
import { MainStateProvider } from './state';
|
||||
import './i18n/config';
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
(props, ref) => {
|
||||
const { className, ...other } = props;
|
||||
return (
|
||||
<BaseButton
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
'cursor-pointer disabled:cursor-not-allowed text-sm font-sans bg-violet-500 hover:bg-violet-600 active:bg-violet-700 text-white rounded-lg font-semibold px-4 py-2 border-none disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
element: <PageLayout />,
|
||||
children: [
|
||||
{
|
||||
path: '/',
|
||||
element: <Home />,
|
||||
errorElement: <Error />,
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
element: <Settings />,
|
||||
errorElement: <Error />,
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
]);
|
||||
|
||||
function App() {
|
||||
const [greetMsg, setGreetMsg] = useState('');
|
||||
const [name, setName] = useState('');
|
||||
|
||||
async function greet() {
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
setGreetMsg(await invoke('greet', { name }));
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Welcome to Tauri!</h1>
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
greet();
|
||||
}}
|
||||
>
|
||||
<input
|
||||
id="greet-input"
|
||||
onChange={(e) => setName(e.currentTarget.value)}
|
||||
placeholder="Enter a name..."
|
||||
/>
|
||||
<Button type="submit">Greet</Button>
|
||||
</form>
|
||||
|
||||
<p>{greetMsg}</p>
|
||||
</div>
|
||||
<MainStateProvider>
|
||||
<RouterProvider router={router} />
|
||||
</MainStateProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const ConnectionEvent = 'connection-state';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './main';
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
import { AppState } from '../types';
|
||||
import { initialState, StateAction } from '../state';
|
||||
|
||||
export const MainStateContext = createContext<AppState>(initialState);
|
||||
export const MainDispatchContext =
|
||||
createContext<React.Dispatch<StateAction> | null>(null);
|
||||
|
||||
export const useMainState = () => {
|
||||
return useContext(MainStateContext);
|
||||
};
|
||||
|
||||
export const useMainDispatch = () => {
|
||||
return useContext(MainDispatchContext);
|
||||
};
|
||||
@@ -1,11 +1,36 @@
|
||||
import { mockIPC, mockWindows } from '@tauri-apps/api/mocks';
|
||||
import { greet } from './tauri-cmd-mocks';
|
||||
import { ConnectionState } from '../types';
|
||||
import { emit } from '@tauri-apps/api/event';
|
||||
import { ConnectionEvent } from '../constants';
|
||||
|
||||
mockWindows('main');
|
||||
export function mockTauriIPC() {
|
||||
mockWindows('main');
|
||||
|
||||
mockIPC(async (cmd, args) => {
|
||||
console.log(`IPC call mocked "${cmd}"`);
|
||||
if (cmd === 'greet') {
|
||||
return greet(args.name as string);
|
||||
}
|
||||
});
|
||||
mockIPC(async (cmd, args) => {
|
||||
console.log(`IPC call mocked "${cmd}"`);
|
||||
console.log(args);
|
||||
if (cmd === 'connect') {
|
||||
await emit(ConnectionEvent, { state: 'Connecting' });
|
||||
return new Promise<ConnectionState>((resolve) =>
|
||||
setTimeout(async () => {
|
||||
await emit(ConnectionEvent, { state: 'Connected' });
|
||||
resolve('Connected');
|
||||
}, 2000),
|
||||
);
|
||||
}
|
||||
if (cmd === 'disconnect') {
|
||||
await emit(ConnectionEvent, { state: 'Disconnecting' });
|
||||
return new Promise<ConnectionState>((resolve) =>
|
||||
setTimeout(async () => {
|
||||
await emit(ConnectionEvent, { state: 'Disconnected' });
|
||||
resolve('Disconnected');
|
||||
}, 2000),
|
||||
);
|
||||
}
|
||||
if (cmd === 'get_connection_state') {
|
||||
return new Promise<ConnectionState>((resolve) =>
|
||||
setTimeout(() => resolve('Disconnected'), 2000),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export default function greet(name: string): string {
|
||||
return `Hello, ${name}!`;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default as greet } from './greet';
|
||||
@@ -0,0 +1,22 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import main from './en/main.json';
|
||||
|
||||
const defaultNS = 'main';
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
lng: 'en',
|
||||
debug: import.meta.env.DEV,
|
||||
resources: {
|
||||
en: {
|
||||
main,
|
||||
},
|
||||
},
|
||||
defaultNS,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"connect": "Connect",
|
||||
"disconnect": "Disconnect"
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import { mockTauriIPC } from './dev/setup';
|
||||
import './styles.css';
|
||||
|
||||
if (import.meta.env.MODE === 'dev-browser') {
|
||||
console.log('Running in dev-browser mode. Mocking tauri window and IPCs');
|
||||
import('./dev/setup');
|
||||
mockTauriIPC();
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useRouteError } from 'react-router-dom';
|
||||
|
||||
type routerErrorType = {
|
||||
statusText: string;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export default function ErrorPage() {
|
||||
const error: routerErrorType = useRouteError() as unknown as routerErrorType;
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<div id="error-page">
|
||||
<h1>Oops!</h1>
|
||||
<p>Sorry, an unexpected error has occurred.</p>
|
||||
<p>
|
||||
<i>{error.statusText || error.message}</i>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { useMainDispatch, useMainState } from '../contexts';
|
||||
import { StateDispatch } from '../types';
|
||||
|
||||
function Home() {
|
||||
const state = useMainState();
|
||||
const dispatch = useMainDispatch() as StateDispatch;
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClick = async () => {
|
||||
if (state.state === 'Connected') {
|
||||
dispatch({ type: 'disconnect' });
|
||||
invoke('disconnect').then((result) => {
|
||||
console.log(result);
|
||||
});
|
||||
} else if (state.state === 'Disconnected') {
|
||||
dispatch({ type: 'connect' });
|
||||
invoke('connect').then((result) => {
|
||||
console.log(result);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>NymVPN</h2>
|
||||
connection state: {state.state}
|
||||
{state.loading ? (
|
||||
'loading…'
|
||||
) : (
|
||||
<button onClick={handleClick}>
|
||||
{state.state === 'Disconnected' ? t('connect') : t('disconnect')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default as PageLayout } from './pageLayout';
|
||||
export { default as Home } from './home';
|
||||
export { default as Settings } from './settings';
|
||||
export { default as Error } from './error';
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
function PageLayout() {
|
||||
return (
|
||||
<div>
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PageLayout;
|
||||
@@ -0,0 +1,5 @@
|
||||
function Settings() {
|
||||
return <div>Settings</div>;
|
||||
}
|
||||
|
||||
export default Settings;
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './main';
|
||||
export * from './provider';
|
||||
@@ -0,0 +1,35 @@
|
||||
import { AppState, ConnectionState } from '../types';
|
||||
|
||||
export type StateAction =
|
||||
| { type: 'change-connection-state'; state: ConnectionState }
|
||||
| { type: 'connect' }
|
||||
| { type: 'disconnect' }
|
||||
| { type: 'reset' };
|
||||
|
||||
export const initialState: AppState = {
|
||||
state: 'Disconnected',
|
||||
loading: false,
|
||||
privacyMode: 'High',
|
||||
tunnel: { name: 'nym', id: 'nym' },
|
||||
};
|
||||
|
||||
export function reducer(state: AppState, action: StateAction): AppState {
|
||||
switch (action.type) {
|
||||
case 'change-connection-state': {
|
||||
return {
|
||||
...state,
|
||||
state: action.state,
|
||||
loading:
|
||||
action.state === 'Connecting' || action.state === 'Disconnecting',
|
||||
};
|
||||
}
|
||||
case 'connect': {
|
||||
return { ...state, state: 'Connecting', loading: true };
|
||||
}
|
||||
case 'disconnect': {
|
||||
return { ...state, state: 'Disconnecting', loading: true };
|
||||
}
|
||||
case 'reset':
|
||||
return initialState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { useEffect, useReducer } from 'react';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { initialState, reducer } from './main';
|
||||
import { useTauriEvents } from './useTauriEvents';
|
||||
import { MainDispatchContext, MainStateContext } from '../contexts';
|
||||
import { ConnectionState } from '../types';
|
||||
|
||||
type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export function MainStateProvider({ children }: Props) {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
|
||||
useTauriEvents(dispatch);
|
||||
|
||||
// initialize connection state
|
||||
useEffect(() => {
|
||||
const getInitialConnectionState = async () => {
|
||||
return await invoke<ConnectionState>('get_connection_state');
|
||||
};
|
||||
|
||||
getInitialConnectionState().then((state) =>
|
||||
dispatch({ type: 'change-connection-state', state }),
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MainStateContext.Provider value={state}>
|
||||
<MainDispatchContext.Provider value={dispatch}>
|
||||
{children}
|
||||
</MainDispatchContext.Provider>
|
||||
</MainStateContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { EventPayload, StateDispatch } from '../types';
|
||||
import { ConnectionEvent } from '../constants';
|
||||
|
||||
export function useTauriEvents(dispatch: StateDispatch) {
|
||||
const registerListener = useCallback(() => {
|
||||
return listen<EventPayload>(ConnectionEvent, (event) => {
|
||||
console.log(
|
||||
`received event ${event.event}, state: ${event.payload.state}`,
|
||||
);
|
||||
switch (event.payload.state) {
|
||||
case 'Connected':
|
||||
dispatch({ type: 'change-connection-state', state: 'Connected' });
|
||||
break;
|
||||
case 'Disconnected':
|
||||
dispatch({ type: 'change-connection-state', state: 'Disconnected' });
|
||||
break;
|
||||
case 'Connecting':
|
||||
dispatch({ type: 'change-connection-state', state: 'Connecting' });
|
||||
break;
|
||||
case 'Disconnecting':
|
||||
dispatch({ type: 'change-connection-state', state: 'Disconnecting' });
|
||||
break;
|
||||
case 'Error':
|
||||
break;
|
||||
}
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
// register/unregister event listener
|
||||
useEffect(() => {
|
||||
const unlisten = registerListener();
|
||||
|
||||
return () => {
|
||||
unlisten.then((f) => f());
|
||||
};
|
||||
}, [registerListener]);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Dispatch } from 'react';
|
||||
import { StateAction } from '../state';
|
||||
|
||||
export type ConnectionState =
|
||||
| 'Connected'
|
||||
| 'Disconnected'
|
||||
| 'Connecting'
|
||||
| 'Disconnecting'
|
||||
| 'Error';
|
||||
|
||||
export type PrivacyMode = 'High' | 'Medium' | 'Low';
|
||||
|
||||
export interface TunnelConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type AppState = {
|
||||
state: ConnectionState;
|
||||
loading: boolean;
|
||||
privacyMode: PrivacyMode;
|
||||
tunnel: TunnelConfig;
|
||||
};
|
||||
|
||||
export type EventPayload = {
|
||||
state: ConnectionState;
|
||||
};
|
||||
|
||||
export type StateDispatch = Dispatch<StateAction>;
|
||||
@@ -0,0 +1 @@
|
||||
export * from './app-state';
|
||||
+843
-697
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user