import 'dart:io'; import '../utils/command_runner.dart'; /// HiTi Mac 驱动(CUPS 过滤器)内置安装:App 资源携带驱动 dmg, /// 向导一键挂载静默安装(osascript 提权一次),已装判断 = /Library/Printers/HiTi 存在。 /// Windows 不适用(PavoApi 直打,官方驱动可选)。 class DriverInstall { static const installedMarker = '/Library/Printers/HiTi'; static bool get isSupported => Platform.isMacOS; /// 驱动是否已安装。 static bool isInstalled() => Directory(installedMarker).existsSync(); /// 内置驱动 dmg 的文件系统路径;未打包携带(如开发运行/产物缺失)返回 null。 /// /// Flutter assets 在 .app 内的真实路径: /// [app]/Contents/Frameworks/App.framework/Resources/flutter_assets/[asset] /// 从可执行文件位置反推(exe 在 [app]/Contents/MacOS/)。 static String? bundledDmgPath() { if (!Platform.isMacOS) return null; final exe = Platform.resolvedExecutable; final exeDir = File(exe).parent.path; // .../Contents/MacOS final driversDir = '$exeDir/../Frameworks/App.framework/Resources/flutter_assets/assets/drivers'; final dir = Directory(driversDir); if (!dir.existsSync()) return null; final dmgs = dir .listSync() .whereType() .where((f) => f.path.toLowerCase().endsWith('.dmg')) .toList(); return dmgs.isEmpty ? null : dmgs.first.path; } /// 从内置 dmg 静默安装驱动(挂载 → 找 pkg → osascript 提权 installer → 卸载卷)。 /// 提权弹窗由系统显示(一次管理员密码),超时 3 分钟。 static Future installFromDmg(String dmgPath, {void Function(String line)? onLog}) async { final log = onLog ?? (_) {}; // 1. 只读挂载(挂载点带随机序号,必须从输出解析,不能拼名字) final attachOut = await runCommand('hdiutil', ['attach', '-nobrowse', '-readonly', dmgPath], timeoutMs: 30000); final match = RegExp(r'/Volumes/[^\t\n]+').allMatches(attachOut); if (match.isEmpty) { throw StateError('驱动 dmg 挂载失败'); } final mountPoint = match.last.group(0)!; log('驱动卷已挂载:$mountPoint'); try { // 2. 找 pkg final pkg = Directory(mountPoint) .listSync() .whereType() .where((f) => f.path.toLowerCase().endsWith('.pkg')) .toList(); if (pkg.isEmpty) { throw StateError('驱动 dmg 内未找到 .pkg 安装包'); } final pkgPath = pkg.first.path; // 3. osascript 提权安装(AppleScript 字符串内嵌套引号用 \" 转义) final script = 'do shell script "installer -pkg \\"$pkgPath\\" -target /" ' 'with administrator privileges with prompt "安装 HiTi 打印机驱动"'; log('开始安装驱动(请在系统弹窗中输入管理员密码)…'); await runCommand('osascript', ['-e', script], timeoutMs: 180000); log('驱动安装完成'); } finally { // 4. 卸载卷(失败不影响安装结果) try { await runCommand('hdiutil', ['detach', mountPoint, '-force'], tolerateExit: true); } catch (_) {} } } }