Skip to content

Commit fbf73f3

Browse files
authored
fix(bundler): find icon for AppImage, define .DirIcon, closes #749 (#1594)
1 parent 1b15974 commit fbf73f3

File tree

4 files changed

+72
-24
lines changed

4 files changed

+72
-24
lines changed

.changes/appimage-icon.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-bundler": patch
3+
---
4+
5+
Find best available icon for AppImage, follow `.DirIcon` spec.

tooling/bundler/src/bundle/appimage_bundle.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
4747
let package_dir = settings.project_out_directory().join("bundle/appimage_deb");
4848

4949
// generate deb_folder structure
50-
deb_bundle::generate_data(settings, &package_dir)?;
50+
let (_, icons) = deb_bundle::generate_data(settings, &package_dir)?;
51+
let icons: Vec<deb_bundle::DebIcon> = icons.into_iter().collect();
5152

5253
let output_path = settings.project_out_directory().join("bundle/appimage");
5354
if output_path.exists() {
@@ -71,6 +72,18 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
7172
sh_map.insert("app_name", settings.main_binary_name());
7273
sh_map.insert("app_name_uppercase", &upcase_app_name);
7374
sh_map.insert("appimage_filename", &appimage_filename);
75+
let larger_icon = icons
76+
.iter()
77+
.filter(|i| i.width == i.height)
78+
.max_by_key(|i| i.width)
79+
.expect("couldn't find a square icon to use as AppImage icon");
80+
let larger_icon_path = larger_icon
81+
.path
82+
.strip_prefix(package_dir.join("data"))
83+
.unwrap()
84+
.to_string_lossy()
85+
.to_string();
86+
sh_map.insert("icon_path", &larger_icon_path);
7487

7588
// initialize shell script template.
7689
let temp = HANDLEBARS.render("appimage", &sh_map)?;

tooling/bundler/src/bundle/deb_bundle.rs

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ use std::{
3939
path::{Path, PathBuf},
4040
};
4141

42+
#[derive(PartialEq, Eq, PartialOrd, Ord)]
43+
pub struct DebIcon {
44+
pub width: u32,
45+
pub height: u32,
46+
pub is_high_density: bool,
47+
pub path: PathBuf,
48+
}
49+
4250
/// Bundles the project.
4351
/// Returns a vector of PathBuf that shows where the DEB was created.
4452
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
@@ -63,7 +71,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
6371
}
6472
let package_path = base_dir.join(package_name);
6573

66-
let data_dir = generate_data(settings, &package_dir)
74+
let (data_dir, _) = generate_data(settings, &package_dir)
6775
.with_context(|| "Failed to build data folders and files")?;
6876
// Generate control files.
6977
let control_dir = package_dir.join("control");
@@ -91,7 +99,10 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
9199
}
92100

93101
/// Generate the debian data folders and files.
94-
pub fn generate_data(settings: &Settings, package_dir: &Path) -> crate::Result<PathBuf> {
102+
pub fn generate_data(
103+
settings: &Settings,
104+
package_dir: &Path,
105+
) -> crate::Result<(PathBuf, BTreeSet<DebIcon>)> {
95106
// Generate data files.
96107
let data_dir = package_dir.join("data");
97108
let bin_dir = data_dir.join("usr/bin");
@@ -108,7 +119,8 @@ pub fn generate_data(settings: &Settings, package_dir: &Path) -> crate::Result<P
108119
.copy_binaries(&bin_dir)
109120
.with_context(|| "Failed to copy external binaries")?;
110121

111-
generate_icon_files(settings, &data_dir).with_context(|| "Failed to create icon files")?;
122+
let icons =
123+
generate_icon_files(settings, &data_dir).with_context(|| "Failed to create icon files")?;
112124
generate_desktop_file(settings, &data_dir).with_context(|| "Failed to create desktop file")?;
113125

114126
let use_bootstrapper = settings.deb().use_bootstrapper.unwrap_or_default();
@@ -117,7 +129,7 @@ pub fn generate_data(settings: &Settings, package_dir: &Path) -> crate::Result<P
117129
.with_context(|| "Failed to generate bootstrap file")?;
118130
}
119131

120-
Ok(data_dir)
132+
Ok((data_dir, icons))
121133
}
122134

123135
/// Generates the bootstrap script file.
@@ -307,7 +319,7 @@ fn transfer_resource_files(settings: &Settings, data_dir: &Path) -> crate::Resul
307319
}
308320

309321
/// Generate the icon files and store them under the `data_dir`.
310-
fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
322+
fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result<BTreeSet<DebIcon>> {
311323
let base_dir = data_dir.join("usr/share/icons/hicolor");
312324
let get_dest_path = |width: u32, height: u32, is_high_density: bool| {
313325
base_dir.join(format!(
@@ -318,7 +330,7 @@ fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result<()
318330
settings.main_binary_name()
319331
))
320332
};
321-
let mut sizes = BTreeSet::new();
333+
let mut icons = BTreeSet::new();
322334
// Prefer PNG files.
323335
for icon_path in settings.icon_files() {
324336
let icon_path = icon_path?;
@@ -329,10 +341,16 @@ fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result<()
329341
let width = decoder.dimensions().0;
330342
let height = decoder.dimensions().1;
331343
let is_high_density = common::is_retina(&icon_path);
332-
if !sizes.contains(&(width, height, is_high_density)) {
333-
sizes.insert((width, height, is_high_density));
334-
let dest_path = get_dest_path(width, height, is_high_density);
335-
common::copy_file(&icon_path, &dest_path)?;
344+
let dest_path = get_dest_path(width, height, is_high_density);
345+
let deb_icon = DebIcon {
346+
width,
347+
height,
348+
is_high_density,
349+
path: dest_path,
350+
};
351+
if !icons.contains(&deb_icon) {
352+
common::copy_file(&icon_path, &deb_icon.path)?;
353+
icons.insert(deb_icon);
336354
}
337355
}
338356
// Fall back to non-PNG files for any missing sizes.
@@ -346,28 +364,40 @@ fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result<()
346364
let width = icon_type.screen_width();
347365
let height = icon_type.screen_height();
348366
let is_high_density = icon_type.pixel_density() > 1;
349-
if !sizes.contains(&(width, height, is_high_density)) {
350-
sizes.insert((width, height, is_high_density));
351-
let dest_path = get_dest_path(width, height, is_high_density);
367+
let dest_path = get_dest_path(width, height, is_high_density);
368+
let deb_icon = DebIcon {
369+
width,
370+
height,
371+
is_high_density,
372+
path: dest_path,
373+
};
374+
if !icons.contains(&deb_icon) {
352375
let icon = icon_family.get_icon_with_type(icon_type)?;
353-
icon.write_png(common::create_file(&dest_path)?)?;
376+
icon.write_png(common::create_file(&deb_icon.path)?)?;
377+
icons.insert(deb_icon);
354378
}
355379
}
356380
} else {
357381
let icon = image::open(&icon_path)?;
358382
let (width, height) = icon.dimensions();
359383
let is_high_density = common::is_retina(&icon_path);
360-
if !sizes.contains(&(width, height, is_high_density)) {
361-
sizes.insert((width, height, is_high_density));
362-
let dest_path = get_dest_path(width, height, is_high_density);
384+
let dest_path = get_dest_path(width, height, is_high_density);
385+
let deb_icon = DebIcon {
386+
width,
387+
height,
388+
is_high_density,
389+
path: dest_path,
390+
};
391+
if !icons.contains(&deb_icon) {
363392
icon.write_to(
364-
&mut common::create_file(&dest_path)?,
393+
&mut common::create_file(&deb_icon.path)?,
365394
image::ImageOutputFormat::Png,
366395
)?;
396+
icons.insert(deb_icon);
367397
}
368398
}
369399
}
370-
Ok(())
400+
Ok(icons)
371401
}
372402

373403
/// Create an empty file at the given path, creating any parent directories as

tooling/bundler/src/bundle/templates/appimage

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ cd "{{app_name}}.AppDir"
1515
wget -q -4 -O AppRun https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-x86_64 || wget -q -4 -O AppRun https://github.com/AppImage/AppImageKit/releases/download/12/AppRun-aarch64
1616
chmod +x AppRun
1717

18-
cp "usr/share/icons/hicolor/256x256/apps/{{app_name}}.png" "{{app_name}}.png"
18+
cp "{{icon_path}}" .DirIcon
19+
ln -s "{{icon_path}}" "{{app_name}}.png"
1920

20-
cd ..
21+
ln -s "usr/share/applications/{{app_name}}.desktop" "{{app_name}}.desktop"
2122

22-
cp "../appimage_deb/data/usr/share/applications/{{app_name}}.desktop" "{{app_name}}.AppDir/usr/share/applications/{{app_name}}.desktop"
23-
cp "../appimage_deb/data/usr/share/applications/{{app_name}}.desktop" "{{app_name}}.AppDir/{{app_name}}.desktop"
23+
cd ..
2424

2525
mksquashfs "{{app_name}}.AppDir" "{{app_name}}.squashfs" -root-owned -noappend
2626

0 commit comments

Comments
 (0)