feat: Nostr Auto Updater (#16)
* clean up * fix version * add auto updater * add windows
This commit is contained in:
173
Cargo.lock
generated
173
Cargo.lock
generated
@@ -4,7 +4,7 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "account"
|
name = "account"
|
||||||
version = "0.0.0"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
@@ -429,6 +429,21 @@ version = "1.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "auto_update"
|
||||||
|
version = "0.1.4"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"common",
|
||||||
|
"global",
|
||||||
|
"gpui",
|
||||||
|
"log",
|
||||||
|
"nostr-sdk",
|
||||||
|
"reqwest 0.12.15",
|
||||||
|
"smol",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -944,7 +959,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chats"
|
name = "chats"
|
||||||
version = "0.0.0"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"account",
|
"account",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -1058,7 +1073,7 @@ dependencies = [
|
|||||||
"cocoa-foundation 0.1.2",
|
"cocoa-foundation 0.1.2",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"core-graphics 0.23.2",
|
"core-graphics 0.23.2",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
@@ -1074,7 +1089,7 @@ dependencies = [
|
|||||||
"cocoa-foundation 0.2.0",
|
"cocoa-foundation 0.2.0",
|
||||||
"core-foundation 0.10.0",
|
"core-foundation 0.10.0",
|
||||||
"core-graphics 0.24.0",
|
"core-graphics 0.24.0",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
@@ -1151,7 +1166,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "0.0.0"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -1205,6 +1220,7 @@ version = "0.1.4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"account",
|
"account",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"auto_update",
|
||||||
"chats",
|
"chats",
|
||||||
"common",
|
"common",
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
@@ -1262,7 +1278,7 @@ dependencies = [
|
|||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"core-graphics-types 0.1.3",
|
"core-graphics-types 0.1.3",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1275,7 +1291,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"core-foundation 0.10.0",
|
"core-foundation 0.10.0",
|
||||||
"core-graphics-types 0.2.0",
|
"core-graphics-types 0.2.0",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1288,7 +1304,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"core-graphics-types 0.1.3",
|
"core-graphics-types 0.1.3",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1335,7 +1351,7 @@ checksum = "a593227b66cbd4007b2a050dfdd9e1d1318311409c8d600dc82ba1b15ca9c130"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation 0.10.0",
|
"core-foundation 0.10.0",
|
||||||
"core-graphics 0.24.0",
|
"core-graphics 0.24.0",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1946,6 +1962,15 @@ dependencies = [
|
|||||||
"ttf-parser 0.25.1",
|
"ttf-parser 0.25.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared 0.1.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types"
|
name = "foreign-types"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -1953,7 +1978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"foreign-types-macros",
|
"foreign-types-macros",
|
||||||
"foreign-types-shared",
|
"foreign-types-shared 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1967,6 +1992,12 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types-shared"
|
name = "foreign-types-shared"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -2197,7 +2228,7 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "global"
|
name = "global"
|
||||||
version = "0.0.0"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
"nostr-sdk",
|
"nostr-sdk",
|
||||||
@@ -2305,7 +2336,7 @@ dependencies = [
|
|||||||
"filedescriptor",
|
"filedescriptor",
|
||||||
"flume",
|
"flume",
|
||||||
"font-kit",
|
"font-kit",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"futures",
|
"futures",
|
||||||
"gpui_macros",
|
"gpui_macros",
|
||||||
"http_client",
|
"http_client",
|
||||||
@@ -2659,6 +2690,22 @@ dependencies = [
|
|||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
@@ -3339,7 +3386,7 @@ dependencies = [
|
|||||||
"core-foundation 0.10.0",
|
"core-foundation 0.10.0",
|
||||||
"core-video",
|
"core-video",
|
||||||
"ctor",
|
"ctor",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"metal",
|
"metal",
|
||||||
"objc",
|
"objc",
|
||||||
"workspace-hack",
|
"workspace-hack",
|
||||||
@@ -3378,7 +3425,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block",
|
"block",
|
||||||
"core-graphics-types 0.1.3",
|
"core-graphics-types 0.1.3",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"log",
|
"log",
|
||||||
"objc",
|
"objc",
|
||||||
"paste",
|
"paste",
|
||||||
@@ -3463,6 +3510,23 @@ dependencies = [
|
|||||||
"getrandom 0.2.15",
|
"getrandom 0.2.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework 2.11.1",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "negentropy"
|
name = "negentropy"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -4048,12 +4112,50 @@ dependencies = [
|
|||||||
"pathdiff",
|
"pathdiff",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types 0.3.2",
|
||||||
|
"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.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option-ext"
|
name = "option-ext"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -4801,19 +4903,23 @@ checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
|
"native-tls",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -4825,14 +4931,18 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-socks",
|
"tokio-socks",
|
||||||
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
"windows-registry 0.4.0",
|
"windows-registry 0.4.0",
|
||||||
@@ -5013,7 +5123,7 @@ dependencies = [
|
|||||||
"openssl-probe",
|
"openssl-probe",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"schannel",
|
"schannel",
|
||||||
"security-framework",
|
"security-framework 3.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5049,7 +5159,7 @@ dependencies = [
|
|||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"rustls-platform-verifier-android",
|
"rustls-platform-verifier-android",
|
||||||
"rustls-webpki",
|
"rustls-webpki",
|
||||||
"security-framework",
|
"security-framework 3.2.0",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
@@ -5266,6 +5376,19 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"core-foundation 0.9.4",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@@ -6071,6 +6194,16 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "tokio-rustls"
|
name = "tokio-rustls"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@@ -6311,7 +6444,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ui"
|
name = "ui"
|
||||||
version = "0.0.0"
|
version = "0.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -6601,6 +6734,12 @@ dependencies = [
|
|||||||
"sval_serde",
|
"sval_serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ members = ["crates/*"]
|
|||||||
default-members = ["crates/app"]
|
default-members = ["crates/app"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
publish = false
|
version = "0.1.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
coop = { path = "crates/*" }
|
coop = { path = "crates/*" }
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ name = "coop"
|
|||||||
description = "Coop is a cross-platform Nostr client designed for secure communication focus on simplicity and customizability."
|
description = "Coop is a cross-platform Nostr client designed for secure communication focus on simplicity and customizability."
|
||||||
product-name = "Coop"
|
product-name = "Coop"
|
||||||
identifier = "su.reya.coop"
|
identifier = "su.reya.coop"
|
||||||
version = "0.1.4"
|
|
||||||
resources = ["assets/*/*", "Cargo.toml", "./LICENSE", "./README.md"]
|
resources = ["assets/*/*", "Cargo.toml", "./LICENSE", "./README.md"]
|
||||||
icons = [
|
icons = [
|
||||||
"assets/brand/32x32.png",
|
"assets/brand/32x32.png",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "account"
|
name = "account"
|
||||||
version = "0.0.0"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "coop"
|
name = "coop"
|
||||||
version = "0.1.4"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ common = { path = "../common" }
|
|||||||
global = { path = "../global" }
|
global = { path = "../global" }
|
||||||
chats = { path = "../chats" }
|
chats = { path = "../chats" }
|
||||||
account = { path = "../account" }
|
account = { path = "../account" }
|
||||||
|
auto_update = { path = "../auto_update" }
|
||||||
|
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
reqwest_client.workspace = true
|
reqwest_client.workspace = true
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
use asset::Assets;
|
use asset::Assets;
|
||||||
|
use auto_update::AutoUpdater;
|
||||||
use chats::ChatRegistry;
|
use chats::ChatRegistry;
|
||||||
use futures::{select, FutureExt};
|
use futures::{select, FutureExt};
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
use global::constants::APP_NAME;
|
use global::constants::APP_NAME;
|
||||||
use global::{
|
use global::{
|
||||||
constants::{ALL_MESSAGES_SUB_ID, APP_ID, BOOTSTRAP_RELAYS, NEW_MESSAGE_SUB_ID},
|
constants::{ALL_MESSAGES_SUB_ID, APP_ID, APP_PUBKEY, BOOTSTRAP_RELAYS, NEW_MESSAGE_SUB_ID},
|
||||||
get_client,
|
get_client,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -17,9 +18,9 @@ use gpui::{point, SharedString, TitlebarOptions};
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use gpui::{WindowBackgroundAppearance, WindowDecorations};
|
use gpui::{WindowBackgroundAppearance, WindowDecorations};
|
||||||
use nostr_sdk::{
|
use nostr_sdk::{
|
||||||
pool::prelude::ReqExitPolicy, Event, EventBuilder, EventId, Filter, JsonUtil, Keys, Kind,
|
nips::nip01::Coordinate, pool::prelude::ReqExitPolicy, Client, Event, EventBuilder, EventId,
|
||||||
Metadata, PublicKey, RelayMessage, RelayPoolNotification, SubscribeAutoCloseOptions,
|
Filter, JsonUtil, Keys, Kind, Metadata, PublicKey, RelayMessage, RelayPoolNotification,
|
||||||
SubscriptionId, Tag,
|
SubscribeAutoCloseOptions, SubscriptionId, Tag,
|
||||||
};
|
};
|
||||||
use smol::Timer;
|
use smol::Timer;
|
||||||
use std::{collections::HashSet, mem, sync::Arc, time::Duration};
|
use std::{collections::HashSet, mem, sync::Arc, time::Duration};
|
||||||
@@ -37,8 +38,10 @@ enum Signal {
|
|||||||
Event(Event),
|
Event(Event),
|
||||||
/// Receive metadata
|
/// Receive metadata
|
||||||
Metadata(Box<(PublicKey, Option<Metadata>)>),
|
Metadata(Box<(PublicKey, Option<Metadata>)>),
|
||||||
/// Receive EOSE
|
/// Receive eose
|
||||||
Eose,
|
Eose,
|
||||||
|
/// Receive app updates
|
||||||
|
AppUpdates(Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -47,11 +50,12 @@ fn main() {
|
|||||||
// Fix crash on startup
|
// Fix crash on startup
|
||||||
_ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
_ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||||
|
|
||||||
let (event_tx, event_rx) = smol::channel::bounded::<Signal>(1024);
|
let (event_tx, event_rx) = smol::channel::bounded::<Signal>(2048);
|
||||||
let (batch_tx, batch_rx) = smol::channel::bounded::<Vec<PublicKey>>(500);
|
let (batch_tx, batch_rx) = smol::channel::bounded::<Vec<PublicKey>>(500);
|
||||||
|
|
||||||
// Initialize nostr client
|
// Initialize nostr client
|
||||||
let client = get_client();
|
let client = get_client();
|
||||||
|
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||||
|
|
||||||
// Initialize application
|
// Initialize application
|
||||||
let app = Application::new()
|
let app = Application::new()
|
||||||
@@ -60,12 +64,36 @@ fn main() {
|
|||||||
|
|
||||||
// Connect to default relays
|
// Connect to default relays
|
||||||
app.background_executor()
|
app.background_executor()
|
||||||
.spawn(async {
|
.spawn(async move {
|
||||||
for relay in BOOTSTRAP_RELAYS.into_iter() {
|
for relay in BOOTSTRAP_RELAYS.into_iter() {
|
||||||
_ = client.add_relay(relay).await;
|
if let Err(e) = client.add_relay(relay).await {
|
||||||
|
log::error!("Failed to add relay {}: {}", relay, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = client.connect().await
|
// Establish connection to bootstrap relays
|
||||||
|
client.connect().await;
|
||||||
|
|
||||||
|
log::info!("Connected to bootstrap relays");
|
||||||
|
log::info!("Subscribing to app updates...");
|
||||||
|
|
||||||
|
let coordinate = Coordinate {
|
||||||
|
kind: Kind::Custom(32267),
|
||||||
|
public_key: PublicKey::from_hex(APP_PUBKEY).expect("App Pubkey is invalid"),
|
||||||
|
identifier: APP_ID.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let filter = Filter::new()
|
||||||
|
.kind(Kind::ArticlesCurationSet)
|
||||||
|
.coordinate(&coordinate)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if let Err(e) = client
|
||||||
|
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::error!("Failed to subscribe for app updates: {}", e);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
@@ -86,7 +114,7 @@ fn main() {
|
|||||||
Ok(keys) => {
|
Ok(keys) => {
|
||||||
batch.extend(keys);
|
batch.extend(keys);
|
||||||
if batch.len() >= BATCH_SIZE {
|
if batch.len() >= BATCH_SIZE {
|
||||||
sync_metadata(mem::take(&mut batch)).await;
|
sync_metadata(mem::take(&mut batch), client, opts).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
@@ -94,7 +122,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
_ = timeout => {
|
_ = timeout => {
|
||||||
if !batch.is_empty() {
|
if !batch.is_empty() {
|
||||||
sync_metadata(mem::take(&mut batch)).await;
|
sync_metadata(mem::take(&mut batch), client, opts).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,6 +203,23 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Kind::ReleaseArtifactSet => {
|
||||||
|
let filter = Filter::new()
|
||||||
|
.ids(event.tags.event_ids().copied())
|
||||||
|
.kind(Kind::FileMetadata);
|
||||||
|
|
||||||
|
if let Err(e) = client
|
||||||
|
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::error!("Failed to subscribe for file metadata: {}", e);
|
||||||
|
} else {
|
||||||
|
event_tx
|
||||||
|
.send(Signal::AppUpdates(event.into_owned()))
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,13 +286,20 @@ fn main() {
|
|||||||
cx.new(|cx| {
|
cx.new(|cx| {
|
||||||
// Initialize components
|
// Initialize components
|
||||||
ui::init(cx);
|
ui::init(cx);
|
||||||
|
|
||||||
|
// Initialize auto update
|
||||||
|
auto_update::init(cx);
|
||||||
|
|
||||||
// Initialize chat state
|
// Initialize chat state
|
||||||
chats::init(cx);
|
chats::init(cx);
|
||||||
|
|
||||||
// Initialize account state
|
// Initialize account state
|
||||||
account::init(cx);
|
account::init(cx);
|
||||||
|
|
||||||
// Spawn a task to handle events from nostr channel
|
// Spawn a task to handle events from nostr channel
|
||||||
cx.spawn_in(window, async move |_, cx| {
|
cx.spawn_in(window, async move |_, cx| {
|
||||||
let chats = cx.update(|_, cx| ChatRegistry::global(cx)).unwrap();
|
let chats = cx.update(|_, cx| ChatRegistry::global(cx)).unwrap();
|
||||||
|
let auto_updater = cx.update(|_, cx| AutoUpdater::global(cx)).unwrap();
|
||||||
|
|
||||||
while let Ok(signal) = event_rx.recv().await {
|
while let Ok(signal) = event_rx.recv().await {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
@@ -269,6 +321,12 @@ fn main() {
|
|||||||
this.load_rooms(window, cx)
|
this.load_rooms(window, cx)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Signal::AppUpdates(event) => {
|
||||||
|
// TODO: add settings for auto updates
|
||||||
|
auto_updater.update(cx, |this, cx| {
|
||||||
|
this.update(event, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
@@ -310,10 +368,11 @@ async fn get_unwrapped(gift_wrap: EventId) -> Result<Event, Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sync_metadata(buffer: HashSet<PublicKey>) {
|
async fn sync_metadata(
|
||||||
let client = get_client();
|
buffer: HashSet<PublicKey>,
|
||||||
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
client: &Client,
|
||||||
|
opts: SubscribeAutoCloseOptions,
|
||||||
|
) {
|
||||||
let kinds = vec![
|
let kinds = vec![
|
||||||
Kind::Metadata,
|
Kind::Metadata,
|
||||||
Kind::ContactList,
|
Kind::ContactList,
|
||||||
|
|||||||
18
crates/auto_update/Cargo.toml
Normal file
18
crates/auto_update/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "auto_update"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
publish.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { path = "../common" }
|
||||||
|
global = { path = "../global" }
|
||||||
|
|
||||||
|
gpui.workspace = true
|
||||||
|
nostr-sdk.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
|
smol.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
|
||||||
|
tempfile = "3.19.1"
|
||||||
|
reqwest = { version = "0.12", features = ["stream"] }
|
||||||
350
crates/auto_update/src/lib.rs
Normal file
350
crates/auto_update/src/lib.rs
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
use std::{
|
||||||
|
env::{self, consts::OS},
|
||||||
|
ffi::OsString,
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Context as _, Error};
|
||||||
|
use global::get_client;
|
||||||
|
use gpui::{App, AppContext, Context, Entity, Global, SemanticVersion, Task};
|
||||||
|
use nostr_sdk::prelude::*;
|
||||||
|
use smol::{
|
||||||
|
fs::{self, File},
|
||||||
|
io::AsyncWriteExt,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
struct GlobalAutoUpdate(Entity<AutoUpdater>);
|
||||||
|
|
||||||
|
impl Global for GlobalAutoUpdate {}
|
||||||
|
|
||||||
|
pub fn init(cx: &mut App) {
|
||||||
|
let env = env!("CARGO_PKG_VERSION");
|
||||||
|
let current_version: SemanticVersion = env.parse().expect("Invalid version in Cargo.toml");
|
||||||
|
|
||||||
|
AutoUpdater::set_global(
|
||||||
|
cx.new(|_| AutoUpdater {
|
||||||
|
current_version,
|
||||||
|
status: AutoUpdateStatus::Idle,
|
||||||
|
}),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MacOsUnmounter {
|
||||||
|
mount_path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for MacOsUnmounter {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let unmount_output = std::process::Command::new("hdiutil")
|
||||||
|
.args(["detach", "-force"])
|
||||||
|
.arg(&self.mount_path)
|
||||||
|
.output();
|
||||||
|
|
||||||
|
match unmount_output {
|
||||||
|
Ok(output) if output.status.success() => {
|
||||||
|
log::info!("Successfully unmounted the disk image");
|
||||||
|
}
|
||||||
|
Ok(output) => {
|
||||||
|
log::error!(
|
||||||
|
"Failed to unmount disk image: {:?}",
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
log::error!("Error while trying to unmount disk image: {:?}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum AutoUpdateStatus {
|
||||||
|
Idle,
|
||||||
|
Checking,
|
||||||
|
Downloading,
|
||||||
|
Installing,
|
||||||
|
Updated { binary_path: PathBuf },
|
||||||
|
Errored,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AutoUpdateStatus {
|
||||||
|
pub fn is_updated(&self) -> bool {
|
||||||
|
matches!(self, Self::Updated { .. })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AutoUpdater {
|
||||||
|
status: AutoUpdateStatus,
|
||||||
|
current_version: SemanticVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AutoUpdater {
|
||||||
|
pub fn global(cx: &App) -> Entity<Self> {
|
||||||
|
cx.global::<GlobalAutoUpdate>().0.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_global(auto_updater: Entity<Self>, cx: &mut App) {
|
||||||
|
cx.set_global(GlobalAutoUpdate(auto_updater));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_version(&self) -> SemanticVersion {
|
||||||
|
self.current_version
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status(&self) -> AutoUpdateStatus {
|
||||||
|
self.status.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_status(&mut self, status: AutoUpdateStatus, cx: &mut Context<Self>) {
|
||||||
|
self.status = status;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, event: Event, cx: &mut Context<Self>) {
|
||||||
|
self.set_status(AutoUpdateStatus::Checking, cx);
|
||||||
|
|
||||||
|
// Extract the version from the identifier tag
|
||||||
|
let ident = match event.tags.identifier() {
|
||||||
|
Some(i) => match i.split('@').next_back() {
|
||||||
|
Some(i) => i,
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert the version string to a SemanticVersion
|
||||||
|
let new_version: SemanticVersion = ident.parse().expect("Invalid version");
|
||||||
|
|
||||||
|
// Check if the new version is the same as the current version
|
||||||
|
if self.current_version == new_version {
|
||||||
|
self.set_status(AutoUpdateStatus::Idle, cx);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Download the new version
|
||||||
|
self.set_status(AutoUpdateStatus::Downloading, cx);
|
||||||
|
|
||||||
|
let task: Task<Result<(TempDir, PathBuf), Error>> = cx.background_spawn(async move {
|
||||||
|
let client = get_client();
|
||||||
|
let ids = event.tags.event_ids().copied();
|
||||||
|
let filter = Filter::new().ids(ids).kind(Kind::FileMetadata);
|
||||||
|
let events = client.database().query(filter).await?;
|
||||||
|
|
||||||
|
if let Some(event) = events.into_iter().find(|event| event.content == OS) {
|
||||||
|
let tag = event.tags.find(TagKind::Url).context("url not found")?;
|
||||||
|
let url = Url::parse(tag.content().context("invalid")?)?;
|
||||||
|
|
||||||
|
let temp_dir = tempfile::Builder::new().prefix("coop-update").tempdir()?;
|
||||||
|
let filename = match OS {
|
||||||
|
"macos" => Ok("Coop.dmg"),
|
||||||
|
"linux" => Ok("Coop.tar.gz"),
|
||||||
|
"windows" => Ok("CoopUpdateInstaller.exe"),
|
||||||
|
_ => Err(anyhow!("not supported: {:?}", OS)),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let downloaded_asset = temp_dir.path().join(filename);
|
||||||
|
let mut target_file = File::create(&downloaded_asset).await?;
|
||||||
|
|
||||||
|
let response = reqwest::get(url).await?;
|
||||||
|
let mut stream = response.bytes_stream();
|
||||||
|
|
||||||
|
while let Some(item) = stream.next().await {
|
||||||
|
let chunk = item?;
|
||||||
|
target_file.write_all(&chunk).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("downloaded update. path:{:?}", downloaded_asset);
|
||||||
|
|
||||||
|
Ok((temp_dir, downloaded_asset))
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Not found"))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
if let Ok((temp_dir, downloaded_asset)) = task.await {
|
||||||
|
cx.update(|cx| {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.set_status(AutoUpdateStatus::Installing, cx);
|
||||||
|
|
||||||
|
match OS {
|
||||||
|
"macos" => this.install_release_macos(temp_dir, downloaded_asset, cx),
|
||||||
|
"linux" => this.install_release_linux(temp_dir, downloaded_asset, cx),
|
||||||
|
"windows" => this.install_release_windows(downloaded_asset, cx),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn install_release_macos(&mut self, temp_dir: TempDir, asset: PathBuf, cx: &mut Context<Self>) {
|
||||||
|
let running_app_path = cx.app_path().unwrap();
|
||||||
|
let running_app_filename = running_app_path.file_name().unwrap();
|
||||||
|
|
||||||
|
let mount_path = temp_dir.path().join("Coop");
|
||||||
|
|
||||||
|
let mut mounted_app_path: OsString = mount_path.join(running_app_filename).into();
|
||||||
|
mounted_app_path.push("/");
|
||||||
|
|
||||||
|
let task: Task<Result<PathBuf, Error>> = cx.background_spawn(async move {
|
||||||
|
let output = Command::new("hdiutil")
|
||||||
|
.args(["attach", "-nobrowse"])
|
||||||
|
.arg(&asset)
|
||||||
|
.arg("-mountroot")
|
||||||
|
.arg(temp_dir.path())
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
anyhow::ensure!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to mount: {:?}",
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create an MacOsUnmounter that will be dropped (and thus unmount the disk) when this function exits
|
||||||
|
let _unmounter = MacOsUnmounter {
|
||||||
|
mount_path: mount_path.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let output = Command::new("rsync")
|
||||||
|
.args(["-av", "--delete"])
|
||||||
|
.arg(&mounted_app_path)
|
||||||
|
.arg(&running_app_path)
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
anyhow::ensure!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to copy app: {:?}",
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(running_app_path)
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
if let Ok(binary_path) = task.await {
|
||||||
|
cx.update(|cx| {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.status = AutoUpdateStatus::Updated { binary_path };
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn install_release_linux(&mut self, temp_dir: TempDir, asset: PathBuf, cx: &mut Context<Self>) {
|
||||||
|
let home_dir = PathBuf::from(env::var("HOME").unwrap());
|
||||||
|
let running_app_path = cx.app_path().unwrap();
|
||||||
|
let extracted = temp_dir.path().join("coop");
|
||||||
|
|
||||||
|
let task: Task<Result<PathBuf, Error>> = cx.background_spawn(async move {
|
||||||
|
fs::create_dir_all(&extracted).await?;
|
||||||
|
|
||||||
|
let output = Command::new("tar")
|
||||||
|
.arg("-xzf")
|
||||||
|
.arg(&asset)
|
||||||
|
.arg("-C")
|
||||||
|
.arg(&extracted)
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
anyhow::ensure!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to extract {:?} to {:?}: {:?}",
|
||||||
|
asset,
|
||||||
|
extracted,
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
let app_folder_name: String = "coop.app".into();
|
||||||
|
let from = extracted.join(&app_folder_name);
|
||||||
|
let mut to = home_dir.join(".local");
|
||||||
|
|
||||||
|
let expected_suffix = format!("{}/libexec/coop", app_folder_name);
|
||||||
|
|
||||||
|
if let Some(prefix) = running_app_path
|
||||||
|
.to_str()
|
||||||
|
.and_then(|str| str.strip_suffix(&expected_suffix))
|
||||||
|
{
|
||||||
|
to = PathBuf::from(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Command::new("rsync")
|
||||||
|
.args(["-av", "--delete"])
|
||||||
|
.arg(&from)
|
||||||
|
.arg(&to)
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
anyhow::ensure!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to copy Coop update from {:?} to {:?}: {:?}",
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(to.join(expected_suffix))
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
if let Ok(binary_path) = task.await {
|
||||||
|
cx.update(|cx| {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.status = AutoUpdateStatus::Updated { binary_path };
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn install_release_windows(&mut self, asset: PathBuf, cx: &mut Context<Self>) {
|
||||||
|
let task: Task<Result<PathBuf, Error>> = cx.background_spawn(async move {
|
||||||
|
let output = Command::new(asset)
|
||||||
|
.arg("/verysilent")
|
||||||
|
.arg("/update=true")
|
||||||
|
.arg("!desktopicon")
|
||||||
|
.arg("!quicklaunchicon")
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
anyhow::ensure!(
|
||||||
|
output.status.success(),
|
||||||
|
"failed to start installer: {:?}",
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
Ok(std::env::current_exe()?)
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
if let Ok(binary_path) = task.await {
|
||||||
|
cx.update(|cx| {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.status = AutoUpdateStatus::Updated { binary_path };
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "chats"
|
name = "chats"
|
||||||
version = "0.0.0"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "common"
|
name = "common"
|
||||||
version = "0.0.0"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "global"
|
name = "global"
|
||||||
version = "0.0.0"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
pub const APP_NAME: &str = "Coop";
|
pub const APP_NAME: &str = "Coop";
|
||||||
pub const APP_ID: &str = "su.reya.coop";
|
pub const APP_ID: &str = "su.reya.coop";
|
||||||
|
pub const APP_PUBKEY: &str = "b1813fb01274b32cc5db6d1198e7c79dda0fb430899f63c7064f651a41d44f2b";
|
||||||
|
|
||||||
/// Bootstrap relays
|
/// Bootstrap relays
|
||||||
pub const BOOTSTRAP_RELAYS: [&str; 5] = [
|
pub const BOOTSTRAP_RELAYS: [&str; 5] = [
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ui"
|
name = "ui"
|
||||||
version = "0.0.0"
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user