import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/state.dart'; import 'package:fl_clash/widgets/input.dart'; import 'package:flutter/services.dart'; class System { static System? _instance; System._internal(); factory System() { _instance ??= System._internal(); return _instance!; } bool get isDesktop => Platform.isWindows || Platform.isMacOS || Platform.isLinux; Future get version async { final deviceInfo = await DeviceInfoPlugin().deviceInfo; return switch (Platform.operatingSystem) { "macos" => (deviceInfo as MacOsDeviceInfo).majorVersion, "android" => (deviceInfo as AndroidDeviceInfo).version.sdkInt, "windows" => (deviceInfo as WindowsDeviceInfo).majorVersion, String() => 0 }; } Future checkIsAdmin() async { final corePath = appPath.corePath.replaceAll(' ', '\\\\ '); if (Platform.isWindows) { final result = await windows?.checkService(); return result == WindowsHelperServiceStatus.running; } else if (Platform.isMacOS) { final result = await Process.run('stat', ['-f', '%Su:%Sg %Sp', corePath]); final output = result.stdout.trim(); if (output.startsWith('root:admin') && output.contains('rws')) { return true; } return false; } else if (Platform.isLinux) { final result = await Process.run('stat', ['-c', '%U:%G %A', corePath]); final output = result.stdout.trim(); if (output.startsWith('root:') && output.contains('rws')) { return true; } return false; } return true; } Future authorizeCore() async { if (Platform.isAndroid) { return AuthorizeCode.none; } final corePath = appPath.corePath.replaceAll(' ', '\\\\ '); final isAdmin = await checkIsAdmin(); if (isAdmin) { return AuthorizeCode.none; } if (Platform.isWindows) { final result = await windows?.registerService(); if (result == true) { return AuthorizeCode.success; } return AuthorizeCode.error; } if (Platform.isMacOS) { final shell = 'chown root:admin $corePath; chmod +sx $corePath'; final arguments = [ "-e", 'do shell script "$shell" with administrator privileges', ]; final result = await Process.run("osascript", arguments); if (result.exitCode != 0) { return AuthorizeCode.error; } return AuthorizeCode.success; } else if (Platform.isLinux) { final shell = Platform.environment['SHELL'] ?? 'bash'; final password = await globalState.showCommonDialog( child: InputDialog( title: appLocalizations.pleaseInputAdminPassword, value: '', ), ); final arguments = [ "-c", 'echo "$password" | sudo -S chown root:root "$corePath" && echo "$password" | sudo -S chmod +sx "$corePath"' ]; final result = await Process.run(shell, arguments); if (result.exitCode != 0) { return AuthorizeCode.error; } return AuthorizeCode.success; } return AuthorizeCode.error; } back() async { await app?.moveTaskToBack(); await window?.hide(); } exit() async { if (Platform.isAndroid) { await SystemNavigator.pop(); } await window?.close(); } } final system = System();