mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-17 11:08:54 +02:00
Compare commits
2 Commits
release/ve
...
feat/andro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f032989f2 | ||
|
|
8a8d24e625 |
5
.changes/android-embedded-activity-config.md
Normal file
5
.changes/android-embedded-activity-config.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-utils": minor:feat
|
||||
---
|
||||
|
||||
Added `tauri.conf.json > bundle > android > activityEmbedding` config to enable Activity embedding and define split rules for Android multi-window support.
|
||||
5
.changes/android-embedded-activity-enabler.md
Normal file
5
.changes/android-embedded-activity-enabler.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-build": minor:feat
|
||||
---
|
||||
|
||||
Enable Activity embedding for Android when `tauri.conf.json > bundle > android > activityEmbedding > enabled` is true.
|
||||
5
.changes/android-embedded-activity-generator.md
Normal file
5
.changes/android-embedded-activity-generator.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-build": minor:feat
|
||||
---
|
||||
|
||||
Generate Android split rules based on `tauri.conf.json > bundle > android > activityEmbedding > splitRules`.
|
||||
@@ -496,12 +496,22 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_NAME_PREFIX={android_package_prefix}");
|
||||
|
||||
if let Some(project_dir) = env::var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) {
|
||||
mobile::generate_gradle_files(project_dir)?;
|
||||
let activity_embedding = config
|
||||
.bundle
|
||||
.android
|
||||
.activity_embedding
|
||||
.as_ref()
|
||||
.filter(|c| c.enabled && !c.split_rules.is_empty());
|
||||
|
||||
mobile::generate_gradle_files(project_dir.clone(), activity_embedding)?;
|
||||
|
||||
// Update Android manifest with file associations
|
||||
if let Some(associations) = config.bundle.file_associations.as_ref() {
|
||||
mobile::update_android_manifest_file_associations(associations)?;
|
||||
}
|
||||
|
||||
if let Some(embedding) = activity_embedding {
|
||||
mobile::setup_activity_embedding(&project_dir, embedding, &config.identifier)?;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_alias("dev", is_dev());
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use tauri_utils::{config::AndroidIntentAction, write_if_changed};
|
||||
use tauri_utils::{
|
||||
config::{
|
||||
ActivityEmbeddingConfig, AndroidIntentAction, EmbeddingAspectRatio, SplitFinishBehavior,
|
||||
SplitLayoutDirection, SplitPairRule, SplitType,
|
||||
},
|
||||
write_if_changed,
|
||||
};
|
||||
|
||||
/// Updates the Android manifest to add file association intent filters
|
||||
pub fn update_android_manifest_file_associations(
|
||||
@@ -144,7 +153,10 @@ fn extension_to_mime_type(ext: &str) -> Option<String> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_gradle_files(project_dir: PathBuf) -> Result<()> {
|
||||
pub fn generate_gradle_files(
|
||||
project_dir: PathBuf,
|
||||
activity_embedding: Option<&ActivityEmbeddingConfig>,
|
||||
) -> Result<()> {
|
||||
let gradle_settings_path = project_dir.join("tauri.settings.gradle");
|
||||
let app_build_gradle_path = project_dir.join("app").join("tauri.build.gradle.kts");
|
||||
|
||||
@@ -156,6 +168,11 @@ dependencies {
|
||||
implementation(\"androidx.lifecycle:lifecycle-process:2.10.0\")"
|
||||
.to_string();
|
||||
|
||||
if activity_embedding.is_some() {
|
||||
app_build_gradle.push_str("\n implementation(\"androidx.window:window:1.5.0\")");
|
||||
app_build_gradle.push_str("\n implementation(\"androidx.startup:startup-runtime:1.2.0\")");
|
||||
}
|
||||
|
||||
for (env, value) in std::env::vars_os() {
|
||||
let env = env.to_string_lossy();
|
||||
if env.starts_with("DEP_") && env.ends_with("_ANDROID_LIBRARY_PATH") {
|
||||
@@ -187,7 +204,6 @@ dependencies {
|
||||
|
||||
app_build_gradle.push_str("\n}");
|
||||
|
||||
// Overwrite only if changed to not trigger rebuilds
|
||||
write_if_changed(&gradle_settings_path, gradle_settings)
|
||||
.context("failed to write tauri.settings.gradle")?;
|
||||
|
||||
@@ -199,3 +215,256 @@ dependencies {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configures Android Activity Embedding: updates the manifest, generates Gradle
|
||||
/// dependencies, and writes the `TauriSplitInitializer.kt` file.
|
||||
pub fn setup_activity_embedding(
|
||||
project_dir: &Path,
|
||||
config: &ActivityEmbeddingConfig,
|
||||
identifier: &str,
|
||||
) -> Result<()> {
|
||||
if config.split_rules.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let package_name = identifier_to_android_package(identifier);
|
||||
|
||||
update_android_manifest_activity_embedding(config, &package_name)?;
|
||||
generate_split_initializer(project_dir, config, &package_name)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn identifier_to_android_package(identifier: &str) -> String {
|
||||
identifier
|
||||
.split('.')
|
||||
.map(|s| s.replace('-', "_"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(".")
|
||||
}
|
||||
|
||||
fn update_android_manifest_activity_embedding(
|
||||
config: &ActivityEmbeddingConfig,
|
||||
package_name: &str,
|
||||
) -> Result<()> {
|
||||
let mut xml = String::new();
|
||||
|
||||
xml.push_str(
|
||||
"<property\n \
|
||||
android:name=\"android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED\"\n \
|
||||
android:value=\"true\" />\n",
|
||||
);
|
||||
|
||||
xml.push_str(&format!(
|
||||
"<provider\n \
|
||||
android:name=\"androidx.startup.InitializationProvider\"\n \
|
||||
android:authorities=\"${{applicationId}}.androidx-startup\"\n \
|
||||
android:exported=\"false\">\n \
|
||||
<meta-data\n \
|
||||
android:name=\"{package_name}.TauriSplitInitializer\"\n \
|
||||
android:value=\"androidx.startup\" />\n\
|
||||
</provider>\n"
|
||||
));
|
||||
|
||||
let mut declared = HashSet::new();
|
||||
for rule in &config.split_rules {
|
||||
let name = if rule.secondary.contains('.') {
|
||||
rule.secondary.clone()
|
||||
} else {
|
||||
format!(".{}", rule.secondary)
|
||||
};
|
||||
if !declared.insert(name.clone()) {
|
||||
continue;
|
||||
}
|
||||
xml.push_str(&format!(
|
||||
"<activity\n \
|
||||
android:name=\"{name}\"\n \
|
||||
android:exported=\"false\"\n \
|
||||
android:configChanges=\"orientation|screenSize|screenLayout|smallestScreenSize\" />\n"
|
||||
));
|
||||
}
|
||||
|
||||
tauri_utils::build::update_android_manifest("tauri-activity-embedding", "application", xml)
|
||||
}
|
||||
|
||||
fn generate_split_initializer(
|
||||
project_dir: &Path,
|
||||
config: &ActivityEmbeddingConfig,
|
||||
package_name: &str,
|
||||
) -> Result<()> {
|
||||
let package_dir = package_name.replace('.', "/");
|
||||
let source_dir = project_dir
|
||||
.join("app/src/main/java")
|
||||
.join(&package_dir)
|
||||
.join("generated");
|
||||
std::fs::create_dir_all(&source_dir)
|
||||
.context("failed to create Android source directory for split initializer")?;
|
||||
|
||||
let mut kt = String::new();
|
||||
kt.push_str(&format!(
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\npackage {package_name}\n\n"
|
||||
));
|
||||
kt.push_str(
|
||||
"import android.content.ComponentName\n\
|
||||
import android.content.Context\n\
|
||||
import androidx.startup.Initializer\n\
|
||||
import androidx.window.embedding.EmbeddingAspectRatio\n\
|
||||
import androidx.window.embedding.RuleController\n\
|
||||
import androidx.window.embedding.SplitAttributes\n\
|
||||
import androidx.window.embedding.SplitPairFilter\n\
|
||||
import androidx.window.embedding.SplitPairRule\n\
|
||||
import androidx.window.embedding.SplitRule\n\n",
|
||||
);
|
||||
kt.push_str(
|
||||
"class TauriSplitInitializer : Initializer<RuleController> {\n \
|
||||
override fun create(context: Context): RuleController {\n \
|
||||
val ruleController = RuleController.getInstance(context)\n\n",
|
||||
);
|
||||
|
||||
for (i, rule) in config.split_rules.iter().enumerate() {
|
||||
append_split_rule(&mut kt, i, rule, package_name);
|
||||
}
|
||||
|
||||
kt.push_str(
|
||||
" return ruleController\n \
|
||||
}\n\n \
|
||||
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()\n\
|
||||
}\n",
|
||||
);
|
||||
|
||||
let initializer_path = source_dir.join("TauriSplitInitializer.kt");
|
||||
write_if_changed(&initializer_path, kt).context("failed to write TauriSplitInitializer.kt")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn append_split_rule(kt: &mut String, i: usize, rule: &SplitPairRule, package_name: &str) {
|
||||
let primary = qualify_activity(&rule.primary, package_name);
|
||||
let secondary = qualify_activity(&rule.secondary, package_name);
|
||||
let secondary_intent_action = rule
|
||||
.secondary_intent_action
|
||||
.as_deref()
|
||||
.map(|s| format!("{s:?}"))
|
||||
.unwrap_or_else(|| "null".to_string());
|
||||
|
||||
kt.push_str(&format!(
|
||||
" val filter{i} = SplitPairFilter(\n \
|
||||
ComponentName(context, {primary}::class.java),\n \
|
||||
ComponentName(context, {secondary}::class.java),\n \
|
||||
{secondary_intent_action}\n \
|
||||
)\n"
|
||||
));
|
||||
|
||||
kt.push_str(&format!(
|
||||
" val attrsBuilder{i} = SplitAttributes.Builder()\n"
|
||||
));
|
||||
if let Some(split_type) = &rule.split_type {
|
||||
kt.push_str(&format!(
|
||||
" attrsBuilder{i}.setSplitType({})\n",
|
||||
kotlin_split_type(split_type)
|
||||
));
|
||||
}
|
||||
if let Some(direction) = rule.layout_direction {
|
||||
kt.push_str(&format!(
|
||||
" attrsBuilder{i}.setLayoutDirection({})\n",
|
||||
kotlin_layout_direction(direction)
|
||||
));
|
||||
}
|
||||
kt.push_str(&format!(" val attrs{i} = attrsBuilder{i}.build()\n"));
|
||||
|
||||
kt.push_str(&format!(
|
||||
" val ruleBuilder{i} = SplitPairRule.Builder(setOf(filter{i}))\n \
|
||||
ruleBuilder{i}.setDefaultSplitAttributes(attrs{i})\n"
|
||||
));
|
||||
|
||||
if let Some(dp) = rule.min_width_dp {
|
||||
kt.push_str(&format!(" ruleBuilder{i}.setMinWidthDp({dp})\n"));
|
||||
}
|
||||
if let Some(dp) = rule.min_height_dp {
|
||||
kt.push_str(&format!(" ruleBuilder{i}.setMinHeightDp({dp})\n"));
|
||||
}
|
||||
if let Some(dp) = rule.min_smallest_width_dp {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setMinSmallestWidthDp({dp})\n"
|
||||
));
|
||||
}
|
||||
if let Some(ar) = &rule.max_aspect_ratio_in_portrait {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setMaxAspectRatioInPortrait({})\n",
|
||||
kotlin_aspect_ratio(ar)
|
||||
));
|
||||
}
|
||||
if let Some(ar) = &rule.max_aspect_ratio_in_landscape {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setMaxAspectRatioInLandscape({})\n",
|
||||
kotlin_aspect_ratio(ar)
|
||||
));
|
||||
}
|
||||
if let Some(b) = rule.finish_primary_with_secondary {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setFinishPrimaryWithSecondary({})\n",
|
||||
kotlin_finish_behavior(b)
|
||||
));
|
||||
}
|
||||
if let Some(b) = rule.finish_secondary_with_primary {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setFinishSecondaryWithPrimary({})\n",
|
||||
kotlin_finish_behavior(b)
|
||||
));
|
||||
}
|
||||
if let Some(clear_top) = rule.clear_top {
|
||||
kt.push_str(&format!(
|
||||
" ruleBuilder{i}.setClearTop({clear_top})\n"
|
||||
));
|
||||
}
|
||||
if let Some(tag) = &rule.tag {
|
||||
kt.push_str(&format!(" ruleBuilder{i}.setTag({tag:?})\n"));
|
||||
}
|
||||
|
||||
kt.push_str(&format!(
|
||||
" val rule{i} = ruleBuilder{i}.build()\n \
|
||||
ruleController.addRule(rule{i})\n\n"
|
||||
));
|
||||
}
|
||||
|
||||
fn qualify_activity(name: &str, package_name: &str) -> String {
|
||||
if name.contains('.') {
|
||||
name.to_string()
|
||||
} else {
|
||||
format!("{package_name}.{name}")
|
||||
}
|
||||
}
|
||||
|
||||
fn kotlin_split_type(split_type: &SplitType) -> String {
|
||||
match split_type {
|
||||
SplitType::Ratio(r) => format!("SplitAttributes.SplitType.ratio({r}f)"),
|
||||
SplitType::Expand => "SplitAttributes.SplitType.SPLIT_TYPE_EXPAND".to_string(),
|
||||
SplitType::Hinge => "SplitAttributes.SplitType.SPLIT_TYPE_HINGE".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn kotlin_layout_direction(direction: SplitLayoutDirection) -> &'static str {
|
||||
match direction {
|
||||
SplitLayoutDirection::Locale => "SplitAttributes.LayoutDirection.LOCALE",
|
||||
SplitLayoutDirection::LeftToRight => "SplitAttributes.LayoutDirection.LEFT_TO_RIGHT",
|
||||
SplitLayoutDirection::RightToLeft => "SplitAttributes.LayoutDirection.RIGHT_TO_LEFT",
|
||||
SplitLayoutDirection::TopToBottom => "SplitAttributes.LayoutDirection.TOP_TO_BOTTOM",
|
||||
SplitLayoutDirection::BottomToTop => "SplitAttributes.LayoutDirection.BOTTOM_TO_TOP",
|
||||
}
|
||||
}
|
||||
|
||||
fn kotlin_finish_behavior(behavior: SplitFinishBehavior) -> &'static str {
|
||||
match behavior {
|
||||
SplitFinishBehavior::Never => "SplitRule.FinishBehavior.NEVER",
|
||||
SplitFinishBehavior::Always => "SplitRule.FinishBehavior.ALWAYS",
|
||||
SplitFinishBehavior::Adjacent => "SplitRule.FinishBehavior.ADJACENT",
|
||||
}
|
||||
}
|
||||
|
||||
fn kotlin_aspect_ratio(ar: &EmbeddingAspectRatio) -> String {
|
||||
match ar {
|
||||
EmbeddingAspectRatio::AlwaysAllow => "EmbeddingAspectRatio.ALWAYS_ALLOW".to_string(),
|
||||
EmbeddingAspectRatio::AlwaysDisallow => "EmbeddingAspectRatio.ALWAYS_DISALLOW".to_string(),
|
||||
EmbeddingAspectRatio::Ratio(r) => format!("EmbeddingAspectRatio.ratio({r}f)"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3914,10 +3914,306 @@
|
||||
"description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"activityEmbedding": {
|
||||
"description": "Activity embedding for large screens (tablets, foldables).\n\n When set and enabled, Tauri generates the Gradle dependencies, Android manifest entries,\n and a `TauriSplitInitializer` Kotlin class for split-screen activity layouts.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ActivityEmbeddingConfig"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ActivityEmbeddingConfig": {
|
||||
"description": "Configuration for Android Activity Embedding, which splits activities\n side by side on large screens.\n\n See <https://developer.android.com/guide/topics/large-screens/activity-embedding>",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "When `false`, Tauri does not generate embedding Gradle entries, manifest updates, or `TauriSplitInitializer`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"splitRules": {
|
||||
"description": "Split pair rules defining how activities are laid out side by side.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SplitPairRule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SplitPairRule": {
|
||||
"description": "A split pair rule for Android Activity Embedding.\n\n Defines how a primary and secondary activity are displayed side by side\n on screens that satisfy the configured minimum dimensions.\n\n Mirrors the fields of [`androidx.window.embedding.SplitPairRule.Builder`] and\n the [`SplitPairFilter`] it accepts. Only [`primary`](Self::primary) and\n [`secondary`](Self::secondary) are required; all other fields fall back to\n the Android SDK defaults when omitted.\n\n [`androidx.window.embedding.SplitPairRule.Builder`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairRule.Builder\n [`SplitPairFilter`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairFilter",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"primary",
|
||||
"secondary"
|
||||
],
|
||||
"properties": {
|
||||
"primary": {
|
||||
"description": "The primary activity class name, relative to the application package\n (e.g. `\"MainActivity\"` or a fully-qualified name like\n `\"com.example.MainActivity\"`).",
|
||||
"type": "string"
|
||||
},
|
||||
"secondary": {
|
||||
"description": "The secondary activity class name, relative to the application package\n (e.g. `\"DetailActivity\"` or a fully-qualified name).",
|
||||
"type": "string"
|
||||
},
|
||||
"secondaryIntentAction": {
|
||||
"description": "Optional intent action used to match the secondary activity when it is\n started via an implicit intent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"splitType": {
|
||||
"description": "How the parent window is split. When omitted, the SDK uses an equal\n 50/50 ratio.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"layoutDirection": {
|
||||
"description": "The layout direction of the primary/secondary containers. Defaults to\n the system locale direction.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitLayoutDirection"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minWidthDp": {
|
||||
"description": "Minimum parent window width in dp for the split to apply. Defaults to the\n SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"minHeightDp": {
|
||||
"description": "Minimum parent window height in dp for the split to apply. Defaults to the\n SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"minSmallestWidthDp": {
|
||||
"description": "Minimum smallest width of the parent window in dp for the split to apply.\n Defaults to the SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxAspectRatioInPortrait": {
|
||||
"description": "Maximum height/width aspect ratio (portrait) for which the split applies.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/EmbeddingAspectRatio"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxAspectRatioInLandscape": {
|
||||
"description": "Maximum height/width aspect ratio (landscape) for which the split applies.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/EmbeddingAspectRatio"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"finishPrimaryWithSecondary": {
|
||||
"description": "Behavior of the primary container when all activities in the secondary\n container finish. Defaults to [`SplitFinishBehavior::Never`].",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitFinishBehavior"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"finishSecondaryWithPrimary": {
|
||||
"description": "Behavior of the secondary container when all activities in the primary\n container finish. Defaults to [`SplitFinishBehavior::Always`].",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitFinishBehavior"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"clearTop": {
|
||||
"description": "Whether the existing secondary container and all activities in it should\n be destroyed when a new split is created using this rule.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"description": "Optional tag used to identify this rule at runtime.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SplitType": {
|
||||
"description": "How the parent window is split between primary and secondary containers.\n\n Mirrors [`androidx.window.embedding.SplitAttributes.SplitType`].\n\n [`androidx.window.embedding.SplitAttributes.SplitType`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.SplitType",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Splits the parent into two containers with the given weight\n for the primary container (0.0 exclusive to 1.0 exclusive).",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ratio"
|
||||
],
|
||||
"properties": {
|
||||
"ratio": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"description": "The secondary container expands to cover the entire parent window.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"expand"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "The split aligns with the device hinge/fold. Cannot be used as a\n default split type without hinge-aware devices.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"hinge"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"SplitLayoutDirection": {
|
||||
"description": "A layout direction for an activity embedding split.\n\n Mirrors [`androidx.window.embedding.SplitAttributes.LayoutDirection`].\n\n [`androidx.window.embedding.SplitAttributes.LayoutDirection`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.LayoutDirection",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Use the system locale's layout direction.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"locale"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the left, secondary on the right.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"leftToRight"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the right, secondary on the left.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"rightToLeft"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on top, secondary on the bottom.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"topToBottom"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the bottom, secondary on top.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bottomToTop"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"EmbeddingAspectRatio": {
|
||||
"description": "Maximum aspect ratio (height / width) of the parent window for which\n activity embedding should apply.\n\n Mirrors [`androidx.window.embedding.EmbeddingAspectRatio`].\n\n [`androidx.window.embedding.EmbeddingAspectRatio`]: https://developer.android.com/reference/androidx/window/embedding/EmbeddingAspectRatio",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Embedding always applies regardless of aspect ratio.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alwaysAllow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Embedding never applies in this orientation.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alwaysDisallow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Embedding applies when the parent window aspect ratio is less than or\n equal to this value. Must be greater than `1.0`.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ratio"
|
||||
],
|
||||
"properties": {
|
||||
"ratio": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"SplitFinishBehavior": {
|
||||
"description": "Describes how an activity container should finish when the linked\n container finishes.\n\n Mirrors [`androidx.window.embedding.SplitRule.FinishBehavior`].\n\n [`androidx.window.embedding.SplitRule.FinishBehavior`]: https://developer.android.com/reference/androidx/window/embedding/SplitRule.FinishBehavior",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Never finish the container when the linked container finishes.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"never"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Always finish the container when the linked container finishes.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"always"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Finish the container only when the linked container finishes\n while they are displayed side-by-side.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"adjacent"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginConfig": {
|
||||
"description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.\n\n See more: <https://v2.tauri.app/reference/config/#pluginconfig>",
|
||||
"type": "object",
|
||||
|
||||
@@ -3914,10 +3914,306 @@
|
||||
"description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"activityEmbedding": {
|
||||
"description": "Activity embedding for large screens (tablets, foldables).\n\n When set and enabled, Tauri generates the Gradle dependencies, Android manifest entries,\n and a `TauriSplitInitializer` Kotlin class for split-screen activity layouts.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ActivityEmbeddingConfig"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ActivityEmbeddingConfig": {
|
||||
"description": "Configuration for Android Activity Embedding, which splits activities\n side by side on large screens.\n\n See <https://developer.android.com/guide/topics/large-screens/activity-embedding>",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "When `false`, Tauri does not generate embedding Gradle entries, manifest updates, or `TauriSplitInitializer`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"splitRules": {
|
||||
"description": "Split pair rules defining how activities are laid out side by side.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SplitPairRule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SplitPairRule": {
|
||||
"description": "A split pair rule for Android Activity Embedding.\n\n Defines how a primary and secondary activity are displayed side by side\n on screens that satisfy the configured minimum dimensions.\n\n Mirrors the fields of [`androidx.window.embedding.SplitPairRule.Builder`] and\n the [`SplitPairFilter`] it accepts. Only [`primary`](Self::primary) and\n [`secondary`](Self::secondary) are required; all other fields fall back to\n the Android SDK defaults when omitted.\n\n [`androidx.window.embedding.SplitPairRule.Builder`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairRule.Builder\n [`SplitPairFilter`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairFilter",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"primary",
|
||||
"secondary"
|
||||
],
|
||||
"properties": {
|
||||
"primary": {
|
||||
"description": "The primary activity class name, relative to the application package\n (e.g. `\"MainActivity\"` or a fully-qualified name like\n `\"com.example.MainActivity\"`).",
|
||||
"type": "string"
|
||||
},
|
||||
"secondary": {
|
||||
"description": "The secondary activity class name, relative to the application package\n (e.g. `\"DetailActivity\"` or a fully-qualified name).",
|
||||
"type": "string"
|
||||
},
|
||||
"secondaryIntentAction": {
|
||||
"description": "Optional intent action used to match the secondary activity when it is\n started via an implicit intent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"splitType": {
|
||||
"description": "How the parent window is split. When omitted, the SDK uses an equal\n 50/50 ratio.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitType"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"layoutDirection": {
|
||||
"description": "The layout direction of the primary/secondary containers. Defaults to\n the system locale direction.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitLayoutDirection"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"minWidthDp": {
|
||||
"description": "Minimum parent window width in dp for the split to apply. Defaults to the\n SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"minHeightDp": {
|
||||
"description": "Minimum parent window height in dp for the split to apply. Defaults to the\n SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"minSmallestWidthDp": {
|
||||
"description": "Minimum smallest width of the parent window in dp for the split to apply.\n Defaults to the SDK value (`600`).",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"format": "uint32",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"maxAspectRatioInPortrait": {
|
||||
"description": "Maximum height/width aspect ratio (portrait) for which the split applies.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/EmbeddingAspectRatio"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxAspectRatioInLandscape": {
|
||||
"description": "Maximum height/width aspect ratio (landscape) for which the split applies.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/EmbeddingAspectRatio"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"finishPrimaryWithSecondary": {
|
||||
"description": "Behavior of the primary container when all activities in the secondary\n container finish. Defaults to [`SplitFinishBehavior::Never`].",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitFinishBehavior"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"finishSecondaryWithPrimary": {
|
||||
"description": "Behavior of the secondary container when all activities in the primary\n container finish. Defaults to [`SplitFinishBehavior::Always`].",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SplitFinishBehavior"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"clearTop": {
|
||||
"description": "Whether the existing secondary container and all activities in it should\n be destroyed when a new split is created using this rule.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"description": "Optional tag used to identify this rule at runtime.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"SplitType": {
|
||||
"description": "How the parent window is split between primary and secondary containers.\n\n Mirrors [`androidx.window.embedding.SplitAttributes.SplitType`].\n\n [`androidx.window.embedding.SplitAttributes.SplitType`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.SplitType",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Splits the parent into two containers with the given weight\n for the primary container (0.0 exclusive to 1.0 exclusive).",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ratio"
|
||||
],
|
||||
"properties": {
|
||||
"ratio": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"description": "The secondary container expands to cover the entire parent window.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"expand"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "The split aligns with the device hinge/fold. Cannot be used as a\n default split type without hinge-aware devices.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"hinge"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"SplitLayoutDirection": {
|
||||
"description": "A layout direction for an activity embedding split.\n\n Mirrors [`androidx.window.embedding.SplitAttributes.LayoutDirection`].\n\n [`androidx.window.embedding.SplitAttributes.LayoutDirection`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.LayoutDirection",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Use the system locale's layout direction.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"locale"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the left, secondary on the right.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"leftToRight"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the right, secondary on the left.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"rightToLeft"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on top, secondary on the bottom.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"topToBottom"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Primary on the bottom, secondary on top.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bottomToTop"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"EmbeddingAspectRatio": {
|
||||
"description": "Maximum aspect ratio (height / width) of the parent window for which\n activity embedding should apply.\n\n Mirrors [`androidx.window.embedding.EmbeddingAspectRatio`].\n\n [`androidx.window.embedding.EmbeddingAspectRatio`]: https://developer.android.com/reference/androidx/window/embedding/EmbeddingAspectRatio",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Embedding always applies regardless of aspect ratio.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alwaysAllow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Embedding never applies in this orientation.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alwaysDisallow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Embedding applies when the parent window aspect ratio is less than or\n equal to this value. Must be greater than `1.0`.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ratio"
|
||||
],
|
||||
"properties": {
|
||||
"ratio": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"SplitFinishBehavior": {
|
||||
"description": "Describes how an activity container should finish when the linked\n container finishes.\n\n Mirrors [`androidx.window.embedding.SplitRule.FinishBehavior`].\n\n [`androidx.window.embedding.SplitRule.FinishBehavior`]: https://developer.android.com/reference/androidx/window/embedding/SplitRule.FinishBehavior",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Never finish the container when the linked container finishes.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"never"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Always finish the container when the linked container finishes.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"always"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Finish the container only when the linked container finishes\n while they are displayed side-by-side.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"adjacent"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginConfig": {
|
||||
"description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.\n\n See more: <https://v2.tauri.app/reference/config/#pluginconfig>",
|
||||
"type": "object",
|
||||
|
||||
@@ -1549,7 +1549,7 @@ pub enum V1Compatible {
|
||||
///
|
||||
/// See more: <https://v2.tauri.app/reference/config/#bundleconfig>
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct BundleConfig {
|
||||
@@ -3176,9 +3176,179 @@ impl Default for IosConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for Android Activity Embedding, which splits activities
|
||||
/// side by side on large screens.
|
||||
///
|
||||
/// See <https://developer.android.com/guide/topics/large-screens/activity-embedding>
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct ActivityEmbeddingConfig {
|
||||
/// When `false`, Tauri does not generate embedding Gradle entries, manifest updates, or `TauriSplitInitializer`.
|
||||
#[serde(default = "default_true")]
|
||||
pub enabled: bool,
|
||||
/// Split pair rules defining how activities are laid out side by side.
|
||||
#[serde(alias = "split-rules", default)]
|
||||
pub split_rules: Vec<SplitPairRule>,
|
||||
}
|
||||
|
||||
/// A split pair rule for Android Activity Embedding.
|
||||
///
|
||||
/// Defines how a primary and secondary activity are displayed side by side
|
||||
/// on screens that satisfy the configured minimum dimensions.
|
||||
///
|
||||
/// Mirrors the fields of [`androidx.window.embedding.SplitPairRule.Builder`] and
|
||||
/// the [`SplitPairFilter`] it accepts. Only [`primary`](Self::primary) and
|
||||
/// [`secondary`](Self::secondary) are required; all other fields fall back to
|
||||
/// the Android SDK defaults when omitted.
|
||||
///
|
||||
/// [`androidx.window.embedding.SplitPairRule.Builder`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairRule.Builder
|
||||
/// [`SplitPairFilter`]: https://developer.android.com/reference/androidx/window/embedding/SplitPairFilter
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct SplitPairRule {
|
||||
/// The primary activity class name, relative to the application package
|
||||
/// (e.g. `"MainActivity"` or a fully-qualified name like
|
||||
/// `"com.example.MainActivity"`).
|
||||
pub primary: String,
|
||||
/// The secondary activity class name, relative to the application package
|
||||
/// (e.g. `"DetailActivity"` or a fully-qualified name).
|
||||
pub secondary: String,
|
||||
/// Optional intent action used to match the secondary activity when it is
|
||||
/// started via an implicit intent.
|
||||
#[serde(alias = "secondary-intent-action")]
|
||||
pub secondary_intent_action: Option<String>,
|
||||
|
||||
/// How the parent window is split. When omitted, the SDK uses an equal
|
||||
/// 50/50 ratio.
|
||||
#[serde(alias = "split-type")]
|
||||
pub split_type: Option<SplitType>,
|
||||
/// The layout direction of the primary/secondary containers. Defaults to
|
||||
/// the system locale direction.
|
||||
#[serde(alias = "layout-direction")]
|
||||
pub layout_direction: Option<SplitLayoutDirection>,
|
||||
|
||||
/// Minimum parent window width in dp for the split to apply. Defaults to the
|
||||
/// SDK value (`600`).
|
||||
#[serde(alias = "min-width-dp")]
|
||||
pub min_width_dp: Option<u32>,
|
||||
/// Minimum parent window height in dp for the split to apply. Defaults to the
|
||||
/// SDK value (`600`).
|
||||
#[serde(alias = "min-height-dp")]
|
||||
pub min_height_dp: Option<u32>,
|
||||
/// Minimum smallest width of the parent window in dp for the split to apply.
|
||||
/// Defaults to the SDK value (`600`).
|
||||
#[serde(alias = "min-smallest-width-dp")]
|
||||
pub min_smallest_width_dp: Option<u32>,
|
||||
|
||||
/// Maximum height/width aspect ratio (portrait) for which the split applies.
|
||||
#[serde(alias = "max-aspect-ratio-in-portrait")]
|
||||
pub max_aspect_ratio_in_portrait: Option<EmbeddingAspectRatio>,
|
||||
/// Maximum height/width aspect ratio (landscape) for which the split applies.
|
||||
#[serde(alias = "max-aspect-ratio-in-landscape")]
|
||||
pub max_aspect_ratio_in_landscape: Option<EmbeddingAspectRatio>,
|
||||
|
||||
/// Behavior of the primary container when all activities in the secondary
|
||||
/// container finish. Defaults to [`SplitFinishBehavior::Never`].
|
||||
#[serde(alias = "finish-primary-with-secondary")]
|
||||
pub finish_primary_with_secondary: Option<SplitFinishBehavior>,
|
||||
/// Behavior of the secondary container when all activities in the primary
|
||||
/// container finish. Defaults to [`SplitFinishBehavior::Always`].
|
||||
#[serde(alias = "finish-secondary-with-primary")]
|
||||
pub finish_secondary_with_primary: Option<SplitFinishBehavior>,
|
||||
|
||||
/// Whether the existing secondary container and all activities in it should
|
||||
/// be destroyed when a new split is created using this rule.
|
||||
#[serde(alias = "clear-top")]
|
||||
pub clear_top: Option<bool>,
|
||||
|
||||
/// Optional tag used to identify this rule at runtime.
|
||||
pub tag: Option<String>,
|
||||
}
|
||||
|
||||
/// How the parent window is split between primary and secondary containers.
|
||||
///
|
||||
/// Mirrors [`androidx.window.embedding.SplitAttributes.SplitType`].
|
||||
///
|
||||
/// [`androidx.window.embedding.SplitAttributes.SplitType`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.SplitType
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub enum SplitType {
|
||||
/// Splits the parent into two containers with the given weight
|
||||
/// for the primary container (0.0 exclusive to 1.0 exclusive).
|
||||
Ratio(f64),
|
||||
/// The secondary container expands to cover the entire parent window.
|
||||
Expand,
|
||||
/// The split aligns with the device hinge/fold. Cannot be used as a
|
||||
/// default split type without hinge-aware devices.
|
||||
Hinge,
|
||||
}
|
||||
|
||||
/// A layout direction for an activity embedding split.
|
||||
///
|
||||
/// Mirrors [`androidx.window.embedding.SplitAttributes.LayoutDirection`].
|
||||
///
|
||||
/// [`androidx.window.embedding.SplitAttributes.LayoutDirection`]: https://developer.android.com/reference/androidx/window/embedding/SplitAttributes.LayoutDirection
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum SplitLayoutDirection {
|
||||
/// Use the system locale's layout direction.
|
||||
Locale,
|
||||
/// Primary on the left, secondary on the right.
|
||||
LeftToRight,
|
||||
/// Primary on the right, secondary on the left.
|
||||
RightToLeft,
|
||||
/// Primary on top, secondary on the bottom.
|
||||
TopToBottom,
|
||||
/// Primary on the bottom, secondary on top.
|
||||
BottomToTop,
|
||||
}
|
||||
|
||||
/// Describes how an activity container should finish when the linked
|
||||
/// container finishes.
|
||||
///
|
||||
/// Mirrors [`androidx.window.embedding.SplitRule.FinishBehavior`].
|
||||
///
|
||||
/// [`androidx.window.embedding.SplitRule.FinishBehavior`]: https://developer.android.com/reference/androidx/window/embedding/SplitRule.FinishBehavior
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum SplitFinishBehavior {
|
||||
/// Never finish the container when the linked container finishes.
|
||||
Never,
|
||||
/// Always finish the container when the linked container finishes.
|
||||
Always,
|
||||
/// Finish the container only when the linked container finishes
|
||||
/// while they are displayed side-by-side.
|
||||
Adjacent,
|
||||
}
|
||||
|
||||
/// Maximum aspect ratio (height / width) of the parent window for which
|
||||
/// activity embedding should apply.
|
||||
///
|
||||
/// Mirrors [`androidx.window.embedding.EmbeddingAspectRatio`].
|
||||
///
|
||||
/// [`androidx.window.embedding.EmbeddingAspectRatio`]: https://developer.android.com/reference/androidx/window/embedding/EmbeddingAspectRatio
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub enum EmbeddingAspectRatio {
|
||||
/// Embedding always applies regardless of aspect ratio.
|
||||
AlwaysAllow,
|
||||
/// Embedding never applies in this orientation.
|
||||
AlwaysDisallow,
|
||||
/// Embedding applies when the parent window aspect ratio is less than or
|
||||
/// equal to this value. Must be greater than `1.0`.
|
||||
Ratio(f64),
|
||||
}
|
||||
|
||||
/// General configuration for the Android target.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "schema", derive(JsonSchema))]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct AndroidConfig {
|
||||
@@ -3205,6 +3375,13 @@ pub struct AndroidConfig {
|
||||
/// Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.
|
||||
#[serde(alias = "auto-increment-version-code", default)]
|
||||
pub auto_increment_version_code: bool,
|
||||
|
||||
/// Activity embedding for large screens (tablets, foldables).
|
||||
///
|
||||
/// When set and enabled, Tauri generates the Gradle dependencies, Android manifest entries,
|
||||
/// and a `TauriSplitInitializer` Kotlin class for split-screen activity layouts.
|
||||
#[serde(alias = "activity-embedding")]
|
||||
pub activity_embedding: Option<ActivityEmbeddingConfig>,
|
||||
}
|
||||
|
||||
impl Default for AndroidConfig {
|
||||
@@ -3213,6 +3390,7 @@ impl Default for AndroidConfig {
|
||||
min_sdk_version: default_min_sdk_version(),
|
||||
version_code: None,
|
||||
auto_increment_version_code: false,
|
||||
activity_embedding: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,19 @@
|
||||
"nsis": {
|
||||
"compression": "none"
|
||||
}
|
||||
},
|
||||
"android": {
|
||||
"activityEmbedding": {
|
||||
"enabled": true,
|
||||
"splitRules": [
|
||||
{
|
||||
"primary": "MainActivity",
|
||||
"secondary": "DetailActivity",
|
||||
"splitType": { "ratio": 0.33 },
|
||||
"minWidthDp": 840
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user