feat: add dmg settings, cherry picked from #7964 (#8334)

* feat(bundler): add dmg settings, closes #4669 (#7964)

* fix(bundler): lint and cleanup for #7964 (#8275)

* fmt

---------

Co-authored-by: Andrew <andrey255@live.com>
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
This commit is contained in:
Harry Mallon
2024-06-17 12:25:12 +01:00
committed by GitHub
parent d2786bf699
commit 924387092e
10 changed files with 531 additions and 33 deletions

View File

@@ -0,0 +1,6 @@
---
tauri-bundler: minor:feat
tauri-cli: minor:feat
---
Added support for DMG settings to `bundler > dmg`. Includes window size, background image and icon positions.

View File

@@ -139,6 +139,20 @@
"deb": {
"files": {}
},
"dmg": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"icon": [],
"identifier": "",
"macOS": {
@@ -285,6 +299,20 @@
"deb": {
"files": {}
},
"dmg": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"icon": [],
"identifier": "",
"macOS": {
@@ -1166,6 +1194,28 @@
}
]
},
"dmg": {
"description": "DMG-specific settings.",
"default": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"allOf": [
{
"$ref": "#/definitions/DmgConfig"
}
]
},
"macOS": {
"description": "Configuration for the macOS bundles.",
"default": {
@@ -1495,6 +1545,113 @@
},
"additionalProperties": false
},
"DmgConfig": {
"description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig",
"type": "object",
"properties": {
"background": {
"description": "Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.",
"type": [
"string",
"null"
]
},
"windowPosition": {
"description": "Position of volume window on screen.",
"anyOf": [
{
"$ref": "#/definitions/Position"
},
{
"type": "null"
}
]
},
"windowSize": {
"description": "Size of volume window.",
"default": {
"height": 400,
"width": 660
},
"allOf": [
{
"$ref": "#/definitions/Size"
}
]
},
"appPosition": {
"description": "Position of app file on window.",
"default": {
"x": 180,
"y": 170
},
"allOf": [
{
"$ref": "#/definitions/Position"
}
]
},
"applicationFolderPosition": {
"description": "Position of application folder on window.",
"default": {
"x": 480,
"y": 170
},
"allOf": [
{
"$ref": "#/definitions/Position"
}
]
}
},
"additionalProperties": false
},
"Position": {
"description": "Position coordinates struct.",
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"description": "X coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"y": {
"description": "Y coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"Size": {
"description": "Size of the window.",
"type": "object",
"required": [
"height",
"width"
],
"properties": {
"width": {
"description": "Width of the window.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"height": {
"description": "Height of the window.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"MacConfig": {
"description": "Configuration for the macOS bundles.\n\nSee more: https://tauri.app/v1/api/config#macconfig",
"type": "object",

View File

@@ -348,6 +348,81 @@ fn default_release() -> String {
"1".into()
}
/// Position coordinates struct.
#[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Position {
/// X coordinate.
pub x: u32,
/// Y coordinate.
pub y: u32,
}
/// Size of the window.
#[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Size {
/// Width of the window.
pub width: u32,
/// Height of the window.
pub height: u32,
}
/// Configuration for Apple Disk Image (.dmg) bundles.
///
/// See more: https://tauri.app/v1/api/config#dmgconfig
#[skip_serializing_none]
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct DmgConfig {
/// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
pub background: Option<PathBuf>,
/// Position of volume window on screen.
pub window_position: Option<Position>,
/// Size of volume window.
#[serde(default = "dmg_window_size", alias = "window-size")]
pub window_size: Size,
/// Position of app file on window.
#[serde(default = "dmg_app_position", alias = "app-position")]
pub app_position: Position,
/// Position of application folder on window.
#[serde(
default = "dmg_application_folder_position",
alias = "application-folder-position"
)]
pub application_folder_position: Position,
}
impl Default for DmgConfig {
fn default() -> Self {
Self {
background: None,
window_position: None,
window_size: dmg_window_size(),
app_position: dmg_app_position(),
application_folder_position: dmg_application_folder_position(),
}
}
}
fn dmg_window_size() -> Size {
Size {
width: 660,
height: 400,
}
}
fn dmg_app_position() -> Position {
Position { x: 180, y: 170 }
}
fn dmg_application_folder_position() -> Position {
Position { x: 480, y: 170 }
}
fn de_minimum_system_version<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
@@ -810,6 +885,9 @@ pub struct BundleConfig {
/// Configuration for the RPM bundle.
#[serde(default)]
pub rpm: RpmConfig,
/// DMG-specific settings.
#[serde(default)]
pub dmg: DmgConfig,
/// Configuration for the macOS bundles.
#[serde(rename = "macOS", default)]
pub macos: MacConfig,
@@ -3639,6 +3717,7 @@ mod build {
let appimage = quote!(Default::default());
let deb = quote!(Default::default());
let rpm = quote!(Default::default());
let dmg = quote!(Default::default());
let macos = quote!(Default::default());
let external_bin = opt_vec_str_lit(self.external_bin.as_ref());
let windows = &self.windows;
@@ -3660,6 +3739,7 @@ mod build {
appimage,
deb,
rpm,
dmg,
macos,
external_bin,
windows
@@ -4104,6 +4184,7 @@ mod test {
appimage: Default::default(),
deb: Default::default(),
rpm: Default::default(),
dmg: Default::default(),
macos: Default::default(),
external_bin: None,
windows: Default::default(),

View File

@@ -20,8 +20,8 @@ use tauri_utils::display_path;
pub use self::{
category::AppCategory,
settings::{
BundleBinary, BundleSettings, DebianSettings, MacOsSettings, PackageSettings, PackageType,
RpmSettings, Settings, SettingsBuilder, UpdaterSettings,
BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings, PackageSettings,
PackageType, Position, RpmSettings, Settings, SettingsBuilder, Size, UpdaterSettings,
},
};
#[cfg(target_os = "macos")]

View File

@@ -96,55 +96,90 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
.output()
.expect("Failed to chmod script");
let mut args = vec![
let dmg_settings = settings.dmg();
let app_position = &dmg_settings.app_position;
let application_folder_position = &dmg_settings.application_folder_position;
let window_size = &dmg_settings.window_size;
let app_position_x = app_position.x.to_string();
let app_position_y = app_position.y.to_string();
let application_folder_position_x = application_folder_position.x.to_string();
let application_folder_position_y = application_folder_position.y.to_string();
let window_size_width = window_size.width.to_string();
let window_size_height = window_size.height.to_string();
let mut bundle_dmg_cmd = Command::new(&bundle_script_path);
bundle_dmg_cmd.args([
"--volname",
product_name,
"--icon",
&bundle_file_name,
"180",
"170",
&app_position_x,
&app_position_y,
"--app-drop-link",
"480",
"170",
&application_folder_position_x,
&application_folder_position_y,
"--window-size",
"660",
"400",
&window_size_width,
&window_size_height,
"--hide-extension",
&bundle_file_name,
];
]);
let icns_icon_path =
create_icns_file(&output_path, settings)?.map(|path| path.to_string_lossy().to_string());
if let Some(icon) = &icns_icon_path {
args.push("--volicon");
args.push(icon);
let window_position = dmg_settings
.window_position
.as_ref()
.map(|position| (position.x.to_string(), position.y.to_string()));
if let Some(window_position) = &window_position {
bundle_dmg_cmd.arg("--window-pos");
bundle_dmg_cmd.arg(&window_position.0);
bundle_dmg_cmd.arg(&window_position.1);
}
#[allow(unused_assignments)]
let mut license_path_ref = "".to_string();
if let Some(license_path) = &settings.macos().license {
args.push("--eula");
license_path_ref = env::current_dir()?
.join(license_path)
.to_string_lossy()
.to_string();
args.push(&license_path_ref);
let background_path = if let Some(background_path) = &dmg_settings.background {
Some(env::current_dir()?.join(background_path))
} else {
None
};
if let Some(background_path) = &background_path {
bundle_dmg_cmd.arg("--background");
bundle_dmg_cmd.arg(background_path);
}
let icns_icon_path = create_icns_file(&output_path, settings)?;
if let Some(icon) = &icns_icon_path {
bundle_dmg_cmd.arg("--volicon");
bundle_dmg_cmd.arg(icon);
}
let license_path = if let Some(license_path) = &settings.macos().license {
Some(env::current_dir()?.join(license_path))
} else {
None
};
if let Some(license_path) = &license_path {
bundle_dmg_cmd.arg("--eula");
bundle_dmg_cmd.arg(license_path);
}
// Issue #592 - Building MacOS dmg files on CI
// https://github.com/tauri-apps/tauri/issues/592
if let Some(value) = env::var_os("CI") {
if value == "true" {
args.push("--skip-jenkins");
bundle_dmg_cmd.arg("--skip-jenkins");
}
}
info!(action = "Running"; "bundle_dmg.sh");
// execute the bundle script
Command::new(&bundle_script_path)
bundle_dmg_cmd
.current_dir(bundle_dir.clone())
.args(args)
.args(vec![dmg_name.as_str(), bundle_file_name.as_str()])
.output_ok()
.context("error running bundle_dmg.sh")?;

View File

@@ -237,6 +237,39 @@ pub struct RpmSettings {
pub desktop_template: Option<PathBuf>,
}
/// Position coordinates struct.
#[derive(Clone, Debug, Default)]
pub struct Position {
/// X coordinate.
pub x: u32,
/// Y coordinate.
pub y: u32,
}
/// Size of the window.
#[derive(Clone, Debug, Default)]
pub struct Size {
/// Width of the window.
pub width: u32,
/// Height of the window.
pub height: u32,
}
/// The DMG bundle settings.
#[derive(Clone, Debug, Default)]
pub struct DmgSettings {
/// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
pub background: Option<PathBuf>,
/// Position of volume window on screen.
pub window_position: Option<Position>,
/// Size of volume window.
pub window_size: Size,
/// Position of app file on window.
pub app_position: Position,
/// Position of application folder on window.
pub application_folder_position: Position,
}
/// The macOS bundle settings.
#[derive(Clone, Debug, Default)]
pub struct MacOsSettings {
@@ -485,6 +518,8 @@ pub struct BundleSettings {
pub deb: DebianSettings,
/// Rpm-specific settings.
pub rpm: RpmSettings,
/// DMG-specific settings.
pub dmg: DmgSettings,
/// MacOS-specific settings.
pub macos: MacOsSettings,
/// Updater configuration.
@@ -949,6 +984,11 @@ impl Settings {
&self.bundle_settings.rpm
}
/// Returns the DMG settings.
pub fn dmg(&self) -> &DmgSettings {
&self.bundle_settings.dmg
}
/// Returns the MacOS settings.
pub fn macos(&self) -> &MacOsSettings {
&self.bundle_settings.macos

View File

@@ -67,6 +67,9 @@ pub enum Error {
/// Couldn't find icons.
#[error("Could not find Icon paths. Please make sure they exist in the tauri config JSON file")]
IconPathError,
/// Couldn't find background file.
#[error("Could not find background file. Make sure it exists in the tauri config JSON file and extension is png/jpg/gif")]
BackgroundPathError,
/// Error on path util operation.
#[error("Path Error:`{0}`")]
PathUtilError(String),

View File

@@ -4863,9 +4863,9 @@ dependencies = [
[[package]]
name = "windows-registry"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f721bc2e55efb506a1a395a545cb76c2481fb023d33b51f0050e7888716281cf"
checksum = "acc134c90a0318d873ec962b13149e9c862ff0d2669082a709a4810167a3c6ee"
dependencies = [
"windows-result",
"windows-targets 0.52.5",
@@ -4873,9 +4873,9 @@ dependencies = [
[[package]]
name = "windows-result"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.5",
]

View File

@@ -139,6 +139,20 @@
"deb": {
"files": {}
},
"dmg": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"icon": [],
"identifier": "",
"macOS": {
@@ -285,6 +299,20 @@
"deb": {
"files": {}
},
"dmg": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"icon": [],
"identifier": "",
"macOS": {
@@ -1166,6 +1194,28 @@
}
]
},
"dmg": {
"description": "DMG-specific settings.",
"default": {
"appPosition": {
"x": 180,
"y": 170
},
"applicationFolderPosition": {
"x": 480,
"y": 170
},
"windowSize": {
"height": 400,
"width": 660
}
},
"allOf": [
{
"$ref": "#/definitions/DmgConfig"
}
]
},
"macOS": {
"description": "Configuration for the macOS bundles.",
"default": {
@@ -1495,6 +1545,113 @@
},
"additionalProperties": false
},
"DmgConfig": {
"description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig",
"type": "object",
"properties": {
"background": {
"description": "Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.",
"type": [
"string",
"null"
]
},
"windowPosition": {
"description": "Position of volume window on screen.",
"anyOf": [
{
"$ref": "#/definitions/Position"
},
{
"type": "null"
}
]
},
"windowSize": {
"description": "Size of volume window.",
"default": {
"height": 400,
"width": 660
},
"allOf": [
{
"$ref": "#/definitions/Size"
}
]
},
"appPosition": {
"description": "Position of app file on window.",
"default": {
"x": 180,
"y": 170
},
"allOf": [
{
"$ref": "#/definitions/Position"
}
]
},
"applicationFolderPosition": {
"description": "Position of application folder on window.",
"default": {
"x": 480,
"y": 170
},
"allOf": [
{
"$ref": "#/definitions/Position"
}
]
}
},
"additionalProperties": false
},
"Position": {
"description": "Position coordinates struct.",
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"description": "X coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"y": {
"description": "Y coordinate.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"Size": {
"description": "Size of the window.",
"type": "object",
"required": [
"height",
"width"
],
"properties": {
"width": {
"description": "Width of the window.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"height": {
"description": "Height of the window.",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"MacConfig": {
"description": "Configuration for the macOS bundles.\n\nSee more: https://tauri.app/v1/api/config#macconfig",
"type": "object",

View File

@@ -28,8 +28,8 @@ use notify_debouncer_mini::new_debouncer;
use serde::Deserialize;
use shared_child::SharedChild;
use tauri_bundler::{
AppCategory, BundleBinary, BundleSettings, DebianSettings, MacOsSettings, PackageSettings,
RpmSettings, UpdaterSettings, WindowsSettings,
AppCategory, BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings,
PackageSettings, Position, RpmSettings, Size, UpdaterSettings, WindowsSettings,
};
use tauri_utils::config::parse::is_configuration_file;
@@ -1180,6 +1180,25 @@ fn tauri_config_to_bundle_settings(
files: config.rpm.files,
desktop_template: config.rpm.desktop_template,
},
dmg: DmgSettings {
background: config.dmg.background,
window_position: config.dmg.window_position.map(|window_position| Position {
x: window_position.x,
y: window_position.y,
}),
window_size: Size {
width: config.dmg.window_size.width,
height: config.dmg.window_size.height,
},
app_position: Position {
x: config.dmg.app_position.x,
y: config.dmg.app_position.y,
},
application_folder_position: Position {
x: config.dmg.application_folder_position.x,
y: config.dmg.application_folder_position.y,
},
},
macos: MacOsSettings {
frameworks: config.macos.frameworks,
minimum_system_version: config.macos.minimum_system_version,