Compare commits
12
Commits
003ec3270b
...
v0.7.10-sw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275fc84a4a | ||
|
|
657e6f2125 | ||
|
|
48baafc3ff | ||
|
|
07dddd569e | ||
|
|
6adf7ba465 | ||
|
|
57d6794ad6 | ||
|
|
fda083bb65 | ||
|
|
3e43ffa6cf | ||
|
|
bfcc111817 | ||
|
|
d1ead872b1 | ||
|
|
f5be0ea510 | ||
|
|
f1a0124227 |
No files matched your search
@@ -70,6 +70,18 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
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
|
- name: Install openssl on macos
|
||||||
if: matrix.platform.os == 'macos-latest'
|
if: matrix.platform.os == 'macos-latest'
|
||||||
|
|||||||
Generated
+56
-56
@@ -3110,7 +3110,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "depinfo"
|
name = "depinfo"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
@@ -3246,7 +3246,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus"
|
name = "dioxus"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -3288,7 +3288,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-asset-resolver"
|
name = "dioxus-asset-resolver"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
@@ -3309,7 +3309,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-autofmt"
|
name = "dioxus-autofmt"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
@@ -3323,7 +3323,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-cli"
|
name = "dioxus-cli"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi-to-html",
|
"ansi-to-html",
|
||||||
"ansi-to-tui",
|
"ansi-to-tui",
|
||||||
@@ -3451,7 +3451,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-cli-config"
|
name = "dioxus-cli-config"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
@@ -3467,7 +3467,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-cli-telemetry"
|
name = "dioxus-cli-telemetry"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs",
|
"dirs",
|
||||||
@@ -3479,7 +3479,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-component-manifest"
|
name = "dioxus-component-manifest"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"schemars 1.2.1",
|
"schemars 1.2.1",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3488,7 +3488,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-config-macro"
|
name = "dioxus-config-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3496,11 +3496,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-config-macros"
|
name = "dioxus-config-macros"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-core"
|
name = "dioxus-core"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"const_format",
|
"const_format",
|
||||||
@@ -3531,7 +3531,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-core-macro"
|
name = "dioxus-core-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case 0.8.0",
|
"convert_case 0.8.0",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -3547,11 +3547,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-core-types"
|
name = "dioxus-core-types"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-desktop"
|
name = "dioxus-desktop"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -3612,7 +3612,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-devtools"
|
name = "dioxus-devtools"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -3631,7 +3631,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-devtools-types"
|
name = "dioxus-devtools-types"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3640,7 +3640,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-document"
|
name = "dioxus-document"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -3658,7 +3658,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-dx-wire-format"
|
name = "dioxus-dx-wire-format"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"manganis-core",
|
"manganis-core",
|
||||||
@@ -3707,7 +3707,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-ext"
|
name = "dioxus-ext"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-autofmt",
|
"dioxus-autofmt",
|
||||||
"dioxus-rsx-rosetta",
|
"dioxus-rsx-rosetta",
|
||||||
@@ -3718,7 +3718,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-fullstack"
|
name = "dioxus-fullstack"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@@ -3785,7 +3785,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-fullstack-core"
|
name = "dioxus-fullstack-core"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum-core 0.5.6",
|
"axum-core 0.5.6",
|
||||||
@@ -3813,7 +3813,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-fullstack-macro"
|
name = "dioxus-fullstack-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum 0.8.9",
|
"axum 0.8.9",
|
||||||
"const_format",
|
"const_format",
|
||||||
@@ -3829,7 +3829,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-history"
|
name = "dioxus-history"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -3838,7 +3838,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-hooks"
|
name = "dioxus-hooks"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -3856,7 +3856,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-html"
|
name = "dioxus-html"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -3887,7 +3887,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-html-internal-macro"
|
name = "dioxus-html-internal-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case 0.8.0",
|
"convert_case 0.8.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -3898,7 +3898,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-interpreter-js"
|
name = "dioxus-interpreter-js"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-types",
|
"dioxus-core-types",
|
||||||
@@ -3916,7 +3916,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-liveview"
|
name = "dioxus-liveview"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum 0.8.9",
|
"axum 0.8.9",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -3944,7 +3944,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-logger"
|
name = "dioxus-logger"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
@@ -3955,7 +3955,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-native"
|
name = "dioxus-native"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyrender",
|
"anyrender",
|
||||||
"anyrender_vello",
|
"anyrender_vello",
|
||||||
@@ -3990,7 +3990,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-native-dom"
|
name = "dioxus-native-dom"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blitz-dom",
|
"blitz-dom",
|
||||||
"blitz-traits",
|
"blitz-traits",
|
||||||
@@ -4115,7 +4115,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-router"
|
name = "dioxus-router"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum 0.8.9",
|
"axum 0.8.9",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@@ -4143,7 +4143,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-router-macro"
|
name = "dioxus-router-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16",
|
"base16",
|
||||||
"digest",
|
"digest",
|
||||||
@@ -4157,7 +4157,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-rsx"
|
name = "dioxus-rsx"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"prettier-please",
|
"prettier-please",
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
@@ -4170,7 +4170,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-rsx-hotreload"
|
name = "dioxus-rsx-hotreload"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-types",
|
"dioxus-core-types",
|
||||||
@@ -4185,7 +4185,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-rsx-rosetta"
|
name = "dioxus-rsx-rosetta"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case 0.8.0",
|
"convert_case 0.8.0",
|
||||||
"dioxus-autofmt",
|
"dioxus-autofmt",
|
||||||
@@ -4201,7 +4201,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-server"
|
name = "dioxus-server"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -4263,7 +4263,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-signals"
|
name = "dioxus-signals"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -4283,7 +4283,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-ssr"
|
name = "dioxus-ssr"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_escape",
|
"askama_escape",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -4294,7 +4294,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-stores"
|
name = "dioxus-stores"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
@@ -4305,7 +4305,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-stores-macro"
|
name = "dioxus-stores-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case 0.8.0",
|
"convert_case 0.8.0",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -4325,7 +4325,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-web"
|
name = "dioxus-web"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ciborium",
|
"ciborium",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -5468,7 +5468,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generational-box"
|
name = "generational-box"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
@@ -7885,7 +7885,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy-js-bundle"
|
name = "lazy-js-bundle"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
@@ -8303,7 +8303,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "manganis"
|
name = "manganis"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-serialize 0.7.2",
|
"const-serialize 0.7.2",
|
||||||
"const-serialize 0.8.0-alpha.0",
|
"const-serialize 0.8.0-alpha.0",
|
||||||
@@ -8317,7 +8317,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "manganis-core"
|
name = "manganis-core"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-serialize 0.7.2",
|
"const-serialize 0.7.2",
|
||||||
"const-serialize 0.8.0-alpha.0",
|
"const-serialize 0.8.0-alpha.0",
|
||||||
@@ -8338,7 +8338,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "manganis-macro"
|
name = "manganis-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
"dunce",
|
||||||
"macro-string",
|
"macro-string",
|
||||||
@@ -12547,7 +12547,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ssr-only"
|
name = "ssr-only"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
]
|
]
|
||||||
@@ -12815,7 +12815,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subsecond"
|
name = "subsecond"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -12841,7 +12841,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subsecond-types"
|
name = "subsecond-types"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -12873,7 +12873,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "suspense-carousel"
|
name = "suspense-carousel"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
@@ -14521,7 +14521,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-split-cli"
|
name = "wasm-split-cli"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -14554,7 +14554,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-split-macro"
|
name = "wasm-split-macro"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16",
|
"base16",
|
||||||
"digest",
|
"digest",
|
||||||
@@ -14566,7 +14566,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-splitter"
|
name = "wasm-splitter"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-once-cell",
|
"async-once-cell",
|
||||||
"wasm-split-macro",
|
"wasm-split-macro",
|
||||||
@@ -14587,7 +14587,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-used"
|
name = "wasm-used"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"id-arena",
|
"id-arena",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -15351,7 +15351,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-headless"
|
name = "windows-headless"
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
]
|
]
|
||||||
|
|||||||
+52
-52
@@ -114,71 +114,71 @@ members = [
|
|||||||
|
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.7.7"
|
version = "0.7.10"
|
||||||
|
|
||||||
# dependencies that are shared across packages
|
# dependencies that are shared across packages
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
dioxus = { path = "packages/dioxus", version = "0.7.7" }
|
dioxus = { path = "packages/dioxus", version = "0.7.10" }
|
||||||
dioxus-core = { path = "packages/core", version = "0.7.7" }
|
dioxus-core = { path = "packages/core", version = "0.7.10" }
|
||||||
dioxus-core-types = { path = "packages/core-types", version = "0.7.7" }
|
dioxus-core-types = { path = "packages/core-types", version = "0.7.10" }
|
||||||
dioxus-core-macro = { path = "packages/core-macro", version = "0.7.7" }
|
dioxus-core-macro = { path = "packages/core-macro", version = "0.7.10" }
|
||||||
dioxus-config-macro = { path = "packages/config-macro", version = "0.7.7" }
|
dioxus-config-macro = { path = "packages/config-macro", version = "0.7.10" }
|
||||||
dioxus-router = { path = "packages/router", version = "0.7.7" }
|
dioxus-router = { path = "packages/router", version = "0.7.10" }
|
||||||
dioxus-router-macro = { path = "packages/router-macro", version = "0.7.7" }
|
dioxus-router-macro = { path = "packages/router-macro", version = "0.7.10" }
|
||||||
dioxus-document = { path = "packages/document", version = "0.7.7", default-features = false }
|
dioxus-document = { path = "packages/document", version = "0.7.10", default-features = false }
|
||||||
dioxus-history = { path = "packages/history", version = "0.7.7", default-features = false }
|
dioxus-history = { path = "packages/history", version = "0.7.10", default-features = false }
|
||||||
dioxus-html = { path = "packages/html", version = "0.7.7", 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.7" }
|
dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.7.10" }
|
||||||
dioxus-hooks = { path = "packages/hooks", version = "0.7.7" }
|
dioxus-hooks = { path = "packages/hooks", version = "0.7.10" }
|
||||||
dioxus-web = { path = "packages/web", version = "0.7.7", default-features = false }
|
dioxus-web = { path = "packages/web", version = "0.7.10", default-features = false }
|
||||||
dioxus-ssr = { path = "packages/ssr", version = "0.7.7", default-features = false }
|
dioxus-ssr = { path = "packages/ssr", version = "0.7.10", default-features = false }
|
||||||
dioxus-desktop = { path = "packages/desktop", version = "0.7.7", default-features = false }
|
dioxus-desktop = { path = "packages/desktop", version = "0.7.10", default-features = false }
|
||||||
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.7" }
|
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.7.10" }
|
||||||
dioxus-liveview = { path = "packages/liveview", version = "0.7.7" }
|
dioxus-liveview = { path = "packages/liveview", version = "0.7.10" }
|
||||||
dioxus-autofmt = { path = "packages/autofmt", version = "0.7.7" }
|
dioxus-autofmt = { path = "packages/autofmt", version = "0.7.10" }
|
||||||
dioxus-rsx = { path = "packages/rsx", version = "0.7.7" }
|
dioxus-rsx = { path = "packages/rsx", version = "0.7.10" }
|
||||||
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.7" }
|
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.7.10" }
|
||||||
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.7" }
|
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.7.10" }
|
||||||
dioxus-signals = { path = "packages/signals", version = "0.7.7" }
|
dioxus-signals = { path = "packages/signals", version = "0.7.10" }
|
||||||
dioxus-stores = { path = "packages/stores", version = "0.7.7" }
|
dioxus-stores = { path = "packages/stores", version = "0.7.10" }
|
||||||
dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.7" }
|
dioxus-stores-macro = { path = "packages/stores-macro", version = "0.7.10" }
|
||||||
dioxus-devtools = { path = "packages/devtools", version = "0.7.7" }
|
dioxus-devtools = { path = "packages/devtools", version = "0.7.10" }
|
||||||
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.7" }
|
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.7.10" }
|
||||||
dioxus-fullstack = { path = "packages/fullstack", version = "0.7.7", default-features = false }
|
dioxus-fullstack = { path = "packages/fullstack", version = "0.7.10", default-features = false }
|
||||||
dioxus-fullstack-core = { path = "packages/fullstack-core", version = "0.7.7", 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.7", 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.7" }
|
dioxus-server = { path = "packages/fullstack-server", version = "0.7.10" }
|
||||||
dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.7" }
|
dioxus-dx-wire-format = { path = "packages/dx-wire-format", version = "0.7.10" }
|
||||||
dioxus-logger = { path = "packages/logger", version = "0.7.7" }
|
dioxus-logger = { path = "packages/logger", version = "0.7.10" }
|
||||||
dioxus-native = { path = "packages/native", version = "0.7.7" }
|
dioxus-native = { path = "packages/native", version = "0.7.10" }
|
||||||
dioxus-native-dom = { path = "packages/native-dom", version = "0.7.7" }
|
dioxus-native-dom = { path = "packages/native-dom", version = "0.7.10" }
|
||||||
dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.7" }
|
dioxus-asset-resolver = { path = "packages/asset-resolver", version = "0.7.10" }
|
||||||
dioxus-config-macros = { path = "packages/config-macros", version = "0.7.7" }
|
dioxus-config-macros = { path = "packages/config-macros", version = "0.7.10" }
|
||||||
dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.7" }
|
dioxus-component-manifest = { path = "packages/component-manifest", version = "0.7.10" }
|
||||||
generational-box = { path = "packages/generational-box", version = "0.7.7" }
|
generational-box = { path = "packages/generational-box", version = "0.7.10" }
|
||||||
lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.7" }
|
lazy-js-bundle = { path = "packages/lazy-js-bundle", version = "0.7.10" }
|
||||||
|
|
||||||
# cli
|
# cli
|
||||||
dioxus-cli-telemetry = { path = "packages/cli-telemetry", 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.7" }
|
dioxus-cli-config = { path = "packages/cli-config", version = "0.7.10" }
|
||||||
|
|
||||||
# subsecond
|
# subsecond
|
||||||
subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.7" }
|
subsecond-types = { path = "packages/subsecond/subsecond-types", version = "0.7.10" }
|
||||||
subsecond = { path = "packages/subsecond/subsecond", version = "0.7.7" }
|
subsecond = { path = "packages/subsecond/subsecond", version = "0.7.10" }
|
||||||
|
|
||||||
# wasm-split
|
# wasm-split
|
||||||
wasm-splitter = { path = "packages/wasm-split/wasm-split", 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.7" }
|
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.7" }
|
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.7" }
|
wasm-used = { path = "packages/wasm-split/wasm-used", version = "0.7.10" }
|
||||||
|
|
||||||
# our dep-info parsing crate
|
# our dep-info parsing crate
|
||||||
depinfo = { path = "packages/depinfo", version = "0.7.7" }
|
depinfo = { path = "packages/depinfo", version = "0.7.10" }
|
||||||
|
|
||||||
# manganis
|
# manganis
|
||||||
manganis = { path = "packages/manganis/manganis", version = "0.7.7" }
|
manganis = { path = "packages/manganis/manganis", version = "0.7.10" }
|
||||||
manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.7" }
|
manganis-core = { path = "packages/manganis/manganis-core", version = "0.7.10" }
|
||||||
manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.7" }
|
manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.7.10" }
|
||||||
manganis-core-07 = { path = "packages/manganis/manganis-07", version = "0.7.2" }
|
manganis-core-07 = { path = "packages/manganis/manganis-07", version = "0.7.2" }
|
||||||
|
|
||||||
# const-serialize.
|
# const-serialize.
|
||||||
|
|||||||
@@ -98,12 +98,19 @@
|
|||||||
);
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages.dioxus-cli = (
|
packages.dioxus-cli =
|
||||||
rustPackage "dioxus-cli" {
|
(rustPackage "dioxus-cli" {
|
||||||
binary = "dx";
|
binary = "dx";
|
||||||
features = [ "no-downloads" ];
|
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;
|
packages.default = self'.packages.dioxus-cli;
|
||||||
checks.dioxus-cli = 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 }
|
dioxus-component-manifest = { workspace = true }
|
||||||
|
|
||||||
bytes = { workspace = true }
|
bytes = { workspace = true }
|
||||||
clap = { workspace = true, features = ["derive", "cargo"] }
|
clap = { workspace = true, features = ["derive", "cargo", "env"] }
|
||||||
convert_case = { workspace = true }
|
convert_case = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
uuid = { workspace = true, features = ["v4", "v5", "v7"] }
|
uuid = { workspace = true, features = ["v4", "v5", "v7"] }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ android {
|
|||||||
applicationId = "{{ application_id }}"
|
applicationId = "{{ application_id }}"
|
||||||
minSdk = {{ min_sdk }}
|
minSdk = {{ min_sdk }}
|
||||||
targetSdk = {{ target_sdk }}
|
targetSdk = {{ target_sdk }}
|
||||||
versionCode = 1
|
versionCode = {{ version_code }}
|
||||||
versionName = "{{ version }}"
|
versionName = "{{ version }}"
|
||||||
}
|
}
|
||||||
{{#if android_bundle}}
|
{{#if android_bundle}}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
{{{ raw_manifest }}}
|
{{{ raw_manifest }}}
|
||||||
|
|
||||||
<application android:hasCode="true" android:icon="@mipmap/ic_launcher"
|
<application android:hasCode="true" android:icon="@mipmap/ic_launcher"
|
||||||
android:extractNativeLibs="true"
|
android:extractNativeLibs="false"
|
||||||
android:allowNativeHeapPointerTagging="false"
|
android:allowNativeHeapPointerTagging="false"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="{{#if supports_rtl}}{{ supports_rtl }}{{else}}true{{/if}}"
|
android:supportsRtl="{{#if supports_rtl}}{{ supports_rtl }}{{else}}true{{/if}}"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:8.7.0")
|
classpath("com.android.tools.build:gradle:8.13.0")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<string>{{ bundle_name }}</string>
|
<string>{{ bundle_name }}</string>
|
||||||
|
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>{{ version }}</string>
|
<string>{{ bundle_version }}</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>{{ version }}</string>
|
<string>{{ version }}</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<string>{{ version }}</string>
|
<string>{{ version }}</string>
|
||||||
|
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>{{ version }}</string>
|
<string>{{ bundle_version }}</string>
|
||||||
|
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>{{ minimum_system_version }}</string>
|
<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;
|
use std::process::Command;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-env-changed=DIOXUS_CLI_GIT_SHA");
|
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-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 manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||||
let output = Command::new("git")
|
let git_dir = find_git_dir(&manifest_dir);
|
||||||
.args(["rev-parse", "HEAD"])
|
|
||||||
.output()
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
// Track the files that determine the current commit. Absolute paths are
|
||||||
return None;
|
// 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 full_hash = env_nonempty("DIOXUS_CLI_GIT_SHA")
|
||||||
let hash = hash.trim().to_string();
|
.or_else(|| git_dir.as_deref().and_then(read_head_sha))
|
||||||
|
.or_else(|| read_cargo_vcs_info(&manifest_dir))
|
||||||
if hash.is_empty() {
|
.or_else(|| git_cli_sha(&manifest_dir));
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(hash)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(full_hash) = full_hash {
|
if let Some(full_hash) = full_hash {
|
||||||
|
let full_hash = full_hash.trim();
|
||||||
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA={full_hash}");
|
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA={full_hash}");
|
||||||
|
|
||||||
let short_hash = std::env::var("DIOXUS_CLI_GIT_SHA_SHORT")
|
let short_hash = env_nonempty("DIOXUS_CLI_GIT_SHA_SHORT")
|
||||||
.ok()
|
|
||||||
.unwrap_or_else(|| full_hash.chars().take(7).collect());
|
.unwrap_or_else(|| full_hash.chars().take(7).collect());
|
||||||
|
|
||||||
println!("cargo:rustc-env=DIOXUS_CLI_GIT_SHA_SHORT={short_hash}");
|
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": {
|
"items": {
|
||||||
"type": "string"
|
"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"
|
"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": {
|
"category": {
|
||||||
"description": "App category. Overrides `bundle.category` for iOS builds.",
|
"description": "App category. Overrides `bundle.category` for iOS builds.",
|
||||||
"type": [
|
"type": [
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ impl BuildRequest {
|
|||||||
application_id: String,
|
application_id: String,
|
||||||
app_name: String,
|
app_name: String,
|
||||||
version: String,
|
version: String,
|
||||||
|
version_code: u32,
|
||||||
android_bundle: Option<crate::AndroidSettings>,
|
android_bundle: Option<crate::AndroidSettings>,
|
||||||
/// Android SDK version settings
|
/// Android SDK version settings
|
||||||
min_sdk: u32,
|
min_sdk: u32,
|
||||||
@@ -180,6 +181,7 @@ impl BuildRequest {
|
|||||||
application_id: self.bundle_identifier(),
|
application_id: self.bundle_identifier(),
|
||||||
app_name: self.bundled_app_name(),
|
app_name: self.bundled_app_name(),
|
||||||
version: self.crate_version(),
|
version: self.crate_version(),
|
||||||
|
version_code: self.android_version_code()?,
|
||||||
android_bundle: self.config.bundle.android.clone(),
|
android_bundle: self.config.bundle.android.clone(),
|
||||||
min_sdk: self.config.android.min_sdk.unwrap_or(24),
|
min_sdk: self.config.android.min_sdk.unwrap_or(24),
|
||||||
target_sdk: self.config.android.target_sdk.unwrap_or(34),
|
target_sdk: self.config.android.target_sdk.unwrap_or(34),
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ impl BuildRequest {
|
|||||||
pub executable_name: String,
|
pub executable_name: String,
|
||||||
/// App version string (from Cargo.toml)
|
/// App version string (from Cargo.toml)
|
||||||
pub version: String,
|
pub version: String,
|
||||||
|
/// Bundle version string (CFBundleVersion)
|
||||||
|
pub bundle_version: String,
|
||||||
/// Permission usage descriptions
|
/// Permission usage descriptions
|
||||||
pub permissions: Vec<PlistPermission>,
|
pub permissions: Vec<PlistPermission>,
|
||||||
/// Additional plist entries as raw XML
|
/// Additional plist entries as raw XML
|
||||||
@@ -231,6 +233,7 @@ impl BuildRequest {
|
|||||||
executable_name: self.platform_exe_name(),
|
executable_name: self.platform_exe_name(),
|
||||||
bundle_identifier: self.bundle_identifier(),
|
bundle_identifier: self.bundle_identifier(),
|
||||||
version: self.crate_version(),
|
version: self.crate_version(),
|
||||||
|
bundle_version: self.apple_bundle_version(),
|
||||||
permissions,
|
permissions,
|
||||||
plist_entries,
|
plist_entries,
|
||||||
raw_plist,
|
raw_plist,
|
||||||
@@ -265,6 +268,7 @@ impl BuildRequest {
|
|||||||
executable_name: self.platform_exe_name(),
|
executable_name: self.platform_exe_name(),
|
||||||
bundle_identifier: self.bundle_identifier(),
|
bundle_identifier: self.bundle_identifier(),
|
||||||
version: self.crate_version(),
|
version: self.crate_version(),
|
||||||
|
bundle_version: self.apple_bundle_version(),
|
||||||
permissions,
|
permissions,
|
||||||
plist_entries,
|
plist_entries,
|
||||||
raw_plist,
|
raw_plist,
|
||||||
|
|||||||
@@ -408,7 +408,9 @@ impl AppBuilder {
|
|||||||
// patch (starting from changed_crates + cascade). That serves a different purpose — it only
|
// 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
|
// compiles what changed now, not everything ever modified. Both use workspace_dependents_of
|
||||||
// for the BFS, so they stay in sync automatically.
|
// 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());
|
self.modified_crates.insert(tip_crate_name.clone());
|
||||||
|
|
||||||
// Add changed crates and their transitive workspace dependents (cascade).
|
// Add changed crates and their transitive workspace dependents (cascade).
|
||||||
|
|||||||
@@ -614,7 +614,9 @@ impl BuildRequest {
|
|||||||
modified_crates: &HashSet<String>,
|
modified_crates: &HashSet<String>,
|
||||||
) -> Result<Vec<String>> {
|
) -> Result<Vec<String>> {
|
||||||
// Exclude the tip crate — it's compiled separately via cargo_build after replay.
|
// 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
|
let crates: HashSet<&String> = modified_crates
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|name| **name != tip)
|
.filter(|name| **name != tip)
|
||||||
|
|||||||
@@ -269,6 +269,8 @@ pub(crate) struct BuildRequest {
|
|||||||
pub(crate) using_dioxus_explicitly: bool,
|
pub(crate) using_dioxus_explicitly: bool,
|
||||||
pub(crate) apple_entitlements: Option<PathBuf>,
|
pub(crate) apple_entitlements: Option<PathBuf>,
|
||||||
pub(crate) apple_team_id: Option<String>,
|
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) session_cache_dir: PathBuf,
|
||||||
pub(crate) raw_json_diagnostics: bool,
|
pub(crate) raw_json_diagnostics: bool,
|
||||||
pub(crate) windows_subsystem: Option<String>,
|
pub(crate) windows_subsystem: Option<String>,
|
||||||
@@ -905,6 +907,8 @@ impl BuildRequest {
|
|||||||
inject_loading_scripts: args.inject_loading_scripts,
|
inject_loading_scripts: args.inject_loading_scripts,
|
||||||
apple_entitlements: args.apple_entitlements.clone(),
|
apple_entitlements: args.apple_entitlements.clone(),
|
||||||
apple_team_id: args.apple_team_id.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,
|
raw_json_diagnostics: args.raw_json_diagnostics,
|
||||||
windows_subsystem: args.windows_subsystem.clone(),
|
windows_subsystem: args.windows_subsystem.clone(),
|
||||||
})
|
})
|
||||||
@@ -2581,6 +2585,16 @@ impl BuildRequest {
|
|||||||
self.main_target.replace('-', "_")
|
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
|
/// 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.
|
/// interception in `rustcwrapper` and read back to surface warnings/errors to the user.
|
||||||
fn link_err_file(&self) -> PathBuf {
|
fn link_err_file(&self) -> PathBuf {
|
||||||
@@ -2675,6 +2689,64 @@ impl BuildRequest {
|
|||||||
.to_string()
|
.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 {
|
pub(crate) fn bundle_identifier(&self) -> String {
|
||||||
use crate::config::BundlePlatform;
|
use crate::config::BundlePlatform;
|
||||||
|
|
||||||
@@ -3095,7 +3167,7 @@ impl BuildRequest {
|
|||||||
})
|
})
|
||||||
.collect();
|
.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 {
|
let Some(tip_nid) = krates.workspace_members().find_map(|m| match m {
|
||||||
krates::Node::Krate { id, krate, .. } if krate.name.replace('-', "_") == tip => {
|
krates::Node::Krate { id, krate, .. } if krate.name.replace('-', "_") == tip => {
|
||||||
krates.nid_for_kid(id)
|
krates.nid_for_kid(id)
|
||||||
|
|||||||
@@ -482,7 +482,11 @@ impl BundleContext<'_> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let version = self.version_string();
|
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(
|
dict.insert(
|
||||||
"CFBundleShortVersionString".into(),
|
"CFBundleShortVersionString".into(),
|
||||||
|
|||||||
@@ -162,6 +162,22 @@ pub(crate) struct TargetArgs {
|
|||||||
#[clap(long, default_value_t = true, help_heading = HELP_HEADING, num_args = 0..=1)]
|
#[clap(long, default_value_t = true, help_heading = HELP_HEADING, num_args = 0..=1)]
|
||||||
pub(crate) wasm_js_cfg: bool,
|
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`.
|
/// 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.
|
/// 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,
|
"debug_symbols": self.debug_symbols,
|
||||||
"keep_names": self.keep_names,
|
"keep_names": self.keep_names,
|
||||||
"device": self.device,
|
"device": self.device,
|
||||||
|
"version_code": self.version_code,
|
||||||
|
"bundle_version": self.bundle_version.is_some(),
|
||||||
"base_path": self.base_path.is_some(),
|
"base_path": self.base_path.is_some(),
|
||||||
"cargo_args": self.cargo_args.is_some(),
|
"cargo_args": self.cargo_args.is_some(),
|
||||||
"rustc_args": self.rustc_args.is_some(),
|
"rustc_args": self.rustc_args.is_some(),
|
||||||
|
|||||||
@@ -326,6 +326,14 @@ pub struct IosConfig {
|
|||||||
pub long_description: Option<String>,
|
pub long_description: Option<String>,
|
||||||
|
|
||||||
// === iOS-specific settings ===
|
// === 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").
|
/// Minimum iOS deployment target (e.g., "15.0").
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub deployment_target: Option<String>,
|
pub deployment_target: Option<String>,
|
||||||
@@ -590,6 +598,16 @@ pub struct AndroidConfig {
|
|||||||
pub signing: Option<AndroidSigningConfig>,
|
pub signing: Option<AndroidSigningConfig>,
|
||||||
|
|
||||||
// === Android-specific settings ===
|
// === 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.
|
/// Minimum SDK version.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub min_sdk: Option<u32>,
|
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.
|
/// 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]`.
|
/// If the changed crate IS the tip crate, returns just `[tip]`.
|
||||||
pub(crate) fn workspace_dep_chain(&self, changed_crate: &str) -> Vec<String> {
|
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 the changed crate is the tip, no chain needed
|
||||||
if changed_crate == tip_name {
|
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.
|
/// The closing behaviour of specific application window.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
@@ -70,6 +74,7 @@ pub struct Config {
|
|||||||
pub(crate) disable_dma_buf_on_wayland: bool,
|
pub(crate) disable_dma_buf_on_wayland: bool,
|
||||||
pub(crate) additional_windows_args: Option<String>,
|
pub(crate) additional_windows_args: Option<String>,
|
||||||
pub(crate) tray_icon_show_window_on_click: bool,
|
pub(crate) tray_icon_show_window_on_click: bool,
|
||||||
|
pub(crate) navigation_handler: Option<NavigationHandler>,
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
|
pub(crate) on_window: Option<Box<dyn FnMut(Arc<Window>, &mut VirtualDom) + 'static>>,
|
||||||
@@ -124,6 +129,7 @@ impl Config {
|
|||||||
on_window: None,
|
on_window: None,
|
||||||
additional_windows_args: None,
|
additional_windows_args: None,
|
||||||
tray_icon_show_window_on_click: true,
|
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.tray_icon_show_window_on_click = show;
|
||||||
self
|
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 {
|
impl Default for Config {
|
||||||
|
|||||||
@@ -353,6 +353,7 @@ impl WebviewInstance {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let navigation_handler = cfg.navigation_handler.take();
|
||||||
let page_loaded = AtomicBool::new(false);
|
let page_loaded = AtomicBool::new(false);
|
||||||
|
|
||||||
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
|
let mut webview = WebViewBuilder::new_with_web_context(&mut web_context)
|
||||||
@@ -367,25 +368,29 @@ impl WebviewInstance {
|
|||||||
.with_url("dioxus://index.html/")
|
.with_url("dioxus://index.html/")
|
||||||
.with_ipc_handler(ipc_handler)
|
.with_ipc_handler(ipc_handler)
|
||||||
.with_navigation_handler(move |var| {
|
.with_navigation_handler(move |var| {
|
||||||
// We don't want to allow any navigation
|
// Serve the index and assets.
|
||||||
// We only want to serve the index file and assets
|
|
||||||
if var.starts_with("dioxus://")
|
if var.starts_with("dioxus://")
|
||||||
|| var.starts_with("http://dioxus.")
|
|| var.starts_with("http://dioxus.")
|
||||||
|| var.starts_with("https://dioxus.")
|
|| var.starts_with("https://dioxus.")
|
||||||
{
|
{
|
||||||
// After the page has loaded once, don't allow any more navigation
|
// After the page has loaded once, don't allow any more navigation
|
||||||
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
|
let page_loaded = page_loaded.swap(true, std::sync::atomic::Ordering::SeqCst);
|
||||||
!page_loaded
|
return !page_loaded;
|
||||||
} else {
|
|
||||||
if var.starts_with("http://")
|
|
||||||
|| var.starts_with("https://")
|
|
||||||
|| var.starts_with("mailto:")
|
|
||||||
{
|
|
||||||
_ = webbrowser::open(&var);
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}) // 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);
|
.with_asynchronous_custom_protocol(String::from("dioxus"), request_handler);
|
||||||
|
|
||||||
// Enable https scheme on android, needed for secure context API, like the geolocation API
|
// 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
|
// 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| {
|
let inner_result: Option<Result<Self, String>> = manganis::android::with_activity(|mut env, activity| {
|
||||||
// Find the class
|
// 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 {
|
let class = match class_result {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => return Some(Err(format!("Failed to find class {}: {:?}", #class_name_lit, e))),
|
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 class_name_bytes = format!("{}\0", name);
|
||||||
|
|
||||||
let type_def = quote! {
|
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
|
/// The actual Swift class is looked up dynamically at runtime after dx links everything
|
||||||
pub struct #name {
|
pub struct #name {
|
||||||
inner: *mut manganis::objc2::runtime::AnyObject,
|
inner: manganis::objc2::rc::Retained<manganis::objc2::runtime::AnyObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for #name {}
|
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![class, alloc];
|
||||||
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![instance, init];
|
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![instance, init];
|
||||||
|
|
||||||
if instance.is_null() {
|
// `alloc` + `init` returns a +1 retained object; `Retained::from_raw`
|
||||||
return Err("Failed to initialize instance");
|
// 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 {
|
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
|
// Build the msg_send call
|
||||||
let this_expr = if func.receiver.is_some() {
|
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 {
|
} else {
|
||||||
// For static methods, we'd need the class
|
// For static methods, we'd need the class
|
||||||
quote! { class }
|
quote! { class }
|
||||||
|
|||||||
@@ -111,17 +111,56 @@ pub fn request_permissions_via_helper(
|
|||||||
Ok(())
|
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>(
|
pub fn load_class_from_classloader<'env>(
|
||||||
env: &mut JNIEnv<'env>,
|
env: &mut JNIEnv<'env>,
|
||||||
|
activity: &JObject<'_>,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
) -> Result<JClass<'env>> {
|
) -> Result<JClass<'env>> {
|
||||||
let class_name_jstring = new_string(env, class_name)?;
|
let binary_name = class_name.replace('/', ".");
|
||||||
let class = env.call_static_method(
|
|
||||||
"java/lang/Class",
|
// Ask the activity INSTANCE for its classloader. `Activity` is a `Context`, and
|
||||||
"forName",
|
// `Context.getClassLoader()` is documented to return a loader for the application
|
||||||
|
// package unconditionally. Do not route this through `get_object_class(activity)`:
|
||||||
|
// that calls `Class.getClassLoader()`, which asks which loader loaded the Activity's
|
||||||
|
// own class and is specified to return null for anything the bootstrap loader
|
||||||
|
// loaded -- a null receiver that then fails obscurely at the `loadClass` below.
|
||||||
|
let loader = env.call_method(activity, "getClassLoader", "()Ljava/lang/ClassLoader;", &[]);
|
||||||
|
let loader = describe_and_clear(env, loader)?.l()?;
|
||||||
|
|
||||||
|
let class_name_jstring = new_string(env, &binary_name);
|
||||||
|
let class_name_jstring = describe_and_clear(env, class_name_jstring)?;
|
||||||
|
|
||||||
|
let class = env.call_method(
|
||||||
|
&loader,
|
||||||
|
"loadClass",
|
||||||
"(Ljava/lang/String;)Ljava/lang/Class;",
|
"(Ljava/lang/String;)Ljava/lang/Class;",
|
||||||
&[JValue::Object(&class_name_jstring)],
|
&[JValue::Object(&class_name_jstring)],
|
||||||
)?;
|
);
|
||||||
|
let class = describe_and_clear(env, class)?;
|
||||||
Ok(class.l()?.into())
|
Ok(class.l()?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Log and clear a pending Java exception before returning an `Err`.
|
||||||
|
///
|
||||||
|
/// jni 0.21 does NOT clear the pending exception when a call returns `Err`
|
||||||
|
/// (see its `JNIEnv` docs), and any later JNI call made while one is pending
|
||||||
|
/// aborts the process with "JNI DETECTED ERROR IN APPLICATION: ... called with
|
||||||
|
/// pending exception". That is what turns a recoverable `ClassNotFoundException`
|
||||||
|
/// into an unreadable ART abort. Describe it to logcat so the cause is visible,
|
||||||
|
/// then clear it so the `Err` can travel normally.
|
||||||
|
fn describe_and_clear<T>(env: &mut JNIEnv<'_>, result: Result<T>) -> Result<T> {
|
||||||
|
if result.is_err() && env.exception_check().unwrap_or(false) {
|
||||||
|
let _ = env.exception_describe();
|
||||||
|
let _ = env.exception_clear();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
@@ -594,24 +594,31 @@ pub unsafe fn apply_patch(mut table: JumpTable) -> Result<(), PatchError> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.unchecked_into();
|
.unchecked_into();
|
||||||
|
|
||||||
// ── SYNC SECTION — no `.await` past this point ────────────────
|
// ── HOST-STATE-MUTATING SECTION ───────────────────────────────
|
||||||
//
|
//
|
||||||
// Everything below mutates shared JS state (linear memory, the
|
// Below we grow shared linear memory and the indirect function
|
||||||
// indirect function table, the patch's data segment) and the
|
// table, then async-instantiate the patch into them and commit
|
||||||
// jump-table pointer. We must not yield, because:
|
// 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
|
// * `memory.grow` and `funcs.grow` each return their PRIOR
|
||||||
// code captured `memory.buffer()` BEFORE the awaits and then
|
// length atomically. Concurrent `apply_patch` tasks therefore
|
||||||
// read its `byteLength` to compute `__memory_base`; if any
|
// each get a unique, non-overlapping `memory_base` /
|
||||||
// other task ran a `memory.grow` during the awaits (e.g. an
|
// `table_base`, so two patches can't land on the same region.
|
||||||
// allocator call from a concurrent render), the snapshot was
|
// * Host code can't observe the half-instantiated patch: the
|
||||||
// detached, `byteLength` returned 0, and the patch's data
|
// new memory pages are zero, the new table slots are null,
|
||||||
// segment ended up loaded over the host's stack/rodata.
|
// and the jump table isn't committed until the very end of
|
||||||
// * Two concurrent `apply_patch` tasks must not interleave
|
// this block, so nothing redirects through the new slots.
|
||||||
// between memory/table grow and `commit_patch`. Doing all
|
// * The original bug — using `memory.buffer().byteLength()`
|
||||||
// side-effecting work in one synchronous turn guarantees that.
|
// captured before the awaits, which returned 0 if the buffer
|
||||||
// * If the future is cancelled before this point, host state
|
// had been detached by a concurrent grow — is gone because
|
||||||
// is untouched.
|
// 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;
|
const PAGE_SIZE: u32 = 64 * 1024;
|
||||||
let patch_pages = (dl_bytes.byte_length() as f64 / PAGE_SIZE as f64).ceil() as u32 + 1;
|
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();
|
let imports = Object::new();
|
||||||
Reflect::set(&imports, &"env".into(), &env).unwrap();
|
Reflect::set(&imports, &"env".into(), &env).unwrap();
|
||||||
|
|
||||||
// Synchronous instantiation of the precompiled module — writes
|
// Async instantiation of the precompiled module. We use the
|
||||||
// the patch's data segment into memory at `memory_base`.
|
// (Module, imports) form of `WebAssembly.instantiate`, which
|
||||||
let instance = Instance::new(&module, &imports).unwrap();
|
// 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();
|
let inst_exports: Object = instance.exports();
|
||||||
|
|
||||||
// Run the patch's relocation thunks and constructors. Order
|
// Run the patch's relocation thunks and constructors. Order
|
||||||
|
|||||||
Reference in new issue
Block a user