Compare commits
10
Commits
003ec3270b
...
aeb5568727
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aeb5568727 | ||
|
|
07dddd569e | ||
|
|
6adf7ba465 | ||
|
|
57d6794ad6 | ||
|
|
fda083bb65 | ||
|
|
3e43ffa6cf | ||
|
|
bfcc111817 | ||
|
|
d1ead872b1 | ||
|
|
f5be0ea510 | ||
|
|
f1a0124227 |
No files matched your search
@@ -70,6 +70,18 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
# Build from the tag we're releasing, not the branch the workflow
|
||||
# was dispatched from. Without this the binary's Cargo.toml version
|
||||
# and embedded SHA reflect whatever was on the dispatch branch.
|
||||
ref: refs/tags/${{ github.event.inputs.post }}
|
||||
|
||||
- name: Resolve release commit SHA
|
||||
shell: bash
|
||||
run: |
|
||||
sha=$(git rev-parse HEAD)
|
||||
echo "DIOXUS_CLI_GIT_SHA=$sha" >> "$GITHUB_ENV"
|
||||
echo "DIOXUS_CLI_GIT_SHA_SHORT=${sha:0:7}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Install openssl on macos
|
||||
if: matrix.platform.os == 'macos-latest'
|
||||
|
||||
Generated
+56
-56
@@ -3110,7 +3110,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "depinfo"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
@@ -3246,7 +3246,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"dioxus",
|
||||
@@ -3288,7 +3288,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-asset-resolver"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-cli-config",
|
||||
@@ -3309,7 +3309,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-autofmt"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-rsx",
|
||||
"pretty_assertions",
|
||||
@@ -3323,7 +3323,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-cli"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"ansi-to-html",
|
||||
"ansi-to-tui",
|
||||
@@ -3451,7 +3451,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-cli-config"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -3467,7 +3467,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-cli-telemetry"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dirs",
|
||||
@@ -3479,7 +3479,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-component-manifest"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"schemars 1.2.1",
|
||||
"serde",
|
||||
@@ -3488,7 +3488,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-config-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3496,11 +3496,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-config-macros"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-core"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"const_format",
|
||||
@@ -3531,7 +3531,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-core-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"dioxus",
|
||||
@@ -3547,11 +3547,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-core-types"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-desktop"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3612,7 +3612,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-devtools"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-cli-config",
|
||||
"dioxus-core",
|
||||
@@ -3631,7 +3631,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-devtools-types"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-core",
|
||||
"serde",
|
||||
@@ -3640,7 +3640,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-document"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
@@ -3658,7 +3658,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-dx-wire-format"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
"manganis-core",
|
||||
@@ -3707,7 +3707,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-ext"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-autofmt",
|
||||
"dioxus-rsx-rosetta",
|
||||
@@ -3718,7 +3718,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-fullstack"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@@ -3785,7 +3785,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-fullstack-core"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum-core 0.5.6",
|
||||
@@ -3813,7 +3813,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-fullstack-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"axum 0.8.9",
|
||||
"const_format",
|
||||
@@ -3829,7 +3829,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-history"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
@@ -3838,7 +3838,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-hooks"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
@@ -3856,7 +3856,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-html"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
@@ -3887,7 +3887,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-html-internal-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"proc-macro2",
|
||||
@@ -3898,7 +3898,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-interpreter-js"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-core",
|
||||
"dioxus-core-types",
|
||||
@@ -3916,7 +3916,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-liveview"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"axum 0.8.9",
|
||||
"dioxus",
|
||||
@@ -3944,7 +3944,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-logger"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-cli-config",
|
||||
@@ -3955,7 +3955,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-native"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyrender",
|
||||
"anyrender_vello",
|
||||
@@ -3990,7 +3990,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-native-dom"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"blitz-dom",
|
||||
"blitz-traits",
|
||||
@@ -4115,7 +4115,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-router"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"axum 0.8.9",
|
||||
"base64 0.22.1",
|
||||
@@ -4143,7 +4143,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-router-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"base16",
|
||||
"digest",
|
||||
@@ -4157,7 +4157,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-rsx"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"prettier-please",
|
||||
"prettyplease",
|
||||
@@ -4170,7 +4170,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-rsx-hotreload"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus-core",
|
||||
"dioxus-core-types",
|
||||
@@ -4185,7 +4185,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-rsx-rosetta"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"dioxus-autofmt",
|
||||
@@ -4201,7 +4201,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-server"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -4263,7 +4263,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-signals"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
@@ -4283,7 +4283,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-ssr"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"askama_escape",
|
||||
"dioxus",
|
||||
@@ -4294,7 +4294,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-stores"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
@@ -4305,7 +4305,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-stores-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"dioxus",
|
||||
@@ -4325,7 +4325,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-web"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"ciborium",
|
||||
"dioxus",
|
||||
@@ -5468,7 +5468,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "generational-box"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"parking_lot",
|
||||
@@ -7885,7 +7885,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lazy-js-bundle"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
@@ -8303,7 +8303,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "manganis"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"const-serialize 0.7.2",
|
||||
"const-serialize 0.8.0-alpha.0",
|
||||
@@ -8317,7 +8317,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "manganis-core"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"const-serialize 0.7.2",
|
||||
"const-serialize 0.8.0-alpha.0",
|
||||
@@ -8338,7 +8338,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "manganis-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"macro-string",
|
||||
@@ -12547,7 +12547,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ssr-only"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
]
|
||||
@@ -12815,7 +12815,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "subsecond"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"libc",
|
||||
@@ -12841,7 +12841,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "subsecond-types"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -12873,7 +12873,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "suspense-carousel"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"dioxus",
|
||||
@@ -14521,7 +14521,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-split-cli"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -14554,7 +14554,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-split-macro"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"base16",
|
||||
"digest",
|
||||
@@ -14566,7 +14566,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-splitter"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"async-once-cell",
|
||||
"wasm-split-macro",
|
||||
@@ -14587,7 +14587,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-used"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"id-arena",
|
||||
"tracing",
|
||||
@@ -15351,7 +15351,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-headless"
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
dependencies = [
|
||||
"dioxus",
|
||||
]
|
||||
|
||||
+52
-52
@@ -114,71 +114,71 @@ members = [
|
||||
|
||||
|
||||
[workspace.package]
|
||||
version = "0.7.7"
|
||||
version = "0.7.10"
|
||||
|
||||
# dependencies that are shared across packages
|
||||
[workspace.dependencies]
|
||||
dioxus = { path = "packages/dioxus", version = "0.7.7" }
|
||||
dioxus-core = { path = "packages/core", version = "0.7.7" }
|
||||
dioxus-core-types = { path = "packages/core-types", version = "0.7.7" }
|
||||
dioxus-core-macro = { path = "packages/core-macro", version = "0.7.7" }
|
||||
dioxus-config-macro = { path = "packages/config-macro", version = "0.7.7" }
|
||||
dioxus-router = { path = "packages/router", version = "0.7.7" }
|
||||
dioxus-router-macro = { path = "packages/router-macro", version = "0.7.7" }
|
||||
dioxus-document = { path = "packages/document", version = "0.7.7", default-features = false }
|
||||
dioxus-history = { path = "packages/history", version = "0.7.7", default-features = false }
|
||||
dioxus-html = { path = "packages/html", version = "0.7.7", default-features = false }
|
||||
dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.7.7" }
|
||||
dioxus-hooks = { path = "packages/hooks", version = "0.7.7" }
|
||||
dioxus-web = { path = "packages/web", version = "0.7.7", default-features = false }
|
||||
dioxus-ssr = { path = "packages/ssr", version = "0.7.7", default-features = false }
|
||||
dioxus-desktop = { path = "packages/desktop", version = "0.7.7", default-features = false }
|
||||
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.7" }
|
||||
dioxus-liveview = { path = "packages/liveview", version = "0.7.7" }
|
||||
dioxus-autofmt = { path = "packages/autofmt", version = "0.7.7" }
|
||||
dioxus-rsx = { path = "packages/rsx", version = "0.7.7" }
|
||||
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.7" }
|
||||
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.7" }
|
||||
dioxus-signals = { path = "packages/signals", version = "0.7.7" }
|
||||
dioxus-stores = { path = "packages/stores", version = "0.7.7" }
|
||||
dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.7" }
|
||||
dioxus-devtools = { path = "packages/devtools", version = "0.7.7" }
|
||||
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.7" }
|
||||
dioxus-fullstack = { path = "packages/fullstack", version = "0.7.7", default-features = false }
|
||||
dioxus-fullstack-core = { path = "packages/fullstack-core", version = "0.7.7", default-features = false }
|
||||
dioxus-fullstack-macro = { path = "packages/fullstack-macro", version = "0.7.7", default-features = false }
|
||||
dioxus-server = { path = "packages/fullstack-server", version = "0.7.7" }
|
||||
dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.7" }
|
||||
dioxus-logger = { path = "packages/logger", version = "0.7.7" }
|
||||
dioxus-native = { path = "packages/native", version = "0.7.7" }
|
||||
dioxus-native-dom = { path = "packages/native-dom", version = "0.7.7" }
|
||||
dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.7" }
|
||||
dioxus-config-macros = { path = "packages/config-macros", version = "0.7.7" }
|
||||
dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.7" }
|
||||
generational-box = { path = "packages/generational-box", version = "0.7.7" }
|
||||
lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.7" }
|
||||
dioxus = { path = "packages/dioxus", version = "0.7.10" }
|
||||
dioxus-core = { path = "packages/core", version = "0.7.10" }
|
||||
dioxus-core-types = { path = "packages/core-types", version = "0.7.10" }
|
||||
dioxus-core-macro = { path = "packages/core-macro", version = "0.7.10" }
|
||||
dioxus-config-macro = { path = "packages/config-macro", version = "0.7.10" }
|
||||
dioxus-router = { path = "packages/router", version = "0.7.10" }
|
||||
dioxus-router-macro = { path = "packages/router-macro", version = "0.7.10" }
|
||||
dioxus-document = { path = "packages/document", version = "0.7.10", default-features = false }
|
||||
dioxus-history = { path = "packages/history", version = "0.7.10", default-features = false }
|
||||
dioxus-html = { path = "packages/html", version = "0.7.10", default-features = false }
|
||||
dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.7.10" }
|
||||
dioxus-hooks = { path = "packages/hooks", version = "0.7.10" }
|
||||
dioxus-web = { path = "packages/web", version = "0.7.10", default-features = false }
|
||||
dioxus-ssr = { path = "packages/ssr", version = "0.7.10", default-features = false }
|
||||
dioxus-desktop = { path = "packages/desktop", version = "0.7.10", default-features = false }
|
||||
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.10" }
|
||||
dioxus-liveview = { path = "packages/liveview", version = "0.7.10" }
|
||||
dioxus-autofmt = { path = "packages/autofmt", version = "0.7.10" }
|
||||
dioxus-rsx = { path = "packages/rsx", version = "0.7.10" }
|
||||
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.10" }
|
||||
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.10" }
|
||||
dioxus-signals = { path = "packages/signals", version = "0.7.10" }
|
||||
dioxus-stores = { path = "packages/stores", version = "0.7.10" }
|
||||
dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.10" }
|
||||
dioxus-devtools = { path = "packages/devtools", version = "0.7.10" }
|
||||
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.10" }
|
||||
dioxus-fullstack = { path = "packages/fullstack", version = "0.7.10", default-features = false }
|
||||
dioxus-fullstack-core = { path = "packages/fullstack-core", version = "0.7.10", default-features = false }
|
||||
dioxus-fullstack-macro = { path = "packages/fullstack-macro", version = "0.7.10", default-features = false }
|
||||
dioxus-server = { path = "packages/fullstack-server", version = "0.7.10" }
|
||||
dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.10" }
|
||||
dioxus-logger = { path = "packages/logger", version = "0.7.10" }
|
||||
dioxus-native = { path = "packages/native", version = "0.7.10" }
|
||||
dioxus-native-dom = { path = "packages/native-dom", version = "0.7.10" }
|
||||
dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.10" }
|
||||
dioxus-config-macros = { path = "packages/config-macros", version = "0.7.10" }
|
||||
dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.10" }
|
||||
generational-box = { path = "packages/generational-box", version = "0.7.10" }
|
||||
lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.10" }
|
||||
|
||||
# cli
|
||||
dioxus-cli-telemetry = { path = "packages/cli-telemetry", version = "0.7.7" }
|
||||
dioxus-cli-config = { path = "packages/cli-config", version = "0.7.7" }
|
||||
dioxus-cli-telemetry = { path = "packages/cli-telemetry", version = "0.7.10" }
|
||||
dioxus-cli-config = { path = "packages/cli-config", version = "0.7.10" }
|
||||
|
||||
# subsecond
|
||||
subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.7" }
|
||||
subsecond = { path = "packages/subsecond/subsecond", version = "0.7.7" }
|
||||
subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.10" }
|
||||
subsecond = { path = "packages/subsecond/subsecond", version = "0.7.10" }
|
||||
|
||||
# wasm-split
|
||||
wasm-splitter = { path = "packages/wasm-split/wasm-split", version = "0.7.7" }
|
||||
wasm-split-macro = { path = "packages/wasm-split/wasm-split-macro", version = "0.7.7" }
|
||||
wasm-split-cli = { path = "packages/wasm-split/wasm-split-cli", version = "0.7.7" }
|
||||
wasm-used = { path = "packages/wasm-split/wasm-used", version = "0.7.7" }
|
||||
wasm-splitter = { path = "packages/wasm-split/wasm-split", version = "0.7.10" }
|
||||
wasm-split-macro = { path = "packages/wasm-split/wasm-split-macro", version = "0.7.10" }
|
||||
wasm-split-cli = { path = "packages/wasm-split/wasm-split-cli", version = "0.7.10" }
|
||||
wasm-used = { path = "packages/wasm-split/wasm-used", version = "0.7.10" }
|
||||
|
||||
# our dep-info parsing crate
|
||||
depinfo = { path = "packages/depinfo", version = "0.7.7" }
|
||||
depinfo = { path = "packages/depinfo", version = "0.7.10" }
|
||||
|
||||
# manganis
|
||||
manganis = { path = "packages/manganis/manganis", version = "0.7.7" }
|
||||
manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.7" }
|
||||
manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.7" }
|
||||
manganis = { path = "packages/manganis/manganis", version = "0.7.10" }
|
||||
manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.10" }
|
||||
manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.10" }
|
||||
manganis-core-07 = { path = "packages/manganis/manganis-07", version = "0.7.2" }
|
||||
|
||||
# const-serialize.
|
||||
|
||||
@@ -98,12 +98,19 @@
|
||||
);
|
||||
in
|
||||
{
|
||||
packages.dioxus-cli = (
|
||||
rustPackage "dioxus-cli" {
|
||||
packages.dioxus-cli =
|
||||
(rustPackage "dioxus-cli" {
|
||||
binary = "dx";
|
||||
features = [ "no-downloads" ];
|
||||
}
|
||||
);
|
||||
}).overrideAttrs
|
||||
(_: {
|
||||
# The nix sandbox has no .git and no .cargo_vcs_info.json, so
|
||||
# build.rs has nothing to derive the commit from. Pass the
|
||||
# flake's own input rev through the env-var override path.
|
||||
# `self.rev` is set on a clean tree; `dirtyRev` on a dirty one
|
||||
# (and includes a `-dirty` suffix, which build.rs accepts).
|
||||
DIOXUS_CLI_GIT_SHA = inputs.self.rev or inputs.self.dirtyRev or "";
|
||||
});
|
||||
packages.default = self'.packages.dioxus-cli;
|
||||
checks.dioxus-cli = self'.packages.dioxus-cli;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ dioxus-cli-telemetry = { workspace = true }
|
||||
dioxus-component-manifest = { workspace = true }
|
||||
|
||||
bytes = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive", "cargo"] }
|
||||
clap = { workspace = true, features = ["derive", "cargo", "env"] }
|
||||
convert_case = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
uuid = { workspace = true, features = ["v4", "v5", "v7"] }
|
||||
|
||||
@@ -13,7 +13,7 @@ android {
|
||||
applicationId = "{{ application_id }}"
|
||||
minSdk = {{ min_sdk }}
|
||||
targetSdk = {{ target_sdk }}
|
||||
versionCode = 1
|
||||
versionCode = {{ version_code }}
|
||||
versionName = "{{ version }}"
|
||||
}
|
||||
{{#if android_bundle}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<string>{{ bundle_name }}</string>
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{ version }}</string>
|
||||
<string>{{ bundle_version }}</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>{{ version }}</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<string>{{ version }}</string>
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{ version }}</string>
|
||||
<string>{{ bundle_version }}</string>
|
||||
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>{{ minimum_system_version }}</string>
|
||||
|
||||
+128
-21
@@ -1,38 +1,145 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA");
|
||||
println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA_SHORT");
|
||||
println!("cargo:rerun-if-changed=.git/HEAD");
|
||||
println!("cargo:rerun-if-changed=.git/refs");
|
||||
|
||||
let full_hash = std::env::var("DIOXUS_CLI_GIT_SHA").ok().or_else(|| {
|
||||
let output = Command::new("git")
|
||||
.args(["rev-parse", "HEAD"])
|
||||
.output()
|
||||
.ok()?;
|
||||
let manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let git_dir = find_git_dir(&manifest_dir);
|
||||
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
// Track the files that determine the current commit. Absolute paths are
|
||||
// required because the build script runs from `packages/cli/`, not the
|
||||
// workspace root where `.git` lives.
|
||||
if let Some(git_dir) = git_dir.as_deref() {
|
||||
emit_rerun(&git_dir.join("HEAD"));
|
||||
emit_rerun(&git_dir.join("packed-refs"));
|
||||
if let Some(target) = head_ref_target(git_dir) {
|
||||
emit_rerun(&git_dir.join(target));
|
||||
}
|
||||
}
|
||||
emit_rerun(&manifest_dir.join(".cargo_vcs_info.json"));
|
||||
|
||||
let hash = String::from_utf8(output.stdout).ok()?;
|
||||
let hash = hash.trim().to_string();
|
||||
|
||||
if hash.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(hash)
|
||||
}
|
||||
});
|
||||
let full_hash = env_nonempty("DIOXUS_CLI_GIT_SHA")
|
||||
.or_else(|| git_dir.as_deref().and_then(read_head_sha))
|
||||
.or_else(|| read_cargo_vcs_info(&manifest_dir))
|
||||
.or_else(|| git_cli_sha(&manifest_dir));
|
||||
|
||||
if let Some(full_hash) = full_hash {
|
||||
let full_hash = full_hash.trim();
|
||||
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA={full_hash}");
|
||||
|
||||
let short_hash = std::env::var("DIOXUS_CLI_GIT_SHA_SHORT")
|
||||
.ok()
|
||||
let short_hash = env_nonempty("DIOXUS_CLI_GIT_SHA_SHORT")
|
||||
.unwrap_or_else(|| full_hash.chars().take(7).collect());
|
||||
|
||||
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA_SHORT={short_hash}");
|
||||
}
|
||||
}
|
||||
|
||||
fn env_nonempty(key: &str) -> Option<String> {
|
||||
env::var(key).ok().filter(|s| !s.trim().is_empty())
|
||||
}
|
||||
|
||||
fn emit_rerun(path: &Path) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
|
||||
/// Walk up from `start` looking for `.git`. Handles the file form used by
|
||||
/// git worktrees and submodules, where `.git` contains `gitdir: <path>`.
|
||||
fn find_git_dir(start: &Path) -> Option<PathBuf> {
|
||||
for dir in start.ancestors() {
|
||||
let candidate = dir.join(".git");
|
||||
let meta = match fs::metadata(&candidate) {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
if meta.is_dir() {
|
||||
return Some(candidate);
|
||||
}
|
||||
if meta.is_file() {
|
||||
let contents = fs::read_to_string(&candidate).ok()?;
|
||||
let pointer = contents
|
||||
.lines()
|
||||
.find_map(|l| l.strip_prefix("gitdir:"))?
|
||||
.trim();
|
||||
let resolved = if Path::new(pointer).is_absolute() {
|
||||
PathBuf::from(pointer)
|
||||
} else {
|
||||
dir.join(pointer)
|
||||
};
|
||||
return Some(resolved);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// If HEAD is a symbolic ref (`ref: refs/heads/foo`), return the target path.
|
||||
fn head_ref_target(git_dir: &Path) -> Option<String> {
|
||||
let head = fs::read_to_string(git_dir.join("HEAD")).ok()?;
|
||||
head.strip_prefix("ref:").map(|s| s.trim().to_owned())
|
||||
}
|
||||
|
||||
fn read_head_sha(git_dir: &Path) -> Option<String> {
|
||||
let head = fs::read_to_string(git_dir.join("HEAD")).ok()?;
|
||||
let head = head.trim();
|
||||
|
||||
let Some(target) = head.strip_prefix("ref:").map(str::trim) else {
|
||||
// Detached HEAD: the file holds the SHA directly.
|
||||
return is_sha(head).then(|| head.to_owned());
|
||||
};
|
||||
|
||||
// Loose ref file.
|
||||
if let Ok(sha) = fs::read_to_string(git_dir.join(target)) {
|
||||
let sha = sha.trim();
|
||||
if is_sha(sha) {
|
||||
return Some(sha.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
// Packed refs (after `git gc` / shallow clones, refs only live here).
|
||||
let packed = fs::read_to_string(git_dir.join("packed-refs")).ok()?;
|
||||
for line in packed.lines() {
|
||||
if line.starts_with('#') || line.starts_with('^') || line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let (sha, name) = line.split_once(' ')?;
|
||||
if name == target && is_sha(sha) {
|
||||
return Some(sha.to_owned());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Cargo writes `.cargo_vcs_info.json` next to `Cargo.toml` when publishing,
|
||||
/// recording the source SHA at publish time. This is how `cargo install`
|
||||
/// from crates.io can still report a real commit despite the `.crate`
|
||||
/// tarball having no `.git/`.
|
||||
fn read_cargo_vcs_info(manifest_dir: &Path) -> Option<String> {
|
||||
let contents = fs::read_to_string(manifest_dir.join(".cargo_vcs_info.json")).ok()?;
|
||||
// Cheap targeted parse so we don't pull serde into the build script.
|
||||
// The file is generated by cargo and the field name is stable.
|
||||
let after = contents.split("\"sha1\"").nth(1)?;
|
||||
let sha = after.split('"').nth(1)?.trim();
|
||||
is_sha(sha).then(|| sha.to_owned())
|
||||
}
|
||||
|
||||
fn git_cli_sha(manifest_dir: &Path) -> Option<String> {
|
||||
// Scope `git` to the manifest dir so we never accidentally pick up a
|
||||
// SHA from a parent repo (e.g. someone's `~` is a git repo).
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(manifest_dir)
|
||||
.args(["rev-parse", "HEAD"])
|
||||
.output()
|
||||
.ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
let sha = String::from_utf8(output.stdout).ok()?.trim().to_owned();
|
||||
is_sha(&sha).then_some(sha)
|
||||
}
|
||||
|
||||
fn is_sha(s: &str) -> bool {
|
||||
matches!(s.len(), 40 | 64) && s.chars().all(|c| c.is_ascii_hexdigit())
|
||||
}
|
||||
@@ -267,6 +267,15 @@
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version_code": {
|
||||
"description": "The version code used for `versionCode` in the generated Gradle project.\n\nMust be between 1 and 2100000000 (the Google Play Store maximum).\n\nCan be overridden per-build with `--version-code` or the `DX_ANDROID_VERSION_CODE`\nenvironment variable. If unset, it is derived from the crate version as\n`major * 1000000 + minor * 1000 + patch`.",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -964,6 +973,13 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"bundle_version": {
|
||||
"description": "The bundle version string (CFBundleVersion).\n\nThis is the machine-readable build number that must increase with every upload\nto App Store Connect. Can be overridden per-build with `--bundle-version` or the\n`DX_BUNDLE_VERSION` environment variable. Defaults to the crate version.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"category": {
|
||||
"description": "App category. Overrides `bundle.category` for iOS builds.",
|
||||
"type": [
|
||||
|
||||
@@ -120,6 +120,7 @@ impl BuildRequest {
|
||||
application_id: String,
|
||||
app_name: String,
|
||||
version: String,
|
||||
version_code: u32,
|
||||
android_bundle: Option<crate::AndroidSettings>,
|
||||
/// Android SDK version settings
|
||||
min_sdk: u32,
|
||||
@@ -180,6 +181,7 @@ impl BuildRequest {
|
||||
application_id: self.bundle_identifier(),
|
||||
app_name: self.bundled_app_name(),
|
||||
version: self.crate_version(),
|
||||
version_code: self.android_version_code()?,
|
||||
android_bundle: self.config.bundle.android.clone(),
|
||||
min_sdk: self.config.android.min_sdk.unwrap_or(24),
|
||||
target_sdk: self.config.android.target_sdk.unwrap_or(34),
|
||||
|
||||
@@ -160,6 +160,8 @@ impl BuildRequest {
|
||||
pub executable_name: String,
|
||||
/// App version string (from Cargo.toml)
|
||||
pub version: String,
|
||||
/// Bundle version string (CFBundleVersion)
|
||||
pub bundle_version: String,
|
||||
/// Permission usage descriptions
|
||||
pub permissions: Vec<PlistPermission>,
|
||||
/// Additional plist entries as raw XML
|
||||
@@ -231,6 +233,7 @@ impl BuildRequest {
|
||||
executable_name: self.platform_exe_name(),
|
||||
bundle_identifier: self.bundle_identifier(),
|
||||
version: self.crate_version(),
|
||||
bundle_version: self.apple_bundle_version(),
|
||||
permissions,
|
||||
plist_entries,
|
||||
raw_plist,
|
||||
@@ -265,6 +268,7 @@ impl BuildRequest {
|
||||
executable_name: self.platform_exe_name(),
|
||||
bundle_identifier: self.bundle_identifier(),
|
||||
version: self.crate_version(),
|
||||
bundle_version: self.apple_bundle_version(),
|
||||
permissions,
|
||||
plist_entries,
|
||||
raw_plist,
|
||||
|
||||
@@ -408,7 +408,9 @@ impl AppBuilder {
|
||||
// patch (starting from changed_crates + cascade). That serves a different purpose — it only
|
||||
// compiles what changed now, not everything ever modified. Both use workspace_dependents_of
|
||||
// for the BFS, so they stay in sync automatically.
|
||||
let tip_crate_name = self.build.main_target.replace('-', "_");
|
||||
// Track the tip by *package* name — that's the identity used by the file→crate
|
||||
// mapping and the workspace dependents graph (the bin target name can differ).
|
||||
let tip_crate_name = self.build.tip_package_name();
|
||||
self.modified_crates.insert(tip_crate_name.clone());
|
||||
|
||||
// Add changed crates and their transitive workspace dependents (cascade).
|
||||
|
||||
@@ -614,7 +614,9 @@ impl BuildRequest {
|
||||
modified_crates: &HashSet<String>,
|
||||
) -> Result<Vec<String>> {
|
||||
// Exclude the tip crate — it's compiled separately via cargo_build after replay.
|
||||
let tip = self.tip_crate_name();
|
||||
// Modified crates are tracked by *package* name, which can differ from the bin
|
||||
// target name (`tip_crate_name()`), e.g. package `browser` with `[[bin]] name = "blitz"`.
|
||||
let tip = self.tip_package_name();
|
||||
let crates: HashSet<&String> = modified_crates
|
||||
.iter()
|
||||
.filter(|name| **name != tip)
|
||||
|
||||
@@ -269,6 +269,8 @@ pub(crate) struct BuildRequest {
|
||||
pub(crate) using_dioxus_explicitly: bool,
|
||||
pub(crate) apple_entitlements: Option<PathBuf>,
|
||||
pub(crate) apple_team_id: Option<String>,
|
||||
pub(crate) version_code: Option<u32>,
|
||||
pub(crate) bundle_version: Option<String>,
|
||||
pub(crate) session_cache_dir: PathBuf,
|
||||
pub(crate) raw_json_diagnostics: bool,
|
||||
pub(crate) windows_subsystem: Option<String>,
|
||||
@@ -905,6 +907,8 @@ impl BuildRequest {
|
||||
inject_loading_scripts: args.inject_loading_scripts,
|
||||
apple_entitlements: args.apple_entitlements.clone(),
|
||||
apple_team_id: args.apple_team_id.clone(),
|
||||
version_code: args.version_code,
|
||||
bundle_version: args.bundle_version.clone(),
|
||||
raw_json_diagnostics: args.raw_json_diagnostics,
|
||||
windows_subsystem: args.windows_subsystem.clone(),
|
||||
})
|
||||
@@ -2581,6 +2585,16 @@ impl BuildRequest {
|
||||
self.main_target.replace('-', "_")
|
||||
}
|
||||
|
||||
/// The workspace package name of the tip crate (hyphens replaced with underscores).
|
||||
///
|
||||
/// This can differ from `tip_crate_name()` when the binary target is named differently
|
||||
/// than its package (e.g. package `browser` with `[[bin]] name = "blitz"`). Use this for
|
||||
/// workspace-graph lookups (which are keyed by package name) and `tip_crate_name()` for
|
||||
/// rustc `--crate-name` keys like `{name}.bin`.
|
||||
pub(crate) fn tip_package_name(&self) -> String {
|
||||
self.package().name.replace('-', "_")
|
||||
}
|
||||
|
||||
/// Stderr captured from the linker during the last build. Written by the linker
|
||||
/// interception in `rustcwrapper` and read back to surface warnings/errors to the user.
|
||||
fn link_err_file(&self) -> PathBuf {
|
||||
@@ -2675,6 +2689,64 @@ impl BuildRequest {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Get the Android `versionCode` for the generated Gradle project.
|
||||
///
|
||||
/// Resolution order: `--version-code` / `DX_ANDROID_VERSION_CODE`, then
|
||||
/// `[android] version_code` in Dioxus.toml, then a value derived from the crate
|
||||
/// version as `major * 1000000 + minor * 1000 + patch`.
|
||||
pub(crate) fn android_version_code(&self) -> Result<u32> {
|
||||
/// The maximum value accepted by the Google Play Store.
|
||||
const MAX_VERSION_CODE: u32 = 2_100_000_000;
|
||||
|
||||
let code = match self.version_code.or(self.config.android.version_code) {
|
||||
Some(code) => code,
|
||||
None => {
|
||||
let version = &self.workspace.krates[self.crate_package].version;
|
||||
if version.major > 2099 || version.minor > 999 || version.patch > 999 {
|
||||
bail!(
|
||||
"Cannot derive an Android versionCode from crate version `{version}`: each component must fit `major <= 2099`, `minor <= 999`, `patch <= 999`. Set an explicit version code via `[android] version_code` in Dioxus.toml or the `--version-code` flag."
|
||||
);
|
||||
}
|
||||
if !version.pre.is_empty() {
|
||||
tracing::warn!(
|
||||
"Pre-release identifier of crate version `{version}` is ignored when deriving the Android versionCode"
|
||||
);
|
||||
}
|
||||
let code =
|
||||
(version.major * 1_000_000 + version.minor * 1_000 + version.patch) as u32;
|
||||
|
||||
// Google Play requires versionCode >= 1, so bump 0.0.0 up to 1.
|
||||
code.max(1)
|
||||
}
|
||||
};
|
||||
|
||||
if !(1..=MAX_VERSION_CODE).contains(&code) {
|
||||
bail!(
|
||||
"Android versionCode must be between 1 and {MAX_VERSION_CODE}, got {code}. See https://developer.android.com/studio/publish/versioning"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(code)
|
||||
}
|
||||
|
||||
/// The explicitly-configured `CFBundleVersion` for iOS/macOS bundles, if any.
|
||||
///
|
||||
/// Resolution order: `--bundle-version` / `DX_BUNDLE_VERSION`, then the platform's
|
||||
/// `bundle_version` in Dioxus.toml (`[ios]` or `[macos]`).
|
||||
pub(crate) fn apple_bundle_version_override(&self) -> Option<String> {
|
||||
self.bundle_version.clone().or_else(|| match self.bundle {
|
||||
BundleFormat::Ios => self.config.ios.bundle_version.clone(),
|
||||
BundleFormat::MacOS => self.config.macos.bundle_version.clone(),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// The `CFBundleVersion` for iOS/macOS bundles, falling back to the crate version.
|
||||
pub(crate) fn apple_bundle_version(&self) -> String {
|
||||
self.apple_bundle_version_override()
|
||||
.unwrap_or_else(|| self.crate_version())
|
||||
}
|
||||
|
||||
pub(crate) fn bundle_identifier(&self) -> String {
|
||||
use crate::config::BundlePlatform;
|
||||
|
||||
@@ -3095,7 +3167,7 @@ impl BuildRequest {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let tip = self.tip_crate_name();
|
||||
let tip = self.tip_package_name();
|
||||
let Some(tip_nid) = krates.workspace_members().find_map(|m| match m {
|
||||
krates::Node::Krate { id, krate, .. } if krate.name.replace('-', "_") == tip => {
|
||||
krates.nid_for_kid(id)
|
||||
|
||||
@@ -482,7 +482,11 @@ impl BundleContext<'_> {
|
||||
);
|
||||
|
||||
let version = self.version_string();
|
||||
let bundle_version = macos_settings.bundle_version.as_deref().unwrap_or(&version);
|
||||
let bundle_version = self
|
||||
.build
|
||||
.apple_bundle_version_override()
|
||||
.or_else(|| macos_settings.bundle_version.clone())
|
||||
.unwrap_or_else(|| version.clone());
|
||||
|
||||
dict.insert(
|
||||
"CFBundleShortVersionString".into(),
|
||||
|
||||
@@ -162,6 +162,22 @@ pub(crate) struct TargetArgs {
|
||||
#[clap(long, default_value_t = true, help_heading = HELP_HEADING, num_args = 0..=1)]
|
||||
pub(crate) wasm_js_cfg: bool,
|
||||
|
||||
/// The Android `versionCode` to stamp into the generated Gradle project.
|
||||
///
|
||||
/// Must be between 1 and 2100000000 (the Google Play Store maximum). Overrides
|
||||
/// `[android] version_code` in Dioxus.toml. If neither is set, the version code is
|
||||
/// derived from the crate version as `major * 1000000 + minor * 1000 + patch`.
|
||||
#[clap(long, env = "DX_ANDROID_VERSION_CODE", help_heading = HELP_HEADING)]
|
||||
pub(crate) version_code: Option<u32>,
|
||||
|
||||
/// The bundle version (CFBundleVersion) to stamp into the Info.plist of iOS and macOS bundles.
|
||||
///
|
||||
/// This is the machine-readable build number that must increase with every upload to
|
||||
/// App Store Connect. Overrides `[ios] bundle_version` / `[macos] bundle_version` in
|
||||
/// Dioxus.toml. Defaults to the crate version.
|
||||
#[clap(long, env = "DX_BUNDLE_VERSION", help_heading = HELP_HEADING)]
|
||||
pub(crate) bundle_version: Option<String>,
|
||||
|
||||
/// The Windows subsystem to use when building for Windows targets. This can be either `CONSOLE` or `WINDOWS`.
|
||||
///
|
||||
/// By default, DX uses `WINDOWS` since it assumes a GUI application, but you can override this behavior with this flag.
|
||||
@@ -200,6 +216,8 @@ impl Anonymized for TargetArgs {
|
||||
"debug_symbols": self.debug_symbols,
|
||||
"keep_names": self.keep_names,
|
||||
"device": self.device,
|
||||
"version_code": self.version_code,
|
||||
"bundle_version": self.bundle_version.is_some(),
|
||||
"base_path": self.base_path.is_some(),
|
||||
"cargo_args": self.cargo_args.is_some(),
|
||||
"rustc_args": self.rustc_args.is_some(),
|
||||
|
||||
@@ -326,6 +326,14 @@ pub struct IosConfig {
|
||||
pub long_description: Option<String>,
|
||||
|
||||
// === iOS-specific settings ===
|
||||
/// The bundle version string (CFBundleVersion).
|
||||
///
|
||||
/// This is the machine-readable build number that must increase with every upload
|
||||
/// to App Store Connect. Can be overridden per-build with `--bundle-version` or the
|
||||
/// `DX_BUNDLE_VERSION` environment variable. Defaults to the crate version.
|
||||
#[serde(default)]
|
||||
pub bundle_version: Option<String>,
|
||||
|
||||
/// Minimum iOS deployment target (e.g., "15.0").
|
||||
#[serde(default)]
|
||||
pub deployment_target: Option<String>,
|
||||
@@ -590,6 +598,16 @@ pub struct AndroidConfig {
|
||||
pub signing: Option<AndroidSigningConfig>,
|
||||
|
||||
// === Android-specific settings ===
|
||||
/// The version code used for `versionCode` in the generated Gradle project.
|
||||
///
|
||||
/// Must be between 1 and 2100000000 (the Google Play Store maximum).
|
||||
///
|
||||
/// Can be overridden per-build with `--version-code` or the `DX_ANDROID_VERSION_CODE`
|
||||
/// environment variable. If unset, it is derived from the crate version as
|
||||
/// `major * 1000000 + minor * 1000 + patch`.
|
||||
#[serde(default)]
|
||||
pub version_code: Option<u32>,
|
||||
|
||||
/// Minimum SDK version.
|
||||
#[serde(default)]
|
||||
pub min_sdk: Option<u32>,
|
||||
|
||||
@@ -1187,7 +1187,7 @@ impl AppServer {
|
||||
/// Uses BFS from the tip crate through its workspace dependencies to find the path.
|
||||
/// If the changed crate IS the tip crate, returns just `[tip]`.
|
||||
pub(crate) fn workspace_dep_chain(&self, changed_crate: &str) -> Vec<String> {
|
||||
let tip_name = self.client.build.main_target.replace('-', "_");
|
||||
let tip_name = self.client.build.tip_package_name();
|
||||
|
||||
// If the changed crate is the tip, no chain needed
|
||||
if changed_crate == tip_name {
|
||||
|
||||
@@ -20,6 +20,10 @@ type CustomEventHandler = Box<
|
||||
),
|
||||
>;
|
||||
|
||||
/// A function taking a URL and returning whether the webview should navigate to it or open it in
|
||||
/// the browser. If missing in the config, all URLs will be allowed.
|
||||
type NavigationHandler = Box<dyn Fn(&str) -> bool + 'static>;
|
||||
|
||||
/// The closing behaviour of specific application window.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
@@ -70,6 +74,7 @@ pub struct Config {
|
||||
pub(crate) disable_dma_buf_on_wayland: bool,
|
||||
pub(crate) additional_windows_args: Option<String>,
|
||||
pub(crate) tray_icon_show_window_on_click: bool,
|
||||
pub(crate) navigation_handler: Option<NavigationHandler>,
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
|
||||
@@ -124,6 +129,7 @@ impl Config {
|
||||
on_window: None,
|
||||
additional_windows_args: None,
|
||||
tray_icon_show_window_on_click: true,
|
||||
navigation_handler: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,6 +356,13 @@ impl Config {
|
||||
self.tray_icon_show_window_on_click = show;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a custom navigation handler for non-dioxus URLs.
|
||||
/// Return true to allow navigation inside the webview, false to block.
|
||||
pub fn with_navigation_handler(mut self, f: impl Fn(&str) -> bool + 'static) -> Self {
|
||||
self.navigation_handler = Some(Box::new(f));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
||||
@@ -353,6 +353,7 @@ impl WebviewInstance {
|
||||
}
|
||||
};
|
||||
|
||||
let navigation_handler = cfg.navigation_handler.take();
|
||||
let page_loaded = AtomicBool::new(false);
|
||||
|
||||
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
|
||||
@@ -367,25 +368,29 @@ impl WebviewInstance {
|
||||
.with_url("dioxus://index.html/")
|
||||
.with_ipc_handler(ipc_handler)
|
||||
.with_navigation_handler(move |var| {
|
||||
// We don't want to allow any navigation
|
||||
// We only want to serve the index file and assets
|
||||
// Serve the index and assets.
|
||||
if var.starts_with("dioxus://")
|
||||
|| var.starts_with("http://dioxus.")
|
||||
|| var.starts_with("https://dioxus.")
|
||||
{
|
||||
// After the page has loaded once, don't allow any more navigation
|
||||
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
|
||||
!page_loaded
|
||||
} else {
|
||||
if var.starts_with("http://")
|
||||
|| var.starts_with("https://")
|
||||
|| var.starts_with("mailto:")
|
||||
{
|
||||
_ = webbrowser::open(&var);
|
||||
}
|
||||
false
|
||||
return !page_loaded;
|
||||
}
|
||||
}) // prevent all navigations
|
||||
|
||||
// External links always open somewhere else. Prevents the webview from navigating
|
||||
if var.starts_with("http://")
|
||||
|| var.starts_with("https://")
|
||||
|| var.starts_with("mailto:")
|
||||
{
|
||||
_ = webbrowser::open(&var);
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default, external links are allowed. This keeps things like iframes working.
|
||||
// However, users can customize this to allow/disallow domains/routes/patterns.
|
||||
navigation_handler.as_ref().map(|f| f(&var)).unwrap_or(true)
|
||||
})
|
||||
.with_asynchronous_custom_protocol(String::from("dioxus"), request_handler);
|
||||
|
||||
// Enable https scheme on android, needed for secure context API, like the geolocation API
|
||||
|
||||
@@ -398,7 +398,7 @@ impl FfiBridgeParser {
|
||||
// Use with_activity which returns Option<R>, wrapping our Result in the Option
|
||||
let inner_result: Option<Result<Self, String>> = manganis::android::with_activity(|mut env, activity| {
|
||||
// Find the class
|
||||
let class_result = env.find_class(#class_name_lit);
|
||||
let class_result = manganis::android::load_class_from_classloader(env, activity, #class_name_lit);
|
||||
let class = match class_result {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Some(Err(format!("Failed to find class {}: {:?}", #class_name_lit, e))),
|
||||
@@ -724,10 +724,10 @@ impl FfiBridgeParser {
|
||||
let class_name_bytes = format!("{}\0", name);
|
||||
|
||||
let type_def = quote! {
|
||||
/// Opaque wrapper around an Objective-C object pointer
|
||||
/// Opaque wrapper around a retained Objective-C object
|
||||
/// The actual Swift class is looked up dynamically at runtime after dx links everything
|
||||
pub struct #name {
|
||||
inner: *mut manganis::objc2::runtime::AnyObject,
|
||||
inner: manganis::objc2::rc::Retained<manganis::objc2::runtime::AnyObject>,
|
||||
}
|
||||
|
||||
unsafe impl Send for #name {}
|
||||
@@ -827,17 +827,26 @@ impl FfiBridgeParser {
|
||||
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![class, alloc];
|
||||
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![instance, init];
|
||||
|
||||
if instance.is_null() {
|
||||
return Err("Failed to initialize instance");
|
||||
}
|
||||
// `alloc` + `init` returns a +1 retained object; `Retained::from_raw`
|
||||
// takes over that reference and sends `release` on drop.
|
||||
let inner = manganis::objc2::rc::Retained::from_raw(instance)
|
||||
.ok_or("Failed to initialize instance")?;
|
||||
|
||||
Ok(Self { inner: instance })
|
||||
Ok(Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from an existing object pointer
|
||||
/// Create from an existing object pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `ptr` must be a valid, non-null pointer to an Objective-C object,
|
||||
/// and the caller must transfer ownership of one retain count (+1)
|
||||
/// to the returned wrapper, which sends `release` on drop.
|
||||
pub unsafe fn from_raw(ptr: *mut manganis::objc2::runtime::AnyObject) -> Self {
|
||||
Self { inner: ptr }
|
||||
let inner = manganis::objc2::rc::Retained::from_raw(ptr)
|
||||
.expect("from_raw called with a null pointer");
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -960,7 +969,7 @@ impl FfiBridgeParser {
|
||||
|
||||
// Build the msg_send call
|
||||
let this_expr = if func.receiver.is_some() {
|
||||
quote! { this.inner }
|
||||
quote! { manganis::objc2::rc::Retained::as_ptr(&this.inner) as *mut manganis::objc2::runtime::AnyObject }
|
||||
} else {
|
||||
// For static methods, we'd need the class
|
||||
quote! { class }
|
||||
|
||||
@@ -111,15 +111,34 @@ pub fn request_permissions_via_helper(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load a Java class from the APK's classloader
|
||||
/// Load a Java class from the APK's classloader.
|
||||
///
|
||||
/// `JNIEnv::find_class` resolves against the *system* classloader on a thread that
|
||||
/// was attached from native code (`JavaVM::attach_current_thread`), which cannot see
|
||||
/// classes packaged in the APK, so it raises `ClassNotFoundException`. The activity's
|
||||
/// own classloader can, so we ask the activity for it and call `loadClass` on it.
|
||||
///
|
||||
/// `class_name` may be given in either JNI form (`com/example/Foo`) or binary form
|
||||
/// (`com.example.Foo`); `loadClass` requires the binary form, so slashes are converted.
|
||||
pub fn load_class_from_classloader<'env>(
|
||||
env: &mut JNIEnv<'env>,
|
||||
activity: &JObject<'_>,
|
||||
class_name: &str,
|
||||
) -> Result<JClass<'env>> {
|
||||
let class_name_jstring = new_string(env, class_name)?;
|
||||
let class = env.call_static_method(
|
||||
"java/lang/Class",
|
||||
"forName",
|
||||
let binary_name = class_name.replace('/', ".");
|
||||
let activity_class = env.get_object_class(activity)?;
|
||||
let loader = env
|
||||
.call_method(
|
||||
&activity_class,
|
||||
"getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;",
|
||||
&[],
|
||||
)?
|
||||
.l()?;
|
||||
let class_name_jstring = new_string(env, &binary_name)?;
|
||||
let class = env.call_method(
|
||||
&loader,
|
||||
"loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;",
|
||||
&[JValue::Object(&class_name_jstring)],
|
||||
)?;
|
||||
|
||||
@@ -594,24 +594,31 @@ pub unsafe fn apply_patch(mut table: JumpTable) -> Result<(), PatchError> {
|
||||
.unwrap()
|
||||
.unchecked_into();
|
||||
|
||||
// ── SYNC SECTION — no `.await` past this point ────────────────
|
||||
// ── HOST-STATE-MUTATING SECTION ───────────────────────────────
|
||||
//
|
||||
// Everything below mutates shared JS state (linear memory, the
|
||||
// indirect function table, the patch's data segment) and the
|
||||
// jump-table pointer. We must not yield, because:
|
||||
// Below we grow shared linear memory and the indirect function
|
||||
// table, then async-instantiate the patch into them and commit
|
||||
// the new jump table. There IS one `.await` for the instantiate
|
||||
// (we can't avoid it: Chrome disallows synchronous
|
||||
// `new WebAssembly.Instance` on the main thread for modules
|
||||
// larger than 8MB, and patches routinely cross that), but it's
|
||||
// safe — the original race we fixed wasn't about yielding here:
|
||||
//
|
||||
// * `memory.grow` detaches the previous `ArrayBuffer`. The old
|
||||
// code captured `memory.buffer()` BEFORE the awaits and then
|
||||
// read its `byteLength` to compute `__memory_base`; if any
|
||||
// other task ran a `memory.grow` during the awaits (e.g. an
|
||||
// allocator call from a concurrent render), the snapshot was
|
||||
// detached, `byteLength` returned 0, and the patch's data
|
||||
// segment ended up loaded over the host's stack/rodata.
|
||||
// * Two concurrent `apply_patch` tasks must not interleave
|
||||
// between memory/table grow and `commit_patch`. Doing all
|
||||
// side-effecting work in one synchronous turn guarantees that.
|
||||
// * If the future is cancelled before this point, host state
|
||||
// is untouched.
|
||||
// * `memory.grow` and `funcs.grow` each return their PRIOR
|
||||
// length atomically. Concurrent `apply_patch` tasks therefore
|
||||
// each get a unique, non-overlapping `memory_base` /
|
||||
// `table_base`, so two patches can't land on the same region.
|
||||
// * Host code can't observe the half-instantiated patch: the
|
||||
// new memory pages are zero, the new table slots are null,
|
||||
// and the jump table isn't committed until the very end of
|
||||
// this block, so nothing redirects through the new slots.
|
||||
// * The original bug — using `memory.buffer().byteLength()`
|
||||
// captured before the awaits, which returned 0 if the buffer
|
||||
// had been detached by a concurrent grow — is gone because
|
||||
// we derive `memory_base` from `memory.grow()`'s return
|
||||
// value instead.
|
||||
// * Cancellation between grow and `commit_patch` leaks memory
|
||||
// pages and table slots, but doesn't corrupt anything.
|
||||
const PAGE_SIZE: u32 = 64 * 1024;
|
||||
let patch_pages = (dl_bytes.byte_length() as f64 / PAGE_SIZE as f64).ceil() as u32 + 1;
|
||||
|
||||
@@ -646,9 +653,16 @@ pub unsafe fn apply_patch(mut table: JumpTable) -> Result<(), PatchError> {
|
||||
let imports = Object::new();
|
||||
Reflect::set(&imports, &"env".into(), &env).unwrap();
|
||||
|
||||
// Synchronous instantiation of the precompiled module — writes
|
||||
// the patch's data segment into memory at `memory_base`.
|
||||
let instance = Instance::new(&module, &imports).unwrap();
|
||||
// Async instantiation of the precompiled module. We use the
|
||||
// (Module, imports) form of `WebAssembly.instantiate`, which
|
||||
// resolves directly to an `Instance` (not `{module, instance}`).
|
||||
// This is the no-size-limit path; the synchronous
|
||||
// `new WebAssembly.Instance` constructor is capped at 8MB on
|
||||
// Chrome's main thread.
|
||||
let instance: Instance = JsFuture::from(WebAssembly::instantiate_module(&module, &imports))
|
||||
.await
|
||||
.unwrap()
|
||||
.unchecked_into();
|
||||
let inst_exports: Object = instance.exports();
|
||||
|
||||
// Run the patch's relocation thunks and constructors. Order
|
||||
|
||||
Reference in new issue
Block a user