diff --git a/packages/flutter_app_packager/lib/src/makers/appimage/app_package_maker_appimage.dart b/packages/flutter_app_packager/lib/src/makers/appimage/app_package_maker_appimage.dart index 439d3671..6f94db05 100644 --- a/packages/flutter_app_packager/lib/src/makers/appimage/app_package_maker_appimage.dart +++ b/packages/flutter_app_packager/lib/src/makers/appimage/app_package_maker_appimage.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter_app_packager/src/api/app_package_maker.dart'; import 'package:flutter_app_packager/src/makers/appimage/make_appimage_config.dart'; +import 'package:image/image.dart' as img; import 'package:path/path.dart' as path; import 'package:shell_executor/shell_executor.dart'; @@ -116,38 +117,28 @@ class AppPackageMakerAppImage extends AppPackageMaker { ), ); - final icon256x256 = path.join( - makeConfig.packagingDirectory.path, - '${makeConfig.appName}.AppDir/usr/share/icons/hicolor/256x256/apps', - ); - final icon128x128 = path.join( - makeConfig.packagingDirectory.path, - '${makeConfig.appName}.AppDir/usr/share/icons/hicolor/128x128/apps', - ); + for (final size in [128, 256, 512]) { + final iconDir = path.join( + makeConfig.packagingDirectory.path, + '${makeConfig.appName}.AppDir/usr/share/icons/hicolor/${size}x$size/apps', + ); + final mkdirProcessRes = await $('mkdir', [ + '-p', + iconDir, + ]); - await $('mkdir', [ - '-p', - icon128x128, - icon256x256, - ]).then((value) { - if (value.exitCode != 0) { - throw MakeError(value.stderr as String); - } - }); + if (mkdirProcessRes.exitCode != 0) throw MakeError(); - await iconFile.copy( - path.join( - icon128x128, - '${makeConfig.appName}${path.extension(makeConfig.icon)}', - ), - ); - - await iconFile.copy( - path.join( - icon256x256, - '${makeConfig.appName}${path.extension(makeConfig.icon)}', - ), - ); + final icon = img.copyResize( + img.decodeImage(iconFile.readAsBytesSync())!, + width: size, + height: size, + interpolation: img.Interpolation.average, + ); + final newIconFile = + File(path.join(iconDir, '${makeConfig.appBinaryName}.png')); + await newIconFile.writeAsBytes(img.encodePng(icon)); + } if (makeConfig.metainfo != null) { final metainfoDir = path.join( diff --git a/packages/flutter_app_packager/lib/src/makers/appimage/make_appimage_config.dart b/packages/flutter_app_packager/lib/src/makers/appimage/make_appimage_config.dart index 7e8c22db..77f4ef92 100644 --- a/packages/flutter_app_packager/lib/src/makers/appimage/make_appimage_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/appimage/make_appimage_config.dart @@ -32,6 +32,7 @@ class AppImageAction { class MakeAppImageConfig extends MakeConfig { MakeAppImageConfig({ + this.packageName, required this.displayName, required this.icon, this.keywords = const [], @@ -45,6 +46,7 @@ class MakeAppImageConfig extends MakeConfig { }); factory MakeAppImageConfig.fromJson(Map map) { return MakeAppImageConfig( + packageName: map['package_name'] as String?, displayName: map['display_name'] as String, icon: map['icon'] as String, metainfo: map['metainfo'] as String?, @@ -66,6 +68,9 @@ class MakeAppImageConfig extends MakeConfig { ); } + @override + String get appName => packageName ?? super.appName; + final String icon; final String? metainfo; final List keywords; @@ -73,6 +78,7 @@ class MakeAppImageConfig extends MakeConfig { final List actions; final bool startupNotify; final String genericName; + final String? packageName; final String displayName; final List include; List? supportedMimeType; diff --git a/packages/flutter_app_packager/lib/src/makers/deb/app_package_maker_deb.dart b/packages/flutter_app_packager/lib/src/makers/deb/app_package_maker_deb.dart index b2e80929..0b6379d8 100644 --- a/packages/flutter_app_packager/lib/src/makers/deb/app_package_maker_deb.dart +++ b/packages/flutter_app_packager/lib/src/makers/deb/app_package_maker_deb.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter_app_packager/src/api/app_package_maker.dart'; import 'package:flutter_app_packager/src/makers/deb/make_deb_config.dart'; +import 'package:image/image.dart' as img; import 'package:path/path.dart' as path; import 'package:shell_executor/shell_executor.dart'; @@ -46,18 +47,11 @@ class AppPackageMakerDeb extends AppPackageMaker { /// /usr/share/applications /// /usr/share/icons/hicolor/128x128/apps /// /usr/share/icons/hicolor/256x256/apps + /// /usr/share/icons/hicolor/512x512/apps final debianDir = path.join(packagingDirectory.path, 'DEBIAN'); final applicationsDir = path.join(packagingDirectory.path, 'usr/share/applications'); - final icon128Dir = path.join( - packagingDirectory.path, - 'usr/share/icons/hicolor/128x128/apps', - ); - final icon256Dir = path.join( - packagingDirectory.path, - 'usr/share/icons/hicolor/256x256/apps', - ); final metainfoDir = path.join(packagingDirectory.path, 'usr/share/metainfo'); final mkdirProcessResult = await $('mkdir', [ @@ -66,7 +60,6 @@ class AppPackageMakerDeb extends AppPackageMaker { path.join(packagingDirectory.path, 'usr/share', makeConfig.appBinaryName), applicationsDir, if (makeConfig.metainfo != null) metainfoDir, - if (makeConfig.icon != null) ...[icon128Dir, icon256Dir], ]); if (mkdirProcessResult.exitCode != 0) throw MakeError(); @@ -77,18 +70,28 @@ class AppPackageMakerDeb extends AppPackageMaker { throw MakeError("provided icon ${makeConfig.icon} path wasn't found"); } - await iconFile.copy( - path.join( - icon128Dir, - makeConfig.appBinaryName + path.extension(makeConfig.icon!), - ), - ); - await iconFile.copy( - path.join( - icon256Dir, - makeConfig.appBinaryName + path.extension(makeConfig.icon!), - ), - ); + for (final size in [128, 256, 512]) { + final iconDir = path.join( + packagingDirectory.path, + 'usr/share/icons/hicolor/${size}x$size/apps', + ); + final mkdirProcessRes = await $('mkdir', [ + '-p', + iconDir, + ]); + + if (mkdirProcessRes.exitCode != 0) throw MakeError(); + + final icon = img.copyResize( + img.decodeImage(iconFile.readAsBytesSync())!, + width: size, + height: size, + interpolation: img.Interpolation.average, + ); + final newIconFile = + File(path.join(iconDir, '${makeConfig.appBinaryName}.png')); + await newIconFile.writeAsBytes(img.encodePng(icon)); + } } if (makeConfig.metainfo != null) { final metainfoPath = diff --git a/packages/flutter_app_packager/lib/src/makers/deb/make_deb_config.dart b/packages/flutter_app_packager/lib/src/makers/deb/make_deb_config.dart index 4fdf1ee8..734b8a94 100644 --- a/packages/flutter_app_packager/lib/src/makers/deb/make_deb_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/deb/make_deb_config.dart @@ -7,6 +7,7 @@ import 'package:flutter_app_packager/src/api/app_package_maker.dart'; # the name used to display in the OS. Specifically desktop # entry name display_name: Hola Amigos +include_build_number: true # package name for debian/apt repository # the name should be all lowercase with -+. @@ -126,6 +127,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { required this.installedSize, required this.maintainer, this.startupNotify = true, + this.includeBuildNumber = true, this.essential = false, List? postinstallScripts, List? postuninstallScripts, @@ -155,6 +157,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { factory MakeDebConfig.fromJson(Map map) { return MakeDebConfig( + includeBuildNumber: map['include_build_number'] as bool? ?? true, displayName: map['display_name'], packageName: map['package_name'], maintainer: @@ -224,6 +227,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { ); } + bool includeBuildNumber; String displayName; String packageName; String maintainer; @@ -271,7 +275,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { 'CONTROL': { 'Maintainer': maintainer, 'Package': packageName, - 'Version': appVersion.toString(), + 'Version': includeBuildNumber ? appVersion.toString() : appBuildName, 'Section': section, 'Priority': priority, 'Architecture': _getArchitecture(), @@ -295,7 +299,6 @@ class MakeDebConfig extends MakeLinuxPackageConfig { }..removeWhere((key, value) => value == null), 'DESKTOP': { 'Type': 'Application', - 'Version': appVersion.toString(), 'Name': displayName, 'GenericName': genericName, 'Icon': appBinaryName, diff --git a/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart b/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart index fc9061f3..72f11ca7 100644 --- a/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart @@ -5,6 +5,7 @@ import 'package:path/path.dart' as p; class MakeExeConfig extends MakeConfig { MakeExeConfig({ + this.packageName, this.scriptTemplate, required this.appId, this.executableName, @@ -27,6 +28,7 @@ class MakeExeConfig extends MakeConfig { MakeExeConfig makeExeConfig = MakeExeConfig( scriptTemplate: json['script_template'], appId: json['app_id'] ?? json['appId'], + packageName: json['package_name'], executableName: json['executable_name'], displayName: json['display_name'], publisherName: json['publisher_name'] ?? json['appPublisher'], @@ -41,6 +43,10 @@ class MakeExeConfig extends MakeConfig { return makeExeConfig; } + @override + String get appName => packageName ?? super.appName; + + String? packageName; String? scriptTemplate; final String appId; String? executableName; @@ -76,6 +82,7 @@ class MakeExeConfig extends MakeConfig { 'app_id': appId, 'app_name': appName, 'app_version': appVersion.toString(), + 'package_name': packageName, 'executable_name': executableName, 'display_name': displayName, 'publisher_name': publisherName, diff --git a/packages/flutter_app_packager/lib/src/makers/pacman/app_package_maker_pacman.dart b/packages/flutter_app_packager/lib/src/makers/pacman/app_package_maker_pacman.dart index 400f492d..8879b0ae 100644 --- a/packages/flutter_app_packager/lib/src/makers/pacman/app_package_maker_pacman.dart +++ b/packages/flutter_app_packager/lib/src/makers/pacman/app_package_maker_pacman.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter_app_packager/src/api/app_package_maker.dart'; import 'package:flutter_app_packager/src/makers/pacman/make_pacman_config.dart'; +import 'package:image/image.dart' as img; import 'package:path/path.dart' as path; import 'package:shell_executor/shell_executor.dart'; @@ -48,14 +49,7 @@ class AppPackageMakerPacman extends AppPackageMaker { final applicationsDir = path.join(packagingDirectory.path, 'usr/share/applications'); - final icon128Dir = path.join( - packagingDirectory.path, - 'usr/share/icons/hicolor/128x128/apps', - ); - final icon256Dir = path.join( - packagingDirectory.path, - 'usr/share/icons/hicolor/256x256/apps', - ); + final metainfoDir = path.join(packagingDirectory.path, 'usr/share/metainfo'); final mkdirProcessResult = await $('mkdir', [ @@ -63,7 +57,6 @@ class AppPackageMakerPacman extends AppPackageMaker { path.join(packagingDirectory.path, 'usr/share', makeConfig.appBinaryName), applicationsDir, if (makeConfig.metainfo != null) metainfoDir, - if (makeConfig.icon != null) ...[icon128Dir, icon256Dir], ]); if (mkdirProcessResult.exitCode != 0) throw MakeError(); @@ -74,18 +67,28 @@ class AppPackageMakerPacman extends AppPackageMaker { throw MakeError("provided icon ${makeConfig.icon} path wasn't found"); } - await iconFile.copy( - path.join( - icon128Dir, - makeConfig.appBinaryName + path.extension(makeConfig.icon!), - ), - ); - await iconFile.copy( - path.join( - icon256Dir, - makeConfig.appBinaryName + path.extension(makeConfig.icon!), - ), - ); + for (final size in [128, 256, 512]) { + final iconDir = path.join( + packagingDirectory.path, + 'usr/share/icons/hicolor/${size}x$size/apps', + ); + final mkdirProcessRes = await $('mkdir', [ + '-p', + iconDir, + ]); + + if (mkdirProcessRes.exitCode != 0) throw MakeError(); + + final icon = img.copyResize( + img.decodeImage(iconFile.readAsBytesSync())!, + width: size, + height: size, + interpolation: img.Interpolation.average, + ); + final newIconFile = + File(path.join(iconDir, '${makeConfig.appBinaryName}.png')); + await newIconFile.writeAsBytes(img.encodePng(icon)); + } } if (makeConfig.metainfo != null) { final metainfoPath = diff --git a/packages/flutter_app_packager/lib/src/makers/pacman/make_pacman_config.dart b/packages/flutter_app_packager/lib/src/makers/pacman/make_pacman_config.dart index 28d17f70..2668199e 100644 --- a/packages/flutter_app_packager/lib/src/makers/pacman/make_pacman_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/pacman/make_pacman_config.dart @@ -127,7 +127,7 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { factory MakePacmanConfig.fromJson(Map map) { return MakePacmanConfig( displayName: map['display_name'], - packageName: map['package_name'], // + packageName: map['package_name'], packageRelease: int.tryParse(map['package_release'] ?? '1') ?? 1, maintainer: "${map['maintainer']['name']} <${map['maintainer']['email']}>", @@ -246,7 +246,6 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { }..removeWhere((key, value) => value == null), 'DESKTOP': { 'Type': 'Application', - 'Version': appVersion.toString(), 'Name': displayName, 'GenericName': genericName, 'Icon': appBinaryName, diff --git a/packages/flutter_app_packager/lib/src/makers/rpm/make_rpm_config.dart b/packages/flutter_app_packager/lib/src/makers/rpm/make_rpm_config.dart index 87a8381c..87d35f1e 100644 --- a/packages/flutter_app_packager/lib/src/makers/rpm/make_rpm_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/rpm/make_rpm_config.dart @@ -4,9 +4,11 @@ import 'package:flutter_app_packager/src/api/app_package_maker.dart'; class MakeRPMConfig extends MakeConfig { MakeRPMConfig({ + this.packageName, // Desktop file required this.displayName, this.startupNotify = true, + this.includeBuildNumber = true, this.actions, this.categories, this.genericName, @@ -39,8 +41,10 @@ class MakeRPMConfig extends MakeConfig { factory MakeRPMConfig.fromJson(Map json) { return MakeRPMConfig( + packageName: json['package_name'] as String?, displayName: json['display_name'] as String, icon: json['icon'] as String?, + includeBuildNumber: json['include_build_number'] as bool? ?? true, metainfo: json['metainfo'] as String?, genericName: json['generic_name'] as String?, startupNotify: json['startup_notify'] as bool?, @@ -71,6 +75,9 @@ class MakeRPMConfig extends MakeConfig { ); } + String? packageName; + + bool includeBuildNumber; String displayName; String? icon; String? metainfo; @@ -103,13 +110,16 @@ class MakeRPMConfig extends MakeConfig { String? attr; String? changelog; + @override + String get appName => packageName ?? super.appName; + @override Map toJson() { return { 'SPEC': { 'preamble': { 'Name': appName, - 'Version': appVersion.toString(), + 'Version': includeBuildNumber ? appVersion.toString() : appBuildName, 'Release': "${appVersion.build.isNotEmpty ? appVersion.build.first : "1"}%{?dist}", 'Summary': summary ?? pubspec.description, @@ -154,7 +164,6 @@ class MakeRPMConfig extends MakeConfig { }, 'DESKTOP': { 'Type': 'Application', - 'Version': appVersion.toString(), 'Name': displayName, 'GenericName': genericName, 'Icon': appName, diff --git a/packages/flutter_app_packager/pubspec.yaml b/packages/flutter_app_packager/pubspec.yaml index a60dd4bf..ebf58a86 100644 --- a/packages/flutter_app_packager/pubspec.yaml +++ b/packages/flutter_app_packager/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: archive: ^3.6.1 + image: ^4.2.0 io: ^1.0.3 liquid_engine: ^0.2.2 msix: ^3.16.6 diff --git a/website/src/content/docs/makers/appimage.md b/website/src/content/docs/makers/appimage.md index 2a6c89cf..5922faa8 100644 --- a/website/src/content/docs/makers/appimage.md +++ b/website/src/content/docs/makers/appimage.md @@ -27,6 +27,7 @@ mv appimagetool /usr/local/bin/ Add `make_config.yaml` to your project `linux/packaging/appimage` directory. ```yaml +package_name: hello_world display_name: Hello World icon: assets/logo.png diff --git a/website/src/content/docs/makers/rpm.md b/website/src/content/docs/makers/rpm.md index 9f59d874..0fdbff0a 100644 --- a/website/src/content/docs/makers/rpm.md +++ b/website/src/content/docs/makers/rpm.md @@ -18,6 +18,7 @@ Install requirements: Add `make_config.yaml` to your project `linux/packaging/rpm` directory. ```yaml +package_name: hello-world icon: assets/logo.png summary: A really cool application group: Application/Emulator diff --git a/website/src/content/docs/zh-hans/makers/appimage.md b/website/src/content/docs/zh-hans/makers/appimage.md index b4edb2f8..cc46bbec 100644 --- a/website/src/content/docs/zh-hans/makers/appimage.md +++ b/website/src/content/docs/zh-hans/makers/appimage.md @@ -27,6 +27,7 @@ mv appimagetool /usr/local/bin/ 将 `make_config.yaml` 添加到您的项目 `linux/packaging/appimage` 目录。 ```yaml +package_name: hello_world display_name: Hello World icon: assets/logo.png diff --git a/website/src/content/docs/zh-hans/makers/rpm.md b/website/src/content/docs/zh-hans/makers/rpm.md index fa909c87..d3133aa1 100644 --- a/website/src/content/docs/zh-hans/makers/rpm.md +++ b/website/src/content/docs/zh-hans/makers/rpm.md @@ -18,6 +18,7 @@ title: RPM 将 `make_config.yaml` 添加到您的项目 `linux/packaging/rpm` 目录。 ```yaml +package_name: hello-world icon: assets/logo.png summary: A really cool application group: Application/Emulator