diff --git a/docs/en/makers/appimage.md b/docs/en/makers/appimage.md index 3750881d..21bb34c2 100644 --- a/docs/en/makers/appimage.md +++ b/docs/en/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/docs/en/makers/rpm.md b/docs/en/makers/rpm.md index d6acee17..69ad2bbf 100644 --- a/docs/en/makers/rpm.md +++ b/docs/en/makers/rpm.md @@ -16,6 +16,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/docs/zh/makers/appimage.md b/docs/zh/makers/appimage.md index 807c1077..6732b586 100644 --- a/docs/zh/makers/appimage.md +++ b/docs/zh/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/docs/zh/makers/rpm.md b/docs/zh/makers/rpm.md index 71dd42e9..d2e11907 100644 --- a/docs/zh/makers/rpm.md +++ b/docs/zh/makers/rpm.md @@ -16,6 +16,7 @@ 将 `make_config.yaml` 添加到您的项目 `linux/packaging/rpm` 目录。 ```yaml +package_name: hello-world icon: assets/logo.png summary: A really cool application group: Application/Emulator 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..5e09b069 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,33 @@ 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', - ); - - await $('mkdir', [ - '-p', - icon128x128, - icon256x256, - ]).then((value) { - if (value.exitCode != 0) { - throw MakeError(value.stderr as String); - } - }); + 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 iconFile.copy( - path.join( - icon128x128, - '${makeConfig.appName}${path.extension(makeConfig.icon)}', - ), - ); + if (mkdirProcessRes.exitCode != 0) throw MakeError(); - await iconFile.copy( - path.join( - icon256x256, - '${makeConfig.appName}${path.extension(makeConfig.icon)}', - ), - ); + final iconBytes = await iconFile.readAsBytes(); + final decodedIcon = img.decodeImage(iconBytes); + if (decodedIcon == null) { + throw MakeError('Failed to decode icon: ${makeConfig.icon}'); + } + final icon = img.copyResize( + decodedIcon, + width: size, + height: size, + interpolation: img.Interpolation.average, + ); + final newIconFile = + File(path.join(iconDir, '${makeConfig.appName}.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 1f254786..69c800ec 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 @@ -22,16 +22,13 @@ class AppImageAction { List arguments; Map toJson() { - return { - 'label': label, - 'name': name, - 'arguments': arguments, - }; + return {'label': label, 'name': name, 'arguments': arguments}; } } class MakeAppImageConfig extends MakeConfig { MakeAppImageConfig({ + this.packageName, required this.displayName, required this.icon, this.keywords = const [], @@ -39,12 +36,14 @@ class MakeAppImageConfig extends MakeConfig { this.actions = const [], this.include = const [], this.startupNotify = true, + this.startupWMClass, this.genericName = 'A Flutter Application', this.supportedMimeType, this.metainfo, }); 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?, @@ -52,6 +51,7 @@ class MakeAppImageConfig extends MakeConfig { keywords: (map['keywords'] as List? ?? []).cast(), categories: (map['categories'] as List? ?? []).cast(), startupNotify: map['startup_notify'] as bool? ?? false, + startupWMClass: map['startup_wm_class'] as String?, genericName: map['generic_name'] as String? ?? 'A Flutter Application', actions: (map['actions'] as List? ?? []) .map( @@ -66,13 +66,18 @@ class MakeAppImageConfig extends MakeConfig { ); } + @override + String get appName => packageName ?? super.appName; + final String icon; final String? metainfo; final List keywords; final List categories; final List actions; final bool startupNotify; + final String? startupWMClass; final String genericName; + final String? packageName; final String displayName; final List include; List? supportedMimeType; @@ -85,6 +90,7 @@ class MakeAppImageConfig extends MakeConfig { 'Icon': appName, 'Type': 'Application', 'StartupNotify': startupNotify ? 'true' : 'false', + if (startupWMClass != null) 'StartupWMClass': startupWMClass, if (supportedMimeType != null && supportedMimeType!.isNotEmpty) 'MimeType': '${supportedMimeType!.join(';')};', if (categories.isNotEmpty) 'Categories': categories.join(';'), @@ -93,14 +99,16 @@ class MakeAppImageConfig extends MakeConfig { 'Actions': this.actions.map((e) => e.label).join(';'), }.entries.map((e) => '${e.key}=${e.value}').join('\n'); - final actions = this.actions.map((action) { - final fields = { - 'Name': action.name, - 'Exec': - 'LD_LIBRARY_PATH=usr/lib $appName ${action.arguments.join(' ')} %u', - }; - return '[Desktop Action ${action.label}]\n${fields.entries.map((e) => '${e.key}=${e.value}').join('\n')}'; - }).join('\n\n'); + final actions = this.actions + .map((action) { + final fields = { + 'Name': action.name, + 'Exec': + 'LD_LIBRARY_PATH=usr/lib $appName ${action.arguments.join(' ')} %u', + }; + return '[Desktop Action ${action.label}]\n${fields.entries.map((e) => '${e.key}=${e.value}').join('\n')}'; + }) + .join('\n\n'); return '[Desktop Entry]\n$fields\n\n$actions'; } 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..7fe67142 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,33 @@ 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 iconBytes = await iconFile.readAsBytes(); + final decodedIcon = img.decodeImage(iconBytes); + if (decodedIcon == null) { + throw MakeError('Failed to decode icon: ${makeConfig.icon}'); + } + final icon = img.copyResize( + decodedIcon, + 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 782e261b..f1bb20b1 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 -+. @@ -127,6 +128,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { required this.maintainer, this.startupNotify = true, this.startupWMClass, + this.includeBuildNumber = true, this.essential = false, List? postinstallScripts, List? postuninstallScripts, @@ -156,6 +158,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: @@ -226,6 +229,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { ); } + bool includeBuildNumber; String displayName; String packageName; String maintainer; @@ -274,7 +278,7 @@ class MakeDebConfig extends MakeLinuxPackageConfig { 'CONTROL': { 'Maintainer': maintainer, 'Package': packageName, - 'Version': appVersion.toString(), + 'Version': includeBuildNumber ? appVersion.toString() : appBuildName, 'Section': section, 'Priority': priority, 'Architecture': _getArchitecture(), @@ -298,7 +302,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 ddcde617..e30f67ad 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, @@ -34,6 +35,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'], @@ -48,6 +50,10 @@ class MakeExeConfig extends MakeConfig { return makeExeConfig; } + @override + String get appName => packageName ?? super.appName; + + String? packageName; String? scriptTemplate; final String appId; String? executableName; @@ -83,6 +89,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..f9c28b8b 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,33 @@ 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 iconBytes = await iconFile.readAsBytes(); + final decodedIcon = img.decodeImage(iconBytes); + if (decodedIcon == null) { + throw MakeError('Failed to decode icon: ${makeConfig.icon}'); + } + final icon = img.copyResize( + decodedIcon, + 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..3102d5fd 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 @@ -111,6 +111,7 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { this.optDependencies, this.options, this.startupNotify = false, + this.startupWMClass, this.groups = const ['default'], this.licenses = const ['unknown'], this.icon, @@ -120,14 +121,14 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { this.conflicts, this.replaces, this.supportedMimeType, - }) : _postinstallScripts = postinstallScripts ?? [], - _postupgradeScripts = postupgradeScripts ?? [], - _postremoveScripts = postuninstallScripts ?? []; + }) : _postinstallScripts = postinstallScripts ?? [], + _postupgradeScripts = postupgradeScripts ?? [], + _postremoveScripts = postuninstallScripts ?? []; 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']}>", @@ -177,6 +178,7 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { ? List.castFrom(map['categories']) : null, startupNotify: map['startup_notify'], + startupWMClass: map['startup_wm_class'] as String?, genericName: map['generic_name'], installedSize: map['installed_size'], icon: map['icon'], @@ -195,6 +197,7 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { String? metainfo; String? genericName; bool startupNotify; + String? startupWMClass; List? options; List? dependencies; List? optDependencies; @@ -210,15 +213,15 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { List? categories; List get postinstallScripts => [ - 'ln -s /usr/share/$appBinaryName/$appBinaryName /usr/bin/$appBinaryName', - 'chmod +x /usr/bin/$appBinaryName', - ..._postinstallScripts, - ]; + 'ln -s /usr/share/$appBinaryName/$appBinaryName /usr/bin/$appBinaryName', + 'chmod +x /usr/bin/$appBinaryName', + ..._postinstallScripts, + ]; List get postuninstallScripts => [ - 'rm /usr/bin/$appBinaryName', - ..._postremoveScripts, - ]; + 'rm /usr/bin/$appBinaryName', + ..._postremoveScripts, + ]; List get postupgradeScripts => _postupgradeScripts; @@ -236,17 +239,18 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { 'arch': '(${_getArchitecture()})', 'url': pubspec.homepage, 'options': options != null ? "(${options!.join(', ')})" : null, - 'depends': - dependencies != null ? "(${dependencies!.join(', ')})" : null, - 'optdepends': - optDependencies != null ? "(${optDependencies!.join(', ')})" : null, + 'depends': dependencies != null + ? "(${dependencies!.join(', ')})" + : null, + 'optdepends': optDependencies != null + ? "(${optDependencies!.join(', ')})" + : null, 'conflicts': conflicts != null ? "(${conflicts!.join(', ')})" : null, 'replaces': replaces != null ? "(${replaces!.join(', ')})" : null, 'provides': provides != null ? "(${provides!.join(', ')})" : null, }..removeWhere((key, value) => value == null), 'DESKTOP': { 'Type': 'Application', - 'Version': appVersion.toString(), 'Name': displayName, 'GenericName': genericName, 'Icon': appBinaryName, @@ -264,6 +268,7 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { ? '${keywords!.join(';')};' : null, 'StartupNotify': startupNotify, + 'StartupWMClass': startupWMClass, }..removeWhere((key, value) => value == null), }; } @@ -271,27 +276,24 @@ class MakePacmanConfig extends MakeLinuxPackageConfig { Map toFilesString() { final json = toJson(); final pkginfoFile = - '${(json['PKGINFO'] as Map).entries.map( - (e) => '${e.key}=${e.value}', - ).join('\n')}\n'; + '${(json['PKGINFO'] as Map).entries.map((e) => '${e.key}=${e.value}').join('\n')}\n'; final installFileMap = { 'post_install': postinstallScripts.join('\n\t'), - 'post_upgrade': - postupgradeScripts.isNotEmpty ? postupgradeScripts.join('\n') : null, + 'post_upgrade': postupgradeScripts.isNotEmpty + ? postupgradeScripts.join('\n') + : null, 'post_remove': postuninstallScripts.join('\n'), }..removeWhere((key, value) => value == null); final installFile = installFileMap.entries - .map( - (e) => '${e.key}() {\n\t${e.value}\n}', - ) + .map((e) => '${e.key}() {\n\t${e.value}\n}') .join('\n'); final desktopFile = [ '[Desktop Entry]', ...(json['DESKTOP'] as Map).entries.map( - (e) => '${e.key}=${e.value}', - ), + (e) => '${e.key}=${e.value}', + ), ].join('\n'); final map = { 'PKGINFO': pkginfoFile, 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..8b583bd4 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,12 @@ 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.startupWMClass, + this.includeBuildNumber = true, this.actions, this.categories, this.genericName, @@ -39,14 +42,17 @@ 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?, + startupWMClass: json['startup_wm_class'] as String?, keywords: (json['keywords'] as List?)?.cast(), - supportedMimeType: - (json['supported_mime_type'] as List?)?.cast(), + supportedMimeType: (json['supported_mime_type'] as List?) + ?.cast(), actions: (json['actions'] as List?)?.cast(), categories: (json['categories'] as List?)?.cast(), summary: json['summary'] as String?, @@ -71,11 +77,15 @@ class MakeRPMConfig extends MakeConfig { ); } + String? packageName; + + bool includeBuildNumber; String displayName; String? icon; String? metainfo; String? genericName; bool? startupNotify; + String? startupWMClass; List? keywords; List? supportedMimeType; List? actions; @@ -103,20 +113,24 @@ 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, 'Group': group, 'Vendor': vendor, - 'Packager': - packagerEmail != null ? '$packager <$packagerEmail>' : packager, + 'Packager': packagerEmail != null + ? '$packager <$packagerEmail>' + : packager, 'License': license, 'URL': url, 'Requires': requires?.join(', '), @@ -138,8 +152,9 @@ class MakeRPMConfig extends MakeConfig { 'cp -r %{name}*.xml %{buildroot}%{_datadir}/metainfo || :', 'update-mime-database %{_datadir}/mime &> /dev/null || :', ].join('\n'), - '%postun': ['update-mime-database %{_datadir}/mime &> /dev/null || :'] - .join('\n'), + '%postun': [ + 'update-mime-database %{_datadir}/mime &> /dev/null || :', + ].join('\n'), '%files': [ '%{_bindir}/%{name}', '%{_datadir}/%{name}', @@ -154,7 +169,6 @@ class MakeRPMConfig extends MakeConfig { }, 'DESKTOP': { 'Type': 'Application', - 'Version': appVersion.toString(), 'Name': displayName, 'GenericName': genericName, 'Icon': appName, @@ -172,6 +186,7 @@ class MakeRPMConfig extends MakeConfig { ? '${keywords!.join(';')};' : null, 'StartupNotify': startupNotify, + 'StartupWMClass': startupWMClass, }..removeWhere((key, value) => value == null), }; } @@ -179,26 +194,25 @@ class MakeRPMConfig extends MakeConfig { Map toFilesString() { final json = toJson(); - final preamble = (json['SPEC']['preamble'] as Map) - .entries + final preamble = (json['SPEC']['preamble'] as Map).entries .map((e) => '${e.key}: ${e.value}') .join('\n'); - final body = (json['SPEC']['body'] as Map).entries.map( - (e) { - return '${e.key}\n${e.value}\n'; - }, - ).join('\n'); - final inlineBody = (json['SPEC']['inline-body'] as Map).entries.map( - (e) { - return '${e.key}${e.value}\n'; - }, - ).join('\n'); + final body = (json['SPEC']['body'] as Map).entries + .map((e) { + return '${e.key}\n${e.value}\n'; + }) + .join('\n'); + final inlineBody = (json['SPEC']['inline-body'] as Map).entries + .map((e) { + return '${e.key}${e.value}\n'; + }) + .join('\n'); final desktopFile = [ '[Desktop Entry]', ...(json['DESKTOP'] as Map).entries.map( - (e) => '${e.key}=${e.value}', - ), + (e) => '${e.key}=${e.value}', + ), ].join('\n'); final map = { 'DESKTOP': desktopFile, diff --git a/packages/flutter_app_packager/pubspec.yaml b/packages/flutter_app_packager/pubspec.yaml index 691ac9a0..739164b0 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