From 93b5ee65bb92c6c4fe647eb333e9d7f52f78c1ba Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 20 Jul 2021 11:02:35 -0400 Subject: [PATCH 01/83] Refactor AppWidget for DDD --- lib/main.dart | 36 ++----------------------------- lib/presentation/app_widget.dart | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 lib/presentation/app_widget.dart diff --git a/lib/main.dart b/lib/main.dart index 2d7755c1..c17f9954 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,14 +6,10 @@ import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; import 'package:nyrna/logger/log_file.dart'; import 'package:nyrna/logger/log_screen.dart'; -import 'package:nyrna/nyrna.dart'; import 'package:nyrna/arguments/argument_parser.dart'; -import 'package:nyrna/screens/apps_screen.dart'; -import 'package:nyrna/screens/loading_screen.dart'; -import 'package:nyrna/settings/screens/settings_screen.dart'; +import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/settings/settings.dart'; import 'package:nyrna/window/active_window.dart'; -import 'package:provider/provider.dart'; import 'application/theme/cubit/theme_cubit.dart'; @@ -33,7 +29,7 @@ Future main(List args) async { create: (context) => ThemeCubit(), ), ], - child: MyApp(), + child: AppWidget(), ), ); } @@ -87,31 +83,3 @@ Future toggleActiveWindow() async { // Not yet possible to run without GUI, so we just exit after toggling. exit(0); } - -/// The entrance to the main Nyrna app. -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => Nyrna()), - ], - child: BlocBuilder( - builder: (context, state) { - return MaterialApp( - title: 'Nyrna', - theme: state.themeData, - routes: { - LoadingScreen.id: (context) => LoadingScreen(), - LogScreen.id: (context) => LogScreen(), - RunningAppsScreen.id: (context) => RunningAppsScreen(), - SettingsScreen.id: (conext) => SettingsScreen(), - }, - home: LoadingScreen(), - debugShowCheckedModeBanner: false, - ); - }, - ), - ); - } -} diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart new file mode 100644 index 00000000..c4a853f2 --- /dev/null +++ b/lib/presentation/app_widget.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/theme/theme.dart'; +import 'package:nyrna/logger/log_screen.dart'; +import 'package:nyrna/screens/apps_screen.dart'; +import 'package:nyrna/screens/loading_screen.dart'; +import 'package:nyrna/settings/screens/settings_screen.dart'; +import 'package:provider/provider.dart'; + +import '../nyrna.dart'; + +class AppWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => Nyrna()), + ], + child: BlocBuilder( + builder: (context, state) { + return MaterialApp( + title: 'Nyrna', + debugShowCheckedModeBanner: false, + theme: state.themeData, + routes: { + LoadingScreen.id: (context) => LoadingScreen(), + LogScreen.id: (context) => LogScreen(), + RunningAppsScreen.id: (context) => RunningAppsScreen(), + SettingsScreen.id: (conext) => SettingsScreen(), + }, + home: LoadingScreen(), + ); + }, + ), + ); + } +} From b9ab9486452c80360861bd6d01e7743e59f31733 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 20 Jul 2021 11:28:05 -0400 Subject: [PATCH 02/83] Refactor argument parser for DDD --- lib/{ => domain}/arguments/argument_parser.dart | 11 ++++------- lib/main.dart | 13 +++++-------- test/arguments/argument_parser_test.dart | 16 ++++++++-------- 3 files changed, 17 insertions(+), 23 deletions(-) rename lib/{ => domain}/arguments/argument_parser.dart (93%) diff --git a/lib/arguments/argument_parser.dart b/lib/domain/arguments/argument_parser.dart similarity index 93% rename from lib/arguments/argument_parser.dart rename to lib/domain/arguments/argument_parser.dart index 8ae84af3..98e59ad0 100644 --- a/lib/arguments/argument_parser.dart +++ b/lib/domain/arguments/argument_parser.dart @@ -10,17 +10,14 @@ import 'package:nyrna/logger/log_file.dart'; /// /// Both options available with `-tl`. class ArgumentParser { - ArgumentParser(this.args); + ArgumentParser(this.args) { + _setFlags(); + } final List args; final _parser = ArgParser(); - Future init() async { - _setFlags(); - await _parse(); - } - void _setFlags() { // Toggle flag means Nyrna should toggle the suspend / resume state of the // active application and then exit. Needed as a workaround since Flutter @@ -41,7 +38,7 @@ class ArgumentParser { late ArgResults _results; - Future _parse() async { + Future parse() async { _parseArgs(); _checkToggleFlag(); await _checkLogFlag(); diff --git a/lib/main.dart b/lib/main.dart index c17f9954..8696b45d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,15 +6,18 @@ import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; import 'package:nyrna/logger/log_file.dart'; import 'package:nyrna/logger/log_screen.dart'; -import 'package:nyrna/arguments/argument_parser.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/settings/settings.dart'; import 'package:nyrna/window/active_window.dart'; import 'application/theme/cubit/theme_cubit.dart'; +import 'domain/arguments/argument_parser.dart'; Future main(List args) async { - await parseArgs(args); + // Parse command-line arguments. + final parser = ArgumentParser(args); + await parser.parse(); + await initSettings(); initLogger(); @@ -34,12 +37,6 @@ Future main(List args) async { ); } -/// Parse command-line arguments. -Future parseArgs(List args) async { - final parser = ArgumentParser(args); - await parser.init(); -} - /// Initialize the singleton Settings instance in settings.dart /// /// Needed early both because it runs syncronously and would block UI, diff --git a/test/arguments/argument_parser_test.dart b/test/arguments/argument_parser_test.dart index 9902dc02..e720f0b9 100644 --- a/test/arguments/argument_parser_test.dart +++ b/test/arguments/argument_parser_test.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nyrna/config.dart'; -import 'package:nyrna/arguments/argument_parser.dart'; +import 'package:nyrna/domain/arguments/argument_parser.dart'; void main() { setUp(() { @@ -10,19 +10,19 @@ void main() { test('With no flags log is false', () async { final parser = ArgumentParser([]); - await parser.init(); + await parser.parse(); expect(Config.log, false); }); test('Config.log is true with -l flag', () async { final parser = ArgumentParser(['-l']); - await parser.init(); + await parser.parse(); expect(Config.log, true); }); test('Config.log is true with --log flag', () async { final parser = ArgumentParser(['--log']); - await parser.init(); + await parser.parse(); expect(Config.log, true); }); @@ -30,7 +30,7 @@ void main() { 'With no flags toggle is false', () async { final parser = ArgumentParser([]); - await parser.init(); + await parser.parse(); expect(Config.toggle, false); }, ); @@ -38,7 +38,7 @@ void main() { '--toggle sets Config.toggle to true', () async { final parser = ArgumentParser(['--toggle']); - await parser.init(); + await parser.parse(); expect(Config.toggle, true); }, ); @@ -47,7 +47,7 @@ void main() { '-t sets Config.toggle to true', () async { final parser = ArgumentParser(['-t']); - await parser.init(); + await parser.parse(); expect(Config.toggle, true); }, ); @@ -56,7 +56,7 @@ void main() { 'With log and toggle flags log and toggle are true', () async { final parser = ArgumentParser(['-tl']); - await parser.init(); + await parser.parse(); expect(Config.toggle, true); expect(Config.log, true); }, From b1db01a9d43d8f4dcb4470656af383aa369ea83a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 20 Jul 2021 11:29:19 -0400 Subject: [PATCH 03/83] On receiving unknown flag, inform then exit. --- lib/domain/arguments/argument_parser.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/domain/arguments/argument_parser.dart b/lib/domain/arguments/argument_parser.dart index 98e59ad0..ef4dfdd4 100644 --- a/lib/domain/arguments/argument_parser.dart +++ b/lib/domain/arguments/argument_parser.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:args/args.dart'; import 'package:nyrna/config.dart'; import 'package:nyrna/logger/log_file.dart'; @@ -50,6 +52,7 @@ class ArgumentParser { _results = _parser.parse(args); } on ArgParserException catch (e) { print('Unknown argument: $e'); + exit(1); } } From 4ef37559535c97082e90ff1de1b06c93de55909d Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 20 Jul 2021 12:36:41 -0400 Subject: [PATCH 04/83] Update appimage artifact name --- .github/workflows/build-linux-appimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-linux-appimage.yml b/.github/workflows/build-linux-appimage.yml index 4d1bbbde..bc4b4b0e 100644 --- a/.github/workflows/build-linux-appimage.yml +++ b/.github/workflows/build-linux-appimage.yml @@ -39,7 +39,7 @@ jobs: args: --recipe packaging/linux/appimage/AppImageBuilder.yml --skip-test - uses: actions/upload-artifact@v2 with: - name: Nyrna-AppImage + name: Nyrna-linux-AppImage path: | *.AppImage *.zsync From 0341b467c4f66b49ccbf91405b4521f5711f0372 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Thu, 22 Jul 2021 13:16:39 -0400 Subject: [PATCH 05/83] Refactor logging for DDD --- lib/domain/arguments/argument_parser.dart | 2 +- lib/{ => infrastructure}/logger/log_file.dart | 0 lib/main.dart | 6 +++--- lib/presentation/app_widget.dart | 4 ++-- lib/presentation/logs/logs.dart | 1 + .../logs/pages/log_page.dart} | 8 ++++---- lib/presentation/logs/pages/pages.dart | 1 + lib/settings/screens/settings_screen.dart | 4 ++-- lib/window/active_window.dart | 2 +- 9 files changed, 15 insertions(+), 13 deletions(-) rename lib/{ => infrastructure}/logger/log_file.dart (100%) create mode 100644 lib/presentation/logs/logs.dart rename lib/{logger/log_screen.dart => presentation/logs/pages/log_page.dart} (94%) create mode 100644 lib/presentation/logs/pages/pages.dart diff --git a/lib/domain/arguments/argument_parser.dart b/lib/domain/arguments/argument_parser.dart index ef4dfdd4..745552e8 100644 --- a/lib/domain/arguments/argument_parser.dart +++ b/lib/domain/arguments/argument_parser.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:args/args.dart'; import 'package:nyrna/config.dart'; -import 'package:nyrna/logger/log_file.dart'; +import 'package:nyrna/infrastructure/logger/log_file.dart'; /// Parse command-line arguments. /// diff --git a/lib/logger/log_file.dart b/lib/infrastructure/logger/log_file.dart similarity index 100% rename from lib/logger/log_file.dart rename to lib/infrastructure/logger/log_file.dart diff --git a/lib/main.dart b/lib/main.dart index 8696b45d..c1044de5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,14 +4,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; -import 'package:nyrna/logger/log_file.dart'; -import 'package:nyrna/logger/log_screen.dart'; +import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/settings/settings.dart'; import 'package:nyrna/window/active_window.dart'; import 'application/theme/cubit/theme_cubit.dart'; import 'domain/arguments/argument_parser.dart'; +import 'infrastructure/logger/log_file.dart'; Future main(List args) async { // Parse command-line arguments. @@ -47,7 +47,7 @@ Future initSettings() async { } /// Print log messages & add them to a Queue so they can be referenced, for -/// example from the [LogScreen]. +/// example from the [LogPage]. void initLogger() { final logQueue = LogFile.logs; Logger.root.onRecord.listen((record) { diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index c4a853f2..e2dc15ab 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/logger/log_screen.dart'; +import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/screens/apps_screen.dart'; import 'package:nyrna/screens/loading_screen.dart'; import 'package:nyrna/settings/screens/settings_screen.dart'; @@ -24,7 +24,7 @@ class AppWidget extends StatelessWidget { theme: state.themeData, routes: { LoadingScreen.id: (context) => LoadingScreen(), - LogScreen.id: (context) => LogScreen(), + LogPage.id: (context) => LogPage(), RunningAppsScreen.id: (context) => RunningAppsScreen(), SettingsScreen.id: (conext) => SettingsScreen(), }, diff --git a/lib/presentation/logs/logs.dart b/lib/presentation/logs/logs.dart new file mode 100644 index 00000000..68a3d15d --- /dev/null +++ b/lib/presentation/logs/logs.dart @@ -0,0 +1 @@ +export 'pages/log_page.dart'; diff --git a/lib/logger/log_screen.dart b/lib/presentation/logs/pages/log_page.dart similarity index 94% rename from lib/logger/log_screen.dart rename to lib/presentation/logs/pages/log_page.dart index 825ccda7..4ada6ab5 100644 --- a/lib/logger/log_screen.dart +++ b/lib/presentation/logs/pages/log_page.dart @@ -1,17 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:logging/logging.dart'; -import 'package:nyrna/logger/log_file.dart'; +import 'package:nyrna/infrastructure/logger/log_file.dart'; /// Display Nyrna's logs. -class LogScreen extends StatefulWidget { +class LogPage extends StatefulWidget { static final id = 'LogScreen'; @override - _LogScreenState createState() => _LogScreenState(); + _LogPageState createState() => _LogPageState(); } -class _LogScreenState extends State { +class _LogPageState extends State { /// The level of logs to show, changed with the DropdownButton. Level level = Level.INFO; diff --git a/lib/presentation/logs/pages/pages.dart b/lib/presentation/logs/pages/pages.dart new file mode 100644 index 00000000..f4e27fde --- /dev/null +++ b/lib/presentation/logs/pages/pages.dart @@ -0,0 +1 @@ +export 'log_page.dart'; diff --git a/lib/settings/screens/settings_screen.dart b/lib/settings/screens/settings_screen.dart index 51bc2966..dd8a1448 100644 --- a/lib/settings/screens/settings_screen.dart +++ b/lib/settings/screens/settings_screen.dart @@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/components/input_dialog.dart'; import 'package:nyrna/globals.dart'; -import 'package:nyrna/logger/log_screen.dart'; +import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/nyrna.dart'; import 'package:nyrna/settings/settings.dart'; import 'package:provider/provider.dart'; @@ -146,7 +146,7 @@ class _SettingsScreenState extends State { ListTile( leading: const Icon(Icons.article_outlined), title: Text('Logs'), - onTap: () => Navigator.pushNamed(context, LogScreen.id), + onTap: () => Navigator.pushNamed(context, LogPage.id), ), _sectionPadding, Text('About'), diff --git a/lib/window/active_window.dart b/lib/window/active_window.dart index 55ab050e..8a6a95cd 100644 --- a/lib/window/active_window.dart +++ b/lib/window/active_window.dart @@ -1,7 +1,7 @@ import 'dart:io' as io; import 'package:logging/logging.dart'; -import 'package:nyrna/logger/log_file.dart'; +import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/platform/native_platform.dart'; import 'package:nyrna/process/process.dart'; import 'package:nyrna/settings/settings.dart'; From cb92b361569373412bc07187c4bf6b024b313548 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 09:52:06 -0400 Subject: [PATCH 06/83] Refactor logger for DDD --- lib/infrastructure/logger/app_logger.dart | 22 ++++++++++++++++++++++ lib/main.dart | 21 ++------------------- 2 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 lib/infrastructure/logger/app_logger.dart diff --git a/lib/infrastructure/logger/app_logger.dart b/lib/infrastructure/logger/app_logger.dart new file mode 100644 index 00000000..a6f7377d --- /dev/null +++ b/lib/infrastructure/logger/app_logger.dart @@ -0,0 +1,22 @@ +import 'package:logging/logging.dart'; + +import 'log_file.dart'; + +class AppLogger { + /// Print log messages & add them to a Queue so they can be referenced, for + /// example from the [LogPage]. + void initialize() { + final logQueue = LogFile.logs; + Logger.root.onRecord.listen((record) { + var msg = '${record.level.name}: ${record.time}: ' + '${record.loggerName}: ${record.message}'; + if (record.error != null) msg += '\nError: ${record.error}'; + print(msg); + logQueue.addLast(record); + // In case the log grows too crazy, prune for sanity. + while (logQueue.length > 100) { + logQueue.removeFirst(); + } + }); + } +} diff --git a/lib/main.dart b/lib/main.dart index c1044de5..b274f14f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; -import 'package:nyrna/presentation/logs/pages/log_page.dart'; +import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/settings/settings.dart'; import 'package:nyrna/window/active_window.dart'; @@ -20,7 +20,7 @@ Future main(List args) async { await initSettings(); - initLogger(); + AppLogger().initialize(); // `-t` or `--toggle` flag detected. if (Config.toggle) await toggleActiveWindow(); @@ -46,23 +46,6 @@ Future initSettings() async { await settings.initialize(); } -/// Print log messages & add them to a Queue so they can be referenced, for -/// example from the [LogPage]. -void initLogger() { - final logQueue = LogFile.logs; - Logger.root.onRecord.listen((record) { - var msg = '${record.level.name}: ${record.time}: ' - '${record.loggerName}: ${record.message}'; - if (record.error != null) msg += '\nError: ${record.error}'; - print(msg); - logQueue.addLast(record); - // In case the log grows too crazy, prune for sanity. - while (logQueue.length > 100) { - logQueue.removeFirst(); - } - }); -} - /// Toggle suspend / resume for the active, foreground window. Future toggleActiveWindow() async { final _log = Logger('toggleActiveWindow'); From 0331bc310cef61f5c2b36978260988b9832e4575 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:09:58 -0400 Subject: [PATCH 07/83] Refactor preferences for DDD --- lib/application/theme/cubit/theme_cubit.dart | 6 +++--- .../preferences/preferences.dart} | 6 +++--- lib/main.dart | 14 +++----------- lib/nyrna.dart | 4 ++-- lib/presentation/app_widget.dart | 4 ++-- .../preferences/pages/preferences_page.dart} | 12 ++++++------ lib/presentation/preferences/preferences.dart | 1 + lib/screens/apps_screen.dart | 8 ++++---- lib/settings/update_notifier.dart | 4 ++-- lib/window/active_window.dart | 4 ++-- test/settings/update_notifier_test.dart | 6 +++--- test/window/active_window_test.dart | 4 ++-- 12 files changed, 33 insertions(+), 40 deletions(-) rename lib/{settings/settings.dart => infrastructure/preferences/preferences.dart} (96%) rename lib/{settings/screens/settings_screen.dart => presentation/preferences/pages/preferences_page.dart} (96%) create mode 100644 lib/presentation/preferences/preferences.dart diff --git a/lib/application/theme/cubit/theme_cubit.dart b/lib/application/theme/cubit/theme_cubit.dart index bcb75f3b..71a48ca2 100644 --- a/lib/application/theme/cubit/theme_cubit.dart +++ b/lib/application/theme/cubit/theme_cubit.dart @@ -2,19 +2,19 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:nyrna/application/theme/enums/app_theme.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; part 'theme_state.dart'; late ThemeCubit themeCubit; class ThemeCubit extends Cubit { - ThemeCubit() : super(ThemeState(appTheme: Settings.instance.appTheme)) { + ThemeCubit() : super(ThemeState(appTheme: Preferences.instance.appTheme)) { themeCubit = this; } void changeTheme(AppTheme appTheme) { - Settings.instance.appTheme = appTheme; + Preferences.instance.appTheme = appTheme; emit(state.copyWith(appTheme: appTheme)); } } diff --git a/lib/settings/settings.dart b/lib/infrastructure/preferences/preferences.dart similarity index 96% rename from lib/settings/settings.dart rename to lib/infrastructure/preferences/preferences.dart index dbf53d17..8a374945 100644 --- a/lib/settings/settings.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -7,10 +7,10 @@ import 'package:nyrna/globals.dart'; import 'package:shared_preferences/shared_preferences.dart'; /// Manages settings & preferences. -class Settings { +class Preferences { // Settings is a singleton. - Settings._privateConstructor(); - static final Settings instance = Settings._privateConstructor(); + Preferences._privateConstructor(); + static final Preferences instance = Preferences._privateConstructor(); static final _log = Logger('Settings'); diff --git a/lib/main.dart b/lib/main.dart index b274f14f..b93effbf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,7 @@ import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/active_window.dart'; import 'application/theme/cubit/theme_cubit.dart'; @@ -18,7 +18,8 @@ Future main(List args) async { final parser = ArgumentParser(args); await parser.parse(); - await initSettings(); + final settings = Preferences.instance; + await settings.initialize(); AppLogger().initialize(); @@ -37,15 +38,6 @@ Future main(List args) async { ); } -/// Initialize the singleton Settings instance in settings.dart -/// -/// Needed early both because it runs syncronously and would block UI, -/// as well as because the toggle feature checks for a saved process. -Future initSettings() async { - final settings = Settings.instance; - await settings.initialize(); -} - /// Toggle suspend / resume for the active, foreground window. Future toggleActiveWindow() async { final _log = Logger('toggleActiveWindow'); diff --git a/lib/nyrna.dart b/lib/nyrna.dart index 42205bf0..8795876e 100644 --- a/lib/nyrna.dart +++ b/lib/nyrna.dart @@ -3,7 +3,7 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; import 'package:nyrna/platform/native_platform.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window.dart'; /// Represents Nyrna, its state, and interactions. @@ -28,7 +28,7 @@ class Nyrna extends ChangeNotifier { final _nativePlatform = NativePlatform(); - final _settings = Settings.instance; + final _settings = Preferences.instance; int? _currentDesktop; diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index e2dc15ab..f20360c5 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -4,7 +4,7 @@ import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/screens/apps_screen.dart'; import 'package:nyrna/screens/loading_screen.dart'; -import 'package:nyrna/settings/screens/settings_screen.dart'; +import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:provider/provider.dart'; import '../nyrna.dart'; @@ -26,7 +26,7 @@ class AppWidget extends StatelessWidget { LoadingScreen.id: (context) => LoadingScreen(), LogPage.id: (context) => LogPage(), RunningAppsScreen.id: (context) => RunningAppsScreen(), - SettingsScreen.id: (conext) => SettingsScreen(), + PreferencesPage.id: (conext) => PreferencesPage(), }, home: LoadingScreen(), ); diff --git a/lib/settings/screens/settings_screen.dart b/lib/presentation/preferences/pages/preferences_page.dart similarity index 96% rename from lib/settings/screens/settings_screen.dart rename to lib/presentation/preferences/pages/preferences_page.dart index dd8a1448..72d859d1 100644 --- a/lib/settings/screens/settings_screen.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -7,21 +7,21 @@ import 'package:nyrna/components/input_dialog.dart'; import 'package:nyrna/globals.dart'; import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/nyrna.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../launcher.dart'; +import '../../../settings/launcher.dart'; /// Screen with configuration settings for Nyrna. -class SettingsScreen extends StatefulWidget { +class PreferencesPage extends StatefulWidget { static const id = 'settings_screen'; @override - _SettingsScreenState createState() => _SettingsScreenState(); + _PreferencesPageState createState() => _PreferencesPageState(); } -class _SettingsScreenState extends State { +class _PreferencesPageState extends State { late Nyrna nyrna; final _divider = const Divider( @@ -32,7 +32,7 @@ class _SettingsScreenState extends State { /// Adds a little space between sections. final _sectionPadding = const SizedBox(height: 50); - Settings settings = Settings.instance; + Preferences settings = Preferences.instance; late final _warningChip = ActionChip( label: Text( diff --git a/lib/presentation/preferences/preferences.dart b/lib/presentation/preferences/preferences.dart new file mode 100644 index 00000000..8a66d351 --- /dev/null +++ b/lib/presentation/preferences/preferences.dart @@ -0,0 +1 @@ +export 'pages/preferences_page.dart'; diff --git a/lib/screens/apps_screen.dart b/lib/screens/apps_screen.dart index f33cf95b..a0cb76d1 100644 --- a/lib/screens/apps_screen.dart +++ b/lib/screens/apps_screen.dart @@ -8,8 +8,8 @@ import 'package:nyrna/components/window_tile.dart'; import 'package:nyrna/globals.dart'; import 'package:nyrna/nyrna.dart'; import 'package:nyrna/process/process.dart'; -import 'package:nyrna/settings/screens/settings_screen.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/settings/update_notifier.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -32,7 +32,7 @@ class _RunningAppsScreenState extends State { static final _log = Logger('RunningAppsScreen'); - final _settings = Settings.instance; + final _settings = Preferences.instance; @override void initState() { @@ -100,7 +100,7 @@ class _RunningAppsScreenState extends State { icon: const Icon(Icons.settings), onPressed: () { _log.info('User clicked settings button'); - Navigator.pushNamed(context, SettingsScreen.id); + Navigator.pushNamed(context, PreferencesPage.id); }, ), ], diff --git a/lib/settings/update_notifier.dart b/lib/settings/update_notifier.dart index 318ca410..0c46d2b2 100644 --- a/lib/settings/update_notifier.dart +++ b/lib/settings/update_notifier.dart @@ -1,10 +1,10 @@ import 'package:http/http.dart' as http; import 'package:nyrna/globals.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; /// Check if updates to Nyrna are available. class UpdateNotifier { - final _settings = Settings.instance; + final _settings = Preferences.instance; /// If update is available returns true. Future updateAvailable() async { diff --git a/lib/window/active_window.dart b/lib/window/active_window.dart index 8a6a95cd..b45d3863 100644 --- a/lib/window/active_window.dart +++ b/lib/window/active_window.dart @@ -4,7 +4,7 @@ import 'package:logging/logging.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/platform/native_platform.dart'; import 'package:nyrna/process/process.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; @@ -18,7 +18,7 @@ class ActiveWindow { static final _log = Logger('ActiveWindow'); - final _settings = Settings.instance; + final _settings = Preferences.instance; /// Nyrna's own PID. final int nyrnaPid = io.pid; diff --git a/test/settings/update_notifier_test.dart b/test/settings/update_notifier_test.dart index 1d23074f..8694af44 100644 --- a/test/settings/update_notifier_test.dart +++ b/test/settings/update_notifier_test.dart @@ -1,13 +1,13 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nyrna/globals.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/settings/update_notifier.dart'; void main() { - Settings? _settings; + Preferences? _settings; setUp(() async { - _settings = Settings.instance; + _settings = Preferences.instance; await _settings!.initialize(); }); diff --git a/test/window/active_window_test.dart b/test/window/active_window_test.dart index d3ebf3c6..56add1c9 100644 --- a/test/window/active_window_test.dart +++ b/test/window/active_window_test.dart @@ -1,9 +1,9 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/settings/settings.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/active_window.dart'; Future main() async { - final settings = Settings.instance; + final settings = Preferences.instance; await settings.initialize(); ActiveWindow? activeWindow; From b90566096ecb9147b1a72665cf3db862ab7249d2 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:10:55 -0400 Subject: [PATCH 08/83] Minor refactor --- lib/main.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b93effbf..5c0308fb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,8 +18,8 @@ Future main(List args) async { final parser = ArgumentParser(args); await parser.parse(); - final settings = Preferences.instance; - await settings.initialize(); + final prefs = Preferences.instance; + await prefs.initialize(); AppLogger().initialize(); From 531de94dc8c199871f5adf23c8938b8a161fe0af Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:18:54 -0400 Subject: [PATCH 09/83] Refactor ActiveWindow for DDD --- lib/main.dart | 24 +----------------------- lib/window/active_window.dart | 34 ++++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5c0308fb..b5c51446 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,5 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:logging/logging.dart'; import 'package:nyrna/config.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; @@ -11,7 +8,6 @@ import 'package:nyrna/window/active_window.dart'; import 'application/theme/cubit/theme_cubit.dart'; import 'domain/arguments/argument_parser.dart'; -import 'infrastructure/logger/log_file.dart'; Future main(List args) async { // Parse command-line arguments. @@ -24,7 +20,7 @@ Future main(List args) async { AppLogger().initialize(); // `-t` or `--toggle` flag detected. - if (Config.toggle) await toggleActiveWindow(); + if (Config.toggle) await ActiveWindow().toggle(); runApp( MultiBlocProvider( @@ -37,21 +33,3 @@ Future main(List args) async { ), ); } - -/// Toggle suspend / resume for the active, foreground window. -Future toggleActiveWindow() async { - final _log = Logger('toggleActiveWindow'); - _log.info('toggleActiveWindow beginning'); - final activeWindow = ActiveWindow(); - await activeWindow.hideNyrna(); - await activeWindow.initialize(); - final successful = await activeWindow.toggle(); - if (!successful) { - await activeWindow.removeSavedProcess(); - _log.warning('Failed to toggle active window. Cleared saved pid.'); - } - _log.info('Finished toggle window, exiting.'); - if (Config.log) await LogFile.instance.write(); - // Not yet possible to run without GUI, so we just exit after toggling. - exit(0); -} diff --git a/lib/window/active_window.dart b/lib/window/active_window.dart index b45d3863..56ace2bd 100644 --- a/lib/window/active_window.dart +++ b/lib/window/active_window.dart @@ -1,5 +1,7 @@ import 'dart:io' as io; +import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/platform/native_platform.dart'; @@ -8,6 +10,8 @@ import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; +import '../config.dart'; + /// Represents the active, foreground window on the system. /// /// Initialize() must be called before anything else. @@ -27,6 +31,7 @@ class ActiveWindow { late int pid; + @visibleForTesting Future initialize() async { pid = await _nativePlatform.activeWindowPid; await _verifyPid(); @@ -37,7 +42,7 @@ class ActiveWindow { /// /// Necessary when using the toggle active window feature, /// until Flutter has a way to run without GUI. - Future hideNyrna() async { + Future _hideNyrna() async { switch (io.Platform.operatingSystem) { case 'linux': await _hideLinux(); @@ -84,7 +89,7 @@ class ActiveWindow { final savedProcess = Process(savedPid); final exists = await savedProcess.exists(); if (!exists) { - await removeSavedProcess(); + await _removeSavedProcess(); _log.warning('Saved pid no longer exists, removed.'); await LogFile.instance.write(); io.exit(0); @@ -92,7 +97,7 @@ class ActiveWindow { } /// Toggle the suspend / resume state of the given process. - Future toggle() async { + Future _toggleProcess() async { if (_settings.savedProcess != 0) { final successful = await _resume(); return successful; @@ -109,12 +114,12 @@ class ActiveWindow { final process = Process(pid); final _status = await process.status; if (_status == ProcessStatus.unknown) { - await removeSavedProcess(); + await _removeSavedProcess(); _log.warning('Issue getting status, removed saved process.'); } if (_status == ProcessStatus.suspended) { successful = await process.toggle(); - await removeSavedProcess(); + await _removeSavedProcess(); if (!successful) { _log.warning('Failed to resume PID: $pid'); return successful; @@ -124,7 +129,7 @@ class ActiveWindow { return successful; } - Future removeSavedProcess() async { + Future _removeSavedProcess() async { await _settings.setSavedProcess(0); await _settings.setSavedWindowId(0); } @@ -146,4 +151,21 @@ class ActiveWindow { } return successful; } + + /// Toggle suspend / resume for the active, foreground window. + Future toggle() async { + final _log = Logger('toggleActiveWindow'); + _log.info('toggleActiveWindow beginning'); + await _hideNyrna(); + await initialize(); + final successful = await _toggleProcess(); + if (!successful) { + await _removeSavedProcess(); + _log.warning('Failed to toggle active window. Cleared saved pid.'); + } + _log.info('Finished toggle window, exiting.'); + if (Config.log) await LogFile.instance.write(); + // Not yet possible to run without GUI, so we just exit after toggling. + exit(0); + } } From 0020bef466f549512795bd94e8df80024cb57f57 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:22:51 -0400 Subject: [PATCH 10/83] Refactor ActiveWindow to Application --- lib/{window => application/active_window}/active_window.dart | 5 ++--- lib/main.dart | 2 +- test/window/active_window_test.dart | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) rename lib/{window => application/active_window}/active_window.dart (98%) diff --git a/lib/window/active_window.dart b/lib/application/active_window/active_window.dart similarity index 98% rename from lib/window/active_window.dart rename to lib/application/active_window/active_window.dart index 56ace2bd..8053994a 100644 --- a/lib/window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -1,5 +1,4 @@ import 'dart:io' as io; -import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; @@ -10,7 +9,7 @@ import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; -import '../config.dart'; +import '../../config.dart'; /// Represents the active, foreground window on the system. /// @@ -166,6 +165,6 @@ class ActiveWindow { _log.info('Finished toggle window, exiting.'); if (Config.log) await LogFile.instance.write(); // Not yet possible to run without GUI, so we just exit after toggling. - exit(0); + io.exit(0); } } diff --git a/lib/main.dart b/lib/main.dart index b5c51446..9ea71ea0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,7 @@ import 'package:nyrna/config.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/window/active_window.dart'; +import 'package:nyrna/application/active_window/active_window.dart'; import 'application/theme/cubit/theme_cubit.dart'; import 'domain/arguments/argument_parser.dart'; diff --git a/test/window/active_window_test.dart b/test/window/active_window_test.dart index 56add1c9..762daf81 100644 --- a/test/window/active_window_test.dart +++ b/test/window/active_window_test.dart @@ -1,6 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/window/active_window.dart'; +import 'package:nyrna/application/active_window/active_window.dart'; Future main() async { final settings = Preferences.instance; From eee8daaa588a9e85e6e6fa1a15c1f097892d2f2b Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:31:32 -0400 Subject: [PATCH 11/83] Refactor platform for DDD --- lib/application/active_window/active_window.dart | 2 +- .../native_platform/linux}/linux.dart | 2 +- .../native_platform}/native_platform.dart | 5 +++-- .../native_platform/win32/ffi}/dwmapi.dart | 0 .../native_platform/win32/ffi}/user32.dart | 0 .../native_platform}/win32/win32.dart | 5 +++-- lib/nyrna.dart | 2 +- test/platform/native_platform_test.dart | 2 +- 8 files changed, 10 insertions(+), 8 deletions(-) rename lib/{platform => infrastructure/native_platform/linux}/linux.dart (97%) rename lib/{platform => infrastructure/native_platform}/native_platform.dart (90%) rename lib/{platform/win32 => infrastructure/native_platform/win32/ffi}/dwmapi.dart (100%) rename lib/{platform/win32 => infrastructure/native_platform/win32/ffi}/user32.dart (100%) rename lib/{platform => infrastructure/native_platform}/win32/win32.dart (97%) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 8053994a..95e644d2 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -3,7 +3,7 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; -import 'package:nyrna/platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/process/process.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window_controls.dart'; diff --git a/lib/platform/linux.dart b/lib/infrastructure/native_platform/linux/linux.dart similarity index 97% rename from lib/platform/linux.dart rename to lib/infrastructure/native_platform/linux/linux.dart index 6f65f04e..ad1cf6aa 100644 --- a/lib/platform/linux.dart +++ b/lib/infrastructure/native_platform/linux/linux.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:nyrna/platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/window/window.dart'; /// Interact with the native Linux operating system. diff --git a/lib/platform/native_platform.dart b/lib/infrastructure/native_platform/native_platform.dart similarity index 90% rename from lib/platform/native_platform.dart rename to lib/infrastructure/native_platform/native_platform.dart index 0f359cd2..28f18703 100644 --- a/lib/platform/native_platform.dart +++ b/lib/infrastructure/native_platform/native_platform.dart @@ -1,9 +1,10 @@ import 'dart:io'; -import 'package:nyrna/platform/linux.dart'; -import 'package:nyrna/platform/win32/win32.dart'; +import 'package:nyrna/infrastructure/native_platform/linux/linux.dart'; import 'package:nyrna/window/window.dart'; +import 'win32/win32.dart'; + /// Interact with the native operating system. /// /// Abstract class bridges types for specific operating systems. diff --git a/lib/platform/win32/dwmapi.dart b/lib/infrastructure/native_platform/win32/ffi/dwmapi.dart similarity index 100% rename from lib/platform/win32/dwmapi.dart rename to lib/infrastructure/native_platform/win32/ffi/dwmapi.dart diff --git a/lib/platform/win32/user32.dart b/lib/infrastructure/native_platform/win32/ffi/user32.dart similarity index 100% rename from lib/platform/win32/user32.dart rename to lib/infrastructure/native_platform/win32/ffi/user32.dart diff --git a/lib/platform/win32/win32.dart b/lib/infrastructure/native_platform/win32/win32.dart similarity index 97% rename from lib/platform/win32/win32.dart rename to lib/infrastructure/native_platform/win32/win32.dart index e6de3264..5c39170e 100644 --- a/lib/platform/win32/win32.dart +++ b/lib/infrastructure/native_platform/win32/win32.dart @@ -1,13 +1,14 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import 'package:nyrna/platform/win32/dwmapi.dart'; import 'package:nyrna/process/win32_process.dart'; // import 'package:nyrna/platform/win32/user32.dart'; -import 'package:nyrna/platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/window/window.dart'; import 'package:win32/win32.dart'; +import 'ffi/dwmapi.dart'; + /// Interact with the native win32 operating system. /// /// Requires many syscalls to the win32 API. diff --git a/lib/nyrna.dart b/lib/nyrna.dart index 8795876e..188d8e04 100644 --- a/lib/nyrna.dart +++ b/lib/nyrna.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:io' as io; import 'package:flutter/foundation.dart'; -import 'package:nyrna/platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window.dart'; diff --git a/test/platform/native_platform_test.dart b/test/platform/native_platform_test.dart index 59c3a8e2..0b4ec735 100644 --- a/test/platform/native_platform_test.dart +++ b/test/platform/native_platform_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; void main() { NativePlatform? nativePlatform; From f8c7ed4141c500040586a33729eeba2e544400a4 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 23 Jul 2021 10:49:42 -0400 Subject: [PATCH 12/83] Refactor visual elements to Presentation layer --- lib/presentation/app/app.dart | 2 ++ .../app/pages/apps_page.dart} | 10 +++++----- lib/presentation/app/pages/pages.dart | 1 + lib/presentation/app/widgets/widgets.dart | 0 .../app/widgets}/window_tile.dart | 0 lib/presentation/app_widget.dart | 10 +++++----- lib/presentation/core/core.dart | 1 + .../core/widgets}/input_dialog.dart | 0 lib/presentation/core/widgets/widgets.dart | 1 + .../loading_page.dart} | 11 ++++++----- lib/presentation/preferences/pages/pages.dart | 1 + .../preferences/pages/preferences_page.dart | 4 ++-- lib/presentation/preferences/preferences.dart | 2 +- 13 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 lib/presentation/app/app.dart rename lib/{screens/apps_screen.dart => presentation/app/pages/apps_page.dart} (94%) create mode 100644 lib/presentation/app/pages/pages.dart create mode 100644 lib/presentation/app/widgets/widgets.dart rename lib/{components => presentation/app/widgets}/window_tile.dart (100%) create mode 100644 lib/presentation/core/core.dart rename lib/{components => presentation/core/widgets}/input_dialog.dart (100%) create mode 100644 lib/presentation/core/widgets/widgets.dart rename lib/{screens/loading_screen.dart => presentation/loading_page.dart} (85%) create mode 100644 lib/presentation/preferences/pages/pages.dart diff --git a/lib/presentation/app/app.dart b/lib/presentation/app/app.dart new file mode 100644 index 00000000..309e1ebb --- /dev/null +++ b/lib/presentation/app/app.dart @@ -0,0 +1,2 @@ +export 'pages/pages.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/screens/apps_screen.dart b/lib/presentation/app/pages/apps_page.dart similarity index 94% rename from lib/screens/apps_screen.dart rename to lib/presentation/app/pages/apps_page.dart index a0cb76d1..18d05bdb 100644 --- a/lib/screens/apps_screen.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/components/window_tile.dart'; +import 'package:nyrna/presentation/app/widgets/window_tile.dart'; import 'package:nyrna/globals.dart'; import 'package:nyrna/nyrna.dart'; import 'package:nyrna/process/process.dart'; @@ -17,14 +17,14 @@ import 'package:url_launcher/url_launcher.dart'; /// The main screen for Nyrna. /// /// Shows a ListView with tiles for each open window on the current desktop. -class RunningAppsScreen extends StatefulWidget { +class AppsPage extends StatefulWidget { static const id = 'running_apps_screen'; @override - _RunningAppsScreenState createState() => _RunningAppsScreenState(); + _AppsPageState createState() => _AppsPageState(); } -class _RunningAppsScreenState extends State { +class _AppsPageState extends State { late Nyrna nyrna; /// Whether or not a newer version of Nyrna is available. @@ -156,7 +156,7 @@ class _RunningAppsScreenState extends State { onPressed: () { notifier.ignoreVersion(latestVersion); setState(() { - Navigator.pushReplacementNamed(context, RunningAppsScreen.id); + Navigator.pushReplacementNamed(context, AppsPage.id); }); }, child: const Text('Dismiss'), diff --git a/lib/presentation/app/pages/pages.dart b/lib/presentation/app/pages/pages.dart new file mode 100644 index 00000000..84e5f9a7 --- /dev/null +++ b/lib/presentation/app/pages/pages.dart @@ -0,0 +1 @@ +export 'apps_page.dart'; diff --git a/lib/presentation/app/widgets/widgets.dart b/lib/presentation/app/widgets/widgets.dart new file mode 100644 index 00000000..e69de29b diff --git a/lib/components/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart similarity index 100% rename from lib/components/window_tile.dart rename to lib/presentation/app/widgets/window_tile.dart diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index f20360c5..42830508 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/logs/pages/log_page.dart'; -import 'package:nyrna/screens/apps_screen.dart'; -import 'package:nyrna/screens/loading_screen.dart'; +import 'package:nyrna/presentation/loading_page.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:provider/provider.dart'; import '../nyrna.dart'; +import 'app/app.dart'; class AppWidget extends StatelessWidget { @override @@ -23,12 +23,12 @@ class AppWidget extends StatelessWidget { debugShowCheckedModeBanner: false, theme: state.themeData, routes: { - LoadingScreen.id: (context) => LoadingScreen(), + LoadingPage.id: (context) => LoadingPage(), LogPage.id: (context) => LogPage(), - RunningAppsScreen.id: (context) => RunningAppsScreen(), + AppsPage.id: (context) => AppsPage(), PreferencesPage.id: (conext) => PreferencesPage(), }, - home: LoadingScreen(), + home: LoadingPage(), ); }, ), diff --git a/lib/presentation/core/core.dart b/lib/presentation/core/core.dart new file mode 100644 index 00000000..e691bba3 --- /dev/null +++ b/lib/presentation/core/core.dart @@ -0,0 +1 @@ +export 'widgets/widgets.dart'; diff --git a/lib/components/input_dialog.dart b/lib/presentation/core/widgets/input_dialog.dart similarity index 100% rename from lib/components/input_dialog.dart rename to lib/presentation/core/widgets/input_dialog.dart diff --git a/lib/presentation/core/widgets/widgets.dart b/lib/presentation/core/widgets/widgets.dart new file mode 100644 index 00000000..598d3d73 --- /dev/null +++ b/lib/presentation/core/widgets/widgets.dart @@ -0,0 +1 @@ +export 'input_dialog.dart'; diff --git a/lib/screens/loading_screen.dart b/lib/presentation/loading_page.dart similarity index 85% rename from lib/screens/loading_screen.dart rename to lib/presentation/loading_page.dart index f987f3e7..992be318 100644 --- a/lib/screens/loading_screen.dart +++ b/lib/presentation/loading_page.dart @@ -1,18 +1,19 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/nyrna.dart'; -import 'package:nyrna/screens/apps_screen.dart'; + +import 'app/app.dart'; /// Intermediate loading screen while verifying that Nyrna's dependencies are /// available. If they are not an error message is shown, preventing a crash. -class LoadingScreen extends StatefulWidget { +class LoadingPage extends StatefulWidget { static const id = 'loading_screen'; @override - _LoadingScreenState createState() => _LoadingScreenState(); + _LoadingPageState createState() => _LoadingPageState(); } -class _LoadingScreenState extends State { +class _LoadingPageState extends State { static final _log = Logger('LoadingScreen'); late Nyrna nyrna; @@ -36,7 +37,7 @@ class _LoadingScreenState extends State { // Slight delay required so we don't push the main // screen while the build method is still executing. Future.microtask(() { - Navigator.pushReplacementNamed(context, RunningAppsScreen.id); + Navigator.pushReplacementNamed(context, AppsPage.id); }); } else { return Card( diff --git a/lib/presentation/preferences/pages/pages.dart b/lib/presentation/preferences/pages/pages.dart new file mode 100644 index 00000000..c169f1ac --- /dev/null +++ b/lib/presentation/preferences/pages/pages.dart @@ -0,0 +1 @@ +export 'preferences_page.dart'; diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index 72d859d1..bcddeee5 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -3,11 +3,11 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/components/input_dialog.dart'; import 'package:nyrna/globals.dart'; -import 'package:nyrna/presentation/logs/pages/log_page.dart'; +import 'package:nyrna/presentation/core/core.dart'; import 'package:nyrna/nyrna.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; +import 'package:nyrna/presentation/logs/logs.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/lib/presentation/preferences/preferences.dart b/lib/presentation/preferences/preferences.dart index 8a66d351..91719565 100644 --- a/lib/presentation/preferences/preferences.dart +++ b/lib/presentation/preferences/preferences.dart @@ -1 +1 @@ -export 'pages/preferences_page.dart'; +export 'pages/pages.dart'; From 11a41e5deb4cba8e72209fa951a230ca3215de37 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 24 Jul 2021 10:30:50 -0400 Subject: [PATCH 13/83] Refactor to use AppCubit --- lib/application/app/app.dart | 1 + lib/application/app/cubit/app_cubit.dart | 83 ++++++++++++ lib/application/app/cubit/app_state.dart | 36 ++++++ .../loading/cubit/loading_cubit.dart | 21 ++++ .../loading/cubit/loading_state.dart | 14 +++ lib/application/loading/loading.dart | 1 + .../preferences/cubit/preferences_cubit.dart | 17 +++ .../preferences/cubit/preferences_state.dart | 10 ++ lib/globals.dart | 11 -- .../launcher}/launcher.dart | 43 +++++-- .../preferences/preferences.dart | 4 +- lib/main.dart | 9 ++ lib/nyrna.dart | 118 ------------------ lib/presentation/app/pages/apps_page.dart | 52 ++++---- lib/presentation/app_widget.dart | 37 +++--- lib/presentation/loading_page.dart | 60 ++++----- .../preferences/pages/preferences_page.dart | 26 ++-- 17 files changed, 299 insertions(+), 244 deletions(-) create mode 100644 lib/application/app/app.dart create mode 100644 lib/application/app/cubit/app_cubit.dart create mode 100644 lib/application/app/cubit/app_state.dart create mode 100644 lib/application/loading/cubit/loading_cubit.dart create mode 100644 lib/application/loading/cubit/loading_state.dart create mode 100644 lib/application/loading/loading.dart create mode 100644 lib/application/preferences/cubit/preferences_cubit.dart create mode 100644 lib/application/preferences/cubit/preferences_state.dart rename lib/{settings => infrastructure/launcher}/launcher.dart (63%) delete mode 100644 lib/nyrna.dart diff --git a/lib/application/app/app.dart b/lib/application/app/app.dart new file mode 100644 index 00000000..253d603e --- /dev/null +++ b/lib/application/app/app.dart @@ -0,0 +1 @@ +export 'cubit/app_cubit.dart'; diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart new file mode 100644 index 00000000..1b71b8af --- /dev/null +++ b/lib/application/app/cubit/app_cubit.dart @@ -0,0 +1,83 @@ +import 'dart:async'; +import 'dart:io' as io; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; +import 'package:nyrna/window/window.dart'; + +part 'app_state.dart'; + +/// Convenience access to the main app cubit. +late AppCubit appCubit; + +class AppCubit extends Cubit { + final NativePlatform nativePlatform; + final Preferences prefs; + + AppCubit() + : nativePlatform = NativePlatform(), + prefs = Preferences.instance, + super(AppState.initial()) { + appCubit = this; + _initialize(); + } + + Future _initialize() async { + _setAutoRefresh(); + await _fetchDesktop(); + } + + Timer? _timer; + + /// The timer which auto-refreshes the list of open windows. + void _setAutoRefresh() { + fetchData(); + if (_timer != null) _timer!.cancel(); + if (prefs.autoRefresh) { + _timer = Timer.periodic( + Duration(seconds: prefs.refreshInterval), + (timer) => fetchData(), + ); + } + } + + Future fetchData() async { + await _fetchDesktop(); + await fetchWindows(); + } + + Future _fetchDesktop() async { + final currentDesktop = await nativePlatform.currentDesktop; + emit(state.copyWith(currentDesktop: currentDesktop)); + } + + Future updateAutoRefresh([bool? autoEnabled]) async { + if (autoEnabled != null) await prefs.setAutoRefresh(autoEnabled); + _setAutoRefresh(); + } + + /// Check for which windows are open. + Future fetchWindows() async { + final newWindows = await nativePlatform.windows; + final windows = Map.from(state.windows); + // Remove if window no longer present, or title has changed. + windows.removeWhere((pid, window) { + if (!newWindows.containsKey(pid) || // Window no longer present. + (newWindows[pid]!.title != window.title)) // Window title changed. + { + return true; + } else { + return false; + } + }); + // Filter out Nyrna's own window / process. + newWindows.removeWhere((pid, window) => pid == io.pid.toString()); + // Add new windows (and those whose title changed). + newWindows.forEach((pid, window) { + if (!windows.containsKey(pid)) windows[pid] = window; + }); + emit(state.copyWith(windows: windows)); + } +} diff --git a/lib/application/app/cubit/app_state.dart b/lib/application/app/cubit/app_state.dart new file mode 100644 index 00000000..ff2202ce --- /dev/null +++ b/lib/application/app/cubit/app_state.dart @@ -0,0 +1,36 @@ +part of 'app_cubit.dart'; + +class AppState extends Equatable { + /// The index of the currently active virtual desktop. + final int currentDesktop; + + final Map windows; + + const AppState._internal({ + required this.currentDesktop, + required this.windows, + }); + + factory AppState.initial() { + return AppState._internal( + currentDesktop: 0, + windows: {}, + ); + } + + @override + List get props => [ + currentDesktop, + windows, + ]; + + AppState copyWith({ + int? currentDesktop, + Map? windows, + }) { + return AppState._internal( + currentDesktop: currentDesktop ?? this.currentDesktop, + windows: windows ?? this.windows, + ); + } +} diff --git a/lib/application/loading/cubit/loading_cubit.dart b/lib/application/loading/cubit/loading_cubit.dart new file mode 100644 index 00000000..9804311b --- /dev/null +++ b/lib/application/loading/cubit/loading_cubit.dart @@ -0,0 +1,21 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; + +part 'loading_state.dart'; + +class LoadingCubit extends Cubit { + final NativePlatform nativePlatform; + + LoadingCubit() + : nativePlatform = NativePlatform(), + super(LoadingInitial()) { + checkDependencies(); + } + + Future checkDependencies() async { + final dependenciesSatisfied = await nativePlatform.checkDependencies(); + final newState = dependenciesSatisfied ? LoadingSuccess() : LoadingFailed(); + emit(newState); + } +} diff --git a/lib/application/loading/cubit/loading_state.dart b/lib/application/loading/cubit/loading_state.dart new file mode 100644 index 00000000..d82d35b0 --- /dev/null +++ b/lib/application/loading/cubit/loading_state.dart @@ -0,0 +1,14 @@ +part of 'loading_cubit.dart'; + +abstract class LoadingState extends Equatable { + const LoadingState(); + + @override + List get props => []; +} + +class LoadingInitial extends LoadingState {} + +class LoadingSuccess extends LoadingState {} + +class LoadingFailed extends LoadingState {} diff --git a/lib/application/loading/loading.dart b/lib/application/loading/loading.dart new file mode 100644 index 00000000..2279c51a --- /dev/null +++ b/lib/application/loading/loading.dart @@ -0,0 +1 @@ +export 'cubit/loading_cubit.dart'; diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart new file mode 100644 index 00000000..f3e4d108 --- /dev/null +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -0,0 +1,17 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:nyrna/infrastructure/launcher/launcher.dart'; + +part 'preferences_state.dart'; + +late PreferencesCubit preferencesCubit; + +class PreferencesCubit extends Cubit { + PreferencesCubit() : super(PreferencesInitial()) { + preferencesCubit = this; + } + + Future createLauncher() async { + await Launcher.add(); + } +} diff --git a/lib/application/preferences/cubit/preferences_state.dart b/lib/application/preferences/cubit/preferences_state.dart new file mode 100644 index 00000000..575db98c --- /dev/null +++ b/lib/application/preferences/cubit/preferences_state.dart @@ -0,0 +1,10 @@ +part of 'preferences_cubit.dart'; + +abstract class PreferencesState extends Equatable { + const PreferencesState(); + + @override + List get props => []; +} + +class PreferencesInitial extends PreferencesState {} diff --git a/lib/globals.dart b/lib/globals.dart index bfd60eec..4e72842a 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -1,16 +1,5 @@ -import 'package:path_provider/path_provider.dart'; - /// Globally accessible variables. class Globals { /// Nyrna's current running version. static String version = ''; - - static String? _tempPath; - - /// The system's temp path, for example: `/tmp`. - static Future get tempPath async { - if (_tempPath != null) return _tempPath; - final _tempDir = await getTemporaryDirectory(); - return _tempDir.path; - } } diff --git a/lib/settings/launcher.dart b/lib/infrastructure/launcher/launcher.dart similarity index 63% rename from lib/settings/launcher.dart rename to lib/infrastructure/launcher/launcher.dart index 160b21ef..e4b26a75 100644 --- a/lib/settings/launcher.dart +++ b/lib/infrastructure/launcher/launcher.dart @@ -1,8 +1,6 @@ import 'dart:io'; -import 'package:flutter/material.dart'; -import 'package:nyrna/globals.dart'; -import 'package:nyrna/nyrna.dart'; +import 'package:path_provider/path_provider.dart' as pp; /// Manage launcher entry. /// @@ -12,9 +10,8 @@ import 'package:nyrna/nyrna.dart'; /// Currently only for the portable version on Linux. class Launcher { /// Add a launcher entry for Nyrna with icon. - static Future add(BuildContext context) async { + static Future add() async { await _addLauncher(); - Navigator.pop(context); } static Future _addLauncher() async { @@ -28,6 +25,35 @@ class Launcher { break; } } + + static String? _executablePath; + + /// Absolute path to Nyrna's executable. + static String get executablePath { + if (_executablePath != null) return _executablePath!; + _executablePath = Platform.resolvedExecutable; + return _executablePath!; + } + + static String? _nyrnaDir; + + /// Absolute path to Nyrna's install directory. + static String get directory { + if (_nyrnaDir != null) return _nyrnaDir!; + final nyrnaPath = executablePath.substring(0, (executablePath.length - 5)); + _nyrnaDir = nyrnaPath; + return nyrnaPath; + } + + static String? _iconPath; + + /// Absolute path to Nyrna's bundled icon asset. + static String? get iconPath { + if (_iconPath != null) return _iconPath; + final _ending = (Platform.isLinux) ? 'png' : 'ico'; + _iconPath = '${directory}data/flutter_assets/assets/icons/nyrna.$_ending'; + return _iconPath; + } } /// Manage launcher entry on Linux. @@ -46,7 +72,7 @@ class _LinuxLauncher { try { await Process.run( 'xdg-icon-resource', - ['install', '--novendor', '--size', '256', '${Nyrna.iconPath}'], + ['install', '--novendor', '--size', '256', '${Launcher.iconPath}'], ); } catch (err) { // TODO: Error handling. @@ -60,7 +86,8 @@ class _LinuxLauncher { /// https://portland.freedesktop.org/xdg-utils-1.1.0-rc1/scripts/html/xdg-desktop-menu.html static Future _addDesktopFile() async { // Write .desktop file to disk in the temp directory. - final tempDir = await Globals.tempPath; + + final tempDir = await pp.getTemporaryDirectory(); final desktopFile = File('$tempDir/nyrna.desktop'); await desktopFile.writeAsString(_desktopFileContent); // Install to xdg location. @@ -80,7 +107,7 @@ final String _desktopFileContent = ''' Type=Application Name=Nyrna Comment=Suspend games & applications -Exec=${Nyrna.executablePath} +Exec=${Launcher.executablePath} Icon=nyrna Terminal=false StartupNotify=false diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index 8a374945..1815643f 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -61,8 +61,8 @@ class Preferences { return prefs!.getBool('autoRefresh') ?? defaultValue; } - set autoRefresh(bool shouldRefresh) { - prefs!.setBool('autoRefresh', shouldRefresh); + Future setAutoRefresh(bool shouldRefresh) async { + await prefs?.setBool('autoRefresh', shouldRefresh); } /// How often to automatically refresh the list of open windows, in seconds. diff --git a/lib/main.dart b/lib/main.dart index 9ea71ea0..40575613 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,8 @@ import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/application/active_window/active_window.dart'; +import 'application/app/app.dart'; +import 'application/preferences/cubit/preferences_cubit.dart'; import 'application/theme/cubit/theme_cubit.dart'; import 'domain/arguments/argument_parser.dart'; @@ -25,6 +27,13 @@ Future main(List args) async { runApp( MultiBlocProvider( providers: [ + BlocProvider( + create: (context) => AppCubit(), + lazy: false, + ), + BlocProvider( + create: (context) => PreferencesCubit(), + ), BlocProvider( create: (context) => ThemeCubit(), ), diff --git a/lib/nyrna.dart b/lib/nyrna.dart deleted file mode 100644 index 188d8e04..00000000 --- a/lib/nyrna.dart +++ /dev/null @@ -1,118 +0,0 @@ -import 'dart:async'; -import 'dart:io' as io; - -import 'package:flutter/foundation.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/window/window.dart'; - -/// Represents Nyrna, its state, and interactions. -class Nyrna extends ChangeNotifier { - Nyrna() { - setRefresh(); - } - - Timer? _timer; - - /// The time which auto-refreshes the list of open windows. - void setRefresh() { - fetchData(); - if (_timer != null) _timer!.cancel(); - if (_settings.autoRefresh) { - _timer = Timer.periodic( - Duration(seconds: _settings.refreshInterval), - (timer) => fetchData(), - ); - } - } - - final _nativePlatform = NativePlatform(); - - final _settings = Preferences.instance; - - int? _currentDesktop; - - /// Returns the index of the currently active virtual desktop. - /// - /// The left-most / first desktop starts at index 0. - int? get currentDesktop => _currentDesktop; - - /// Check which virtual desktop is active. - Future fetchDesktop() async { - _currentDesktop = await _nativePlatform.currentDesktop; - notifyListeners(); - } - - final Map _windows = {}; - - /// [Map] where keys are [pid] and values are [Window] objects. - Map get windows => _windows; - - /// Check for which windows are open. - Future fetchWindows() async { - final newWindows = await _nativePlatform.windows; - // Remove if window no longer present, or title has changed. - _windows.removeWhere((pid, window) { - if (!newWindows.containsKey(pid) || // Window no longer present. - (newWindows[pid]!.title != window.title)) // Window title changed. - { - return true; - } else { - return false; - } - }); - // Filter out Nyrna's own window / process. - newWindows.removeWhere((pid, window) => pid == io.pid.toString()); - // Add new windows (and those whose title changed). - newWindows.forEach((pid, window) { - if (!_windows.containsKey(pid)) _windows[pid] = window; - }); - notifyListeners(); - } - - /// Fetch fresh data. - void fetchData() { - fetchDesktop(); - fetchWindows(); - notifyListeners(); - } - - static String? _executablePath; - - /// Absolute path to Nyrna's executable. - static String get executablePath { - if (_executablePath != null) return _executablePath!; - _executablePath = io.Platform.resolvedExecutable; - return _executablePath!; - } - - static String? _nyrnaDir; - - /// Absolute path to Nyrna's install directory. - static String get directory { - if (_nyrnaDir != null) return _nyrnaDir!; - final nyrnaPath = executablePath.substring(0, (executablePath.length - 5)); - _nyrnaDir = nyrnaPath; - return nyrnaPath; - } - - static String? _iconPath; - - /// Absolute path to Nyrna's bundled icon asset. - static String? get iconPath { - if (_iconPath != null) return _iconPath; - final _ending = (io.Platform.isLinux) ? 'png' : 'ico'; - _iconPath = '${directory}data/flutter_assets/assets/icons/nyrna.$_ending'; - return _iconPath; - } - - /// Instantiate the Nyrna class without a timer. - /// - /// Used by [Loading] when checking dependencies at startup. - Nyrna.loading(); - - /// Verify Nyrna's dependencies are available on the system. - Future checkDependencies() async { - return await _nativePlatform.checkDependencies(); - } -} diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 18d05bdb..85fd3801 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -3,10 +3,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; +import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/app/widgets/window_tile.dart'; import 'package:nyrna/globals.dart'; -import 'package:nyrna/nyrna.dart'; import 'package:nyrna/process/process.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; @@ -25,8 +25,6 @@ class AppsPage extends StatefulWidget { } class _AppsPageState extends State { - late Nyrna nyrna; - /// Whether or not a newer version of Nyrna is available. Future updateAvailable = UpdateNotifier().updateAvailable(); @@ -40,12 +38,6 @@ class _AppsPageState extends State { super.initState(); } - @override - void didChangeDependencies() { - nyrna = Provider.of(context); - super.didChangeDependencies(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -53,20 +45,24 @@ class _AppsPageState extends State { body: Center( child: Container( width: MediaQuery.of(context).size.width / 1.20, - child: ListView.builder( - padding: const EdgeInsets.only(top: 40), - itemCount: nyrna.windows.length, - itemBuilder: (context, index) { - if (nyrna.windows.isEmpty) return Container(); - var keys = nyrna.windows.keys.toList(); - var window = nyrna.windows[keys[index]]!; - return ChangeNotifierProvider( - key: ValueKey('${window.pid}${window.title}'), - create: (context) => Process(window.pid), - child: WindowTile( - key: ValueKey('${window.pid}${window.title}'), - window: window, - ), + child: BlocBuilder( + builder: (context, state) { + return ListView.builder( + padding: const EdgeInsets.only(top: 40), + itemCount: state.windows.length, + itemBuilder: (context, index) { + if (state.windows.isEmpty) return Container(); + var keys = state.windows.keys.toList(); + var window = state.windows[keys[index]]!; + return ChangeNotifierProvider( + key: ValueKey('${window.pid}${window.title}'), + create: (context) => Process(window.pid), + child: WindowTile( + key: ValueKey('${window.pid}${window.title}'), + window: window, + ), + ); + }, ); }, ), @@ -88,9 +84,9 @@ class _AppsPageState extends State { // GetWindowDesktopId() with FFI. // https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ivirtualdesktopmanager-getwindowdesktopid title: (Platform.isLinux) - ? Consumer( - builder: (context, nyrna, widget) { - return Text('Current Desktop: ${nyrna.currentDesktop}'); + ? BlocBuilder( + builder: (context, state) { + return Text('Current Desktop: ${state.currentDesktop}'); }, ) : null, @@ -177,14 +173,12 @@ class _FloatingActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - final nyrna = Provider.of(context); - return BlocBuilder( builder: (context, state) { return FloatingActionButton( backgroundColor: (state.appTheme == AppTheme.pitchBlack) ? Colors.black : null, - onPressed: () => nyrna.fetchData(), + onPressed: () => appCubit.fetchData(), child: const Icon(Icons.refresh), ); }, diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index 42830508..8beb6309 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -4,34 +4,27 @@ import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/logs/pages/log_page.dart'; import 'package:nyrna/presentation/loading_page.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; -import 'package:provider/provider.dart'; -import '../nyrna.dart'; import 'app/app.dart'; class AppWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => Nyrna()), - ], - child: BlocBuilder( - builder: (context, state) { - return MaterialApp( - title: 'Nyrna', - debugShowCheckedModeBanner: false, - theme: state.themeData, - routes: { - LoadingPage.id: (context) => LoadingPage(), - LogPage.id: (context) => LogPage(), - AppsPage.id: (context) => AppsPage(), - PreferencesPage.id: (conext) => PreferencesPage(), - }, - home: LoadingPage(), - ); - }, - ), + return BlocBuilder( + builder: (context, state) { + return MaterialApp( + title: 'Nyrna', + debugShowCheckedModeBanner: false, + theme: state.themeData, + routes: { + LoadingPage.id: (context) => LoadingPage(), + LogPage.id: (context) => LogPage(), + AppsPage.id: (context) => AppsPage(), + PreferencesPage.id: (conext) => PreferencesPage(), + }, + home: LoadingPage(), + ); + }, ); } } diff --git a/lib/presentation/loading_page.dart b/lib/presentation/loading_page.dart index 992be318..2f041a5c 100644 --- a/lib/presentation/loading_page.dart +++ b/lib/presentation/loading_page.dart @@ -1,45 +1,33 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; -import 'package:nyrna/nyrna.dart'; +import 'package:nyrna/application/loading/loading.dart'; import 'app/app.dart'; /// Intermediate loading screen while verifying that Nyrna's dependencies are /// available. If they are not an error message is shown, preventing a crash. -class LoadingPage extends StatefulWidget { +class LoadingPage extends StatelessWidget { static const id = 'loading_screen'; @override - _LoadingPageState createState() => _LoadingPageState(); -} - -class _LoadingPageState extends State { - static final _log = Logger('LoadingScreen'); - late Nyrna nyrna; - - @override - void initState() { - super.initState(); + Widget build(BuildContext context) { + final _log = Logger('LoadingScreen'); _log.info('Loading screen initializing'); - nyrna = Nyrna.loading(); - } - @override - Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: FutureBuilder( - future: nyrna.checkDependencies(), - builder: (context, snapshot) { - if (snapshot.hasData) { - final dependenciesPresent = snapshot.data!; - if (dependenciesPresent) { - // Slight delay required so we don't push the main - // screen while the build method is still executing. - Future.microtask(() { - Navigator.pushReplacementNamed(context, AppsPage.id); - }); - } else { + return BlocProvider( + create: (context) => LoadingCubit(), + lazy: false, + child: Scaffold( + body: Center( + child: BlocConsumer( + listener: (context, state) { + if (state is LoadingSuccess) { + Navigator.pushReplacementNamed(context, AppsPage.id); + } + }, + builder: (context, state) { + if (state is LoadingFailed) { return Card( child: Container( padding: const EdgeInsets.all(20.0), @@ -49,16 +37,14 @@ Dependency check failed. Please make sure you have installed Nyrna's dependencies. (On Linux this would be wmctrl and xdotool) - '''), + '''), ), ); + } else { + return const CircularProgressIndicator(); } - } else if (snapshot.hasError) { - print('Error: ${snapshot.error}'); - return Text('Error: ${snapshot.error}'); - } - return const CircularProgressIndicator(); - }, + }, + ), ), ), ); diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index bcddeee5..c78b9d4e 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -2,17 +2,15 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/app/cubit/app_cubit.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/globals.dart'; import 'package:nyrna/presentation/core/core.dart'; -import 'package:nyrna/nyrna.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/presentation/logs/logs.dart'; -import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../../../settings/launcher.dart'; - /// Screen with configuration settings for Nyrna. class PreferencesPage extends StatefulWidget { static const id = 'settings_screen'; @@ -22,8 +20,6 @@ class PreferencesPage extends StatefulWidget { } class _PreferencesPageState extends State { - late Nyrna nyrna; - final _divider = const Divider( indent: 20, endIndent: 20, @@ -62,12 +58,6 @@ class _PreferencesPageState extends State { }, ); - @override - void didChangeDependencies() { - super.didChangeDependencies(); - nyrna = Provider.of(context, listen: false); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -94,9 +84,8 @@ class _PreferencesPageState extends State { trailing: Switch( value: settings.autoRefresh, onChanged: (value) { - setState(() { - settings.autoRefresh = value; - nyrna.setRefresh(); + setState(() async { + await appCubit.updateAutoRefresh(value); }); }, ), @@ -189,7 +178,7 @@ class _PreferencesPageState extends State { final newInterval = int.tryParse(result); if (newInterval == null) return; setState(() => settings.refreshInterval = newInterval); - nyrna.setRefresh(); + await appCubit.updateAutoRefresh(); } // Future _pickIconColor() async { @@ -267,7 +256,10 @@ void _confirmAddToLauncher(BuildContext context) { child: const Text('Cancel'), ), TextButton( - onPressed: () => Launcher.add(context), + onPressed: () async { + await preferencesCubit.createLauncher(); + Navigator.pop(context); + }, child: const Text('Continue'), ), ], From 09ff684368229aa5a4c4fcaeb98c9382641b7b3a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 24 Jul 2021 12:40:06 -0400 Subject: [PATCH 14/83] Refactor update check to cubit & infrastructure --- lib/application/app/cubit/app_cubit.dart | 24 +++++++ lib/application/app/cubit/app_state.dart | 35 ++++++++-- .../preferences/cubit/preferences_cubit.dart | 6 ++ lib/globals.dart | 5 -- .../preferences/preferences.dart | 40 ++---------- lib/infrastructure/versions/versions.dart | 64 +++++++++++++++++++ lib/main.dart | 1 + lib/presentation/app/pages/apps_page.dart | 46 ++++++------- .../preferences/pages/preferences_page.dart | 16 ++--- lib/settings/update_notifier.dart | 41 ------------ pubspec.lock | 14 ++++ pubspec.yaml | 3 + test/settings/update_notifier_test.dart | 30 --------- 13 files changed, 174 insertions(+), 151 deletions(-) delete mode 100644 lib/globals.dart create mode 100644 lib/infrastructure/versions/versions.dart delete mode 100644 lib/settings/update_notifier.dart delete mode 100644 test/settings/update_notifier_test.dart diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index 1b71b8af..8c2d9d52 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -5,7 +5,9 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; +import 'package:nyrna/infrastructure/versions/versions.dart'; import 'package:nyrna/window/window.dart'; +import 'package:url_launcher/url_launcher.dart'; part 'app_state.dart'; @@ -27,6 +29,7 @@ class AppCubit extends Cubit { Future _initialize() async { _setAutoRefresh(); await _fetchDesktop(); + await _fetchVersionData(); } Timer? _timer; @@ -80,4 +83,25 @@ class AppCubit extends Cubit { }); emit(state.copyWith(windows: windows)); } + + Future _fetchVersionData() async { + final versionRepo = Versions(); + final runningVersion = await versionRepo.runningVersion(); + final latestVersion = await versionRepo.latestVersion(); + final ignoredUpdate = Preferences.instance.getString('ignoredUpdate'); + final updateHasBeenIgnored = (latestVersion == ignoredUpdate); + final updateAvailable = + (updateHasBeenIgnored) ? false : await versionRepo.updateAvailable(); + emit(state.copyWith( + runningVersion: runningVersion, + updateVersion: latestVersion, + updateAvailable: updateAvailable, + )); + } + + Future launchURL(String url) async { + await canLaunch(url) + ? await launch(url) + : throw 'Could not launch url: $url'; + } } diff --git a/lib/application/app/cubit/app_state.dart b/lib/application/app/cubit/app_state.dart index ff2202ce..b1a7b91a 100644 --- a/lib/application/app/cubit/app_state.dart +++ b/lib/application/app/cubit/app_state.dart @@ -1,34 +1,55 @@ part of 'app_cubit.dart'; class AppState extends Equatable { + final String runningVersion; + final String updateVersion; + final bool updateAvailable; + /// The index of the currently active virtual desktop. final int currentDesktop; final Map windows; - const AppState._internal({ + const AppState({ + required this.runningVersion, + required this.updateVersion, + required this.updateAvailable, required this.currentDesktop, required this.windows, }); factory AppState.initial() { - return AppState._internal( + return AppState( + runningVersion: '', + updateVersion: '', + updateAvailable: false, currentDesktop: 0, windows: {}, ); } @override - List get props => [ - currentDesktop, - windows, - ]; + List get props { + return [ + runningVersion, + updateVersion, + updateAvailable, + currentDesktop, + windows, + ]; + } AppState copyWith({ + String? runningVersion, + String? updateVersion, + bool? updateAvailable, int? currentDesktop, Map? windows, }) { - return AppState._internal( + return AppState( + runningVersion: runningVersion ?? this.runningVersion, + updateVersion: updateVersion ?? this.updateVersion, + updateAvailable: updateAvailable ?? this.updateAvailable, currentDesktop: currentDesktop ?? this.currentDesktop, windows: windows ?? this.windows, ); diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index f3e4d108..b7699637 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -1,6 +1,7 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:nyrna/infrastructure/launcher/launcher.dart'; +import 'package:nyrna/infrastructure/preferences/preferences.dart'; part 'preferences_state.dart'; @@ -14,4 +15,9 @@ class PreferencesCubit extends Cubit { Future createLauncher() async { await Launcher.add(); } + + /// If user wishes to ignore this update, save to SharedPreferences. + Future ignoreUpdate(String version) async { + await Preferences.instance.setString(key: 'ignoredUpdate', value: version); + } } diff --git a/lib/globals.dart b/lib/globals.dart deleted file mode 100644 index 4e72842a..00000000 --- a/lib/globals.dart +++ /dev/null @@ -1,5 +0,0 @@ -/// Globally accessible variables. -class Globals { - /// Nyrna's current running version. - static String version = ''; -} diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index 1815643f..310340fd 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -1,9 +1,6 @@ import 'dart:io'; -import 'package:logging/logging.dart'; import 'package:nyrna/application/theme/enums/app_theme.dart'; -import 'package:nyrna/config.dart'; -import 'package:nyrna/globals.dart'; import 'package:shared_preferences/shared_preferences.dart'; /// Manages settings & preferences. @@ -12,8 +9,6 @@ class Preferences { Preferences._privateConstructor(); static final Preferences instance = Preferences._privateConstructor(); - static final _log = Logger('Settings'); - /// Instance of SharedPreferences for getting and setting preferences. SharedPreferences? prefs; @@ -21,39 +16,16 @@ class Preferences { Future initialize() async { if (prefs != null) return; prefs = await SharedPreferences.getInstance(); - if (!Config.toggle) await _readVersion(); // Not needed for toggle func. } - /// Read Nyrna's version info from the `VERSION` file. - Future _readVersion() async { - File? file; - try { - file = File('VERSION'); - } catch (e) { - _log.info('No VERSION file found in current directory.\n' - '$e'); - } - if (Platform.isLinux && file == null) { - // This is necessary for AppImage, because it runs in a temp folder. - // Gets the path to the running executable, then read the VERSION - // file that is in that directory. - final nyrnaPath = Platform.resolvedExecutable; - final splitPath = nyrnaPath.split(''); - final lastSeperator = splitPath.lastIndexOf('/'); - final path = splitPath.sublist(0, lastSeperator).join(); - file = File('$path/VERSION'); - } else { - file = File('VERSION'); - } - final exists = await file.exists(); - if (exists) { - final version = await file.readAsString(); - Globals.version = version.trim(); - } else { - Globals.version = 'Unknown'; - } + Future setString({required String key, required String value}) async { + assert(key != ''); + assert(value != ''); + await prefs?.setString(key, value); } + String? getString(String key) => prefs?.getString(key); + /// Whether or not to automatically refresh the list of open windows. bool get autoRefresh { bool defaultValue; diff --git a/lib/infrastructure/versions/versions.dart b/lib/infrastructure/versions/versions.dart new file mode 100644 index 00000000..695a6976 --- /dev/null +++ b/lib/infrastructure/versions/versions.dart @@ -0,0 +1,64 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart' show rootBundle; +import 'package:pub_semver/pub_semver.dart' as semver; +import 'package:yaml/yaml.dart'; +import 'package:http/http.dart' as http; + +/// Check app versions. +class Versions { + String _runningVersion = ''; + + /// The application's version as read from pubspec.yaml, + /// in the format of `1.0.0`. + Future runningVersion() async { + if (_runningVersion == '') { + final rawVersion = await _readVersion(); + // Remove the `+xx` that indicates the Android build number. + _runningVersion = rawVersion.split('+').first; + } + return _runningVersion; + } + + /// Reads the pubspec.yaml included in the assets and extracts + /// the version string. + Future _readVersion() async { + final pubspec = await rootBundle.loadString('pubspec.yaml'); + final yaml = loadYaml(pubspec); + final rawVersion = yaml['version'] as String; + return rawVersion; + } + + Future updateAvailable() async { + final current = semver.Version.parse(await runningVersion()); + final latest = semver.Version.parse(await latestVersion()); + return (current < latest) ? true : false; + } + + String _latestVersion = ''; + + /// Checks the latest GitHub tag. + Future latestVersion() async { + if (_latestVersion != '') return _latestVersion; + final uri = Uri.parse( + 'https://api.github.com/repos/merrit/nyrna/releases', + ); + final response = await http.get( + uri, + headers: {'Accept': 'application/vnd.github.v3+json'}, + ); + if (response.statusCode == 200) { + final json = jsonDecode(response.body) as List; + final data = List.from(json); + final tag = data.firstWhere((element) => element['prerelease'] == false); + final tagName = tag['tag_name'] as String; + // Strip the leading `v` and anything trailing. + // May need to be updated if we starting using postfixes like `beta`. + _latestVersion = tagName.substring(1, 6); + } else { + print('Issue getting latest version info from GitHub, ' + 'status code: ${response.statusCode}\n'); + } + return _latestVersion; + } +} diff --git a/lib/main.dart b/lib/main.dart index 40575613..d6d36dc5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,6 +33,7 @@ Future main(List args) async { ), BlocProvider( create: (context) => PreferencesCubit(), + lazy: false, ), BlocProvider( create: (context) => ThemeCubit(), diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 85fd3801..492f1b43 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -4,13 +4,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/app/widgets/window_tile.dart'; -import 'package:nyrna/globals.dart'; import 'package:nyrna/process/process.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/settings/update_notifier.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -25,9 +24,6 @@ class AppsPage extends StatefulWidget { } class _AppsPageState extends State { - /// Whether or not a newer version of Nyrna is available. - Future updateAvailable = UpdateNotifier().updateAvailable(); - static final _log = Logger('RunningAppsScreen'); final _settings = Preferences.instance; @@ -104,32 +100,30 @@ class _AppsPageState extends State { } /// Show an icon if a newer version of Nyrna is available. - FutureBuilder _updateIcon() { - return FutureBuilder( - future: updateAvailable, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return snapshot.data! - ? IconButton( - icon: Icon( - Icons.notifications_active, - color: Colors.pink[400], - ), - onPressed: () => _showUpdateDialog(), - ) - : Container(); - } - return Container(); - }); + Widget _updateIcon() { + return BlocBuilder( + builder: (context, state) { + return state.updateAvailable + ? IconButton( + icon: Icon( + Icons.notifications_active, + color: Colors.pink[400], + ), + onPressed: () => _showUpdateDialog(), + ) + : Container(); + }, + ); } /// Inform user about new version of Nyrna, download link, etc. Future _showUpdateDialog() async { - final notifier = UpdateNotifier(); - final latestVersion = await notifier.latestVersion(); + final state = appCubit.state; + final currentVersion = state.runningVersion; + final latestVersion = state.updateVersion; const url = 'https://nyrna.merritt.codes/download'; var _message = 'An update for Nyrna is available!\n\n' - 'Current version: ${Globals.version}\n' + 'Current version: $currentVersion\n' 'Latest version: $latestVersion'; await showDialog( context: context, @@ -150,7 +144,7 @@ class _AppsPageState extends State { ), TextButton( onPressed: () { - notifier.ignoreVersion(latestVersion); + preferencesCubit.ignoreUpdate(latestVersion); setState(() { Navigator.pushReplacementNamed(context, AppsPage.id); }); diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index c78b9d4e..d7a5d7df 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -5,7 +5,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/app/cubit/app_cubit.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/globals.dart'; import 'package:nyrna/presentation/core/core.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/presentation/logs/logs.dart'; @@ -139,14 +138,15 @@ class _PreferencesPageState extends State { ), _sectionPadding, Text('About'), - // Hide version if `VERSION` file not found. - // Definitely the case for the Snap version on Linux. - if (Globals.version != 'Unknown') - ListTile( - leading: const Icon(Icons.info_outline), - title: Text('Nyrna version'), - subtitle: Text(Globals.version), + ListTile( + leading: const Icon(Icons.info_outline), + title: Text('Nyrna version'), + subtitle: BlocBuilder( + builder: (context, state) { + return Text(state.runningVersion); + }, ), + ), ListTile( leading: const Icon(Icons.launch), title: Text('Nyrna homepage'), diff --git a/lib/settings/update_notifier.dart b/lib/settings/update_notifier.dart deleted file mode 100644 index 0c46d2b2..00000000 --- a/lib/settings/update_notifier.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:http/http.dart' as http; -import 'package:nyrna/globals.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; - -/// Check if updates to Nyrna are available. -class UpdateNotifier { - final _settings = Preferences.instance; - - /// If update is available returns true. - Future updateAvailable() async { - if (!_shouldCheck()) return false; - final latest = await latestVersion(); - if (latest == '') return false; - if (_settings.ignoredUpdate == latest) return false; - return (Globals.version == latest) ? false : true; - } - - /// Only check for update once a day. - bool _shouldCheck() { - final savedCheck = _settings.prefs!.getString('checkedUpdate'); - if (savedCheck == null) return true; - final lastChecked = DateTime.tryParse(savedCheck); - if (lastChecked == null) return true; - final timestamp = DateTime.now(); - // Add 1 day to the saved timestamp, check if 1 day has passed. - return timestamp.isAfter(lastChecked.add(Duration(days: 1))); - } - - /// Checks the VERSION file at GitHub to get the latest version number. - Future latestVersion() async { - final uri = - Uri.https('raw.githubusercontent.com', '/Merrit/nyrna/master/VERSION'); - final result = await http.read(uri); - return result.trim(); - } - - /// If user wishes to ignore this update, save to SharedPreferences. - void ignoreVersion(String version) { - _settings.prefs!.setString('ignoredUpdate', version); - } -} diff --git a/pubspec.lock b/pubspec.lock index a1f3f3ab..4f631bc9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -269,6 +269,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" + pub_semver: + dependency: "direct main" + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" shared_preferences: dependency: "direct main" description: @@ -456,6 +463,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" + yaml: + dependency: "direct main" + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" sdks: dart: ">=2.13.0 <3.0.0" flutter: ">=1.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index c5e572e6..9b02b51e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,10 +17,12 @@ dependencies: logging: ^1.0.1 path_provider: ^2.0.1 provider: ^5.0.0 + pub_semver: ^2.0.0 shared_preferences: ^2.0.5 url_launcher: ^6.0.4 win32: ^2.1.1 win32_suspend_process: ^1.0.0 + yaml: ^3.1.0 dev_dependencies: flutter_test: @@ -33,3 +35,4 @@ flutter: uses-material-design: true assets: - assets/icons/ + - pubspec.yaml diff --git a/test/settings/update_notifier_test.dart b/test/settings/update_notifier_test.dart deleted file mode 100644 index 8694af44..00000000 --- a/test/settings/update_notifier_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/globals.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/settings/update_notifier.dart'; - -void main() { - Preferences? _settings; - - setUp(() async { - _settings = Preferences.instance; - await _settings!.initialize(); - }); - - tearDown(() { - _settings = null; - }); - - test('Current version being old returns true', () async { - Globals.version = '1.0'; - final updateAvailable = await UpdateNotifier().updateAvailable(); - expect(updateAvailable, true); - }); - - test('Current version matching latest returns false', () async { - final notifier = UpdateNotifier(); - Globals.version = await notifier.latestVersion(); - final updateAvailable = await notifier.updateAvailable(); - expect(updateAvailable, false); - }); -} From 4a5a0a59111cf020d2c7b3cf28e2767ac92ba066 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 24 Jul 2021 14:35:39 -0400 Subject: [PATCH 15/83] Refactor config --- .../active_window/active_window.dart | 9 ++++--- lib/config.dart | 9 ------- lib/domain/arguments/argument_parser.dart | 24 +++++++++---------- lib/infrastructure/logger/log_file.dart | 13 ++++------ lib/main.dart | 3 +-- test/arguments/argument_parser_test.dart | 22 +++++++---------- 6 files changed, 30 insertions(+), 50 deletions(-) delete mode 100644 lib/config.dart diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 95e644d2..505abe51 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -2,6 +2,7 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; +import 'package:nyrna/domain/arguments/argument_parser.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/process/process.dart'; @@ -9,8 +10,6 @@ import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; -import '../../config.dart'; - /// Represents the active, foreground window on the system. /// /// Initialize() must be called before anything else. @@ -76,7 +75,7 @@ class ActiveWindow { // just not running the GUI for now. Sanity check: don't suspend self. if (pid == nyrnaPid) { _log.severe("Active window PID was Nyrna's own, exiting."); - await LogFile.instance.write(); + if (ArgumentParser.logToFile) await LogFile.instance.write(); io.exit(1); } if (_settings.savedProcess != 0) await _checkStillExists(); @@ -90,7 +89,7 @@ class ActiveWindow { if (!exists) { await _removeSavedProcess(); _log.warning('Saved pid no longer exists, removed.'); - await LogFile.instance.write(); + if (ArgumentParser.logToFile) await LogFile.instance.write(); io.exit(0); } } @@ -163,7 +162,7 @@ class ActiveWindow { _log.warning('Failed to toggle active window. Cleared saved pid.'); } _log.info('Finished toggle window, exiting.'); - if (Config.log) await LogFile.instance.write(); + if (ArgumentParser.logToFile) await LogFile.instance.write(); // Not yet possible to run without GUI, so we just exit after toggling. io.exit(0); } diff --git a/lib/config.dart b/lib/config.dart deleted file mode 100644 index de10f3c4..00000000 --- a/lib/config.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// Run-time environmental variables. -class Config { - /// If toggle is true => toggle suspend for active window, - /// do not load GUI. - static bool toggle = false; - - /// If true, enable logging functionality. - static bool log = false; -} diff --git a/lib/domain/arguments/argument_parser.dart b/lib/domain/arguments/argument_parser.dart index 745552e8..71f67395 100644 --- a/lib/domain/arguments/argument_parser.dart +++ b/lib/domain/arguments/argument_parser.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:args/args.dart'; -import 'package:nyrna/config.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; /// Parse command-line arguments. @@ -42,7 +41,6 @@ class ArgumentParser { Future parse() async { _parseArgs(); - _checkToggleFlag(); await _checkLogFlag(); } @@ -57,20 +55,22 @@ class ArgumentParser { } /// Check if `toggle` flag was received. - void _checkToggleFlag() { - final toggle = _results.wasParsed('toggle'); - if (toggle) Config.toggle = true; - } + /// + /// If toggle is true => toggle suspend for active window, + /// do not load GUI. + bool get toggleFlagged => _results.wasParsed('toggle'); + + static bool _logToFile = false; + + static bool get logToFile => _logToFile; /// Check if `log` flag was received. Future _checkLogFlag() async { - final logger = _results.wasParsed('log'); - if (logger) { - // Set environment variable. - Config.log = true; + final flagReceived = _results.wasParsed('log'); + if (flagReceived) { + _logToFile = true; // One-time initialization of the logger. - final logFile = LogFile.instance; - await logFile.init(); + await LogFile.instance.init(); } } } diff --git a/lib/infrastructure/logger/log_file.dart b/lib/infrastructure/logger/log_file.dart index 7439c689..50c44d79 100644 --- a/lib/infrastructure/logger/log_file.dart +++ b/lib/infrastructure/logger/log_file.dart @@ -1,7 +1,6 @@ import 'dart:collection'; import 'dart:io'; import 'package:logging/logging.dart'; -import 'package:nyrna/config.dart'; import 'package:path_provider/path_provider.dart' as p; /// Log debug messages to a temp file. @@ -50,12 +49,10 @@ class LogFile { /// Flush the log to ensure it has been written to disk before exiting. Future write() async { - if (Config.log) { - await _logFile!.writeAsString( - logs.toString(), - mode: FileMode.append, - flush: true, - ); - } + await _logFile!.writeAsString( + logs.toString(), + mode: FileMode.append, + flush: true, + ); } } diff --git a/lib/main.dart b/lib/main.dart index d6d36dc5..dc70fdb9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:nyrna/config.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; @@ -22,7 +21,7 @@ Future main(List args) async { AppLogger().initialize(); // `-t` or `--toggle` flag detected. - if (Config.toggle) await ActiveWindow().toggle(); + if (parser.toggleFlagged) await ActiveWindow().toggle(); runApp( MultiBlocProvider( diff --git a/test/arguments/argument_parser_test.dart b/test/arguments/argument_parser_test.dart index e720f0b9..ec987938 100644 --- a/test/arguments/argument_parser_test.dart +++ b/test/arguments/argument_parser_test.dart @@ -1,29 +1,23 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/config.dart'; import 'package:nyrna/domain/arguments/argument_parser.dart'; void main() { - setUp(() { - Config.log = false; - Config.toggle = false; - }); - test('With no flags log is false', () async { final parser = ArgumentParser([]); await parser.parse(); - expect(Config.log, false); + expect(parser.toggleFlagged, false); }); test('Config.log is true with -l flag', () async { final parser = ArgumentParser(['-l']); await parser.parse(); - expect(Config.log, true); + expect(ArgumentParser.logToFile, true); }); test('Config.log is true with --log flag', () async { final parser = ArgumentParser(['--log']); await parser.parse(); - expect(Config.log, true); + expect(ArgumentParser.logToFile, true); }); test( @@ -31,7 +25,7 @@ void main() { () async { final parser = ArgumentParser([]); await parser.parse(); - expect(Config.toggle, false); + expect(parser.toggleFlagged, false); }, ); test( @@ -39,7 +33,7 @@ void main() { () async { final parser = ArgumentParser(['--toggle']); await parser.parse(); - expect(Config.toggle, true); + expect(parser.toggleFlagged, true); }, ); @@ -48,7 +42,7 @@ void main() { () async { final parser = ArgumentParser(['-t']); await parser.parse(); - expect(Config.toggle, true); + expect(parser.toggleFlagged, true); }, ); @@ -57,8 +51,8 @@ void main() { () async { final parser = ArgumentParser(['-tl']); await parser.parse(); - expect(Config.toggle, true); - expect(Config.log, true); + expect(parser.toggleFlagged, true); + expect(ArgumentParser.logToFile, true); }, ); } From 94bf79a80b4110975de77bdbce4054aa9cc9c173 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:12:58 -0400 Subject: [PATCH 16/83] Refactor Process to infrastructure --- .../active_window/active_window.dart | 2 +- .../native_platform/native_platform.dart | 39 +------------------ .../{ => src}/linux/linux.dart | 3 +- .../src/linux}/linux_process.dart | 3 +- .../native_platform/src/native_platform.dart | 37 ++++++++++++++++++ .../native_platform/src}/process.dart | 5 ++- .../{ => src}/win32/ffi/dwmapi.dart | 0 .../{ => src}/win32/ffi/user32.dart | 0 .../{ => src}/win32/win32.dart | 4 +- .../src/win32}/win32_process.dart | 3 +- lib/presentation/app/pages/apps_page.dart | 2 +- lib/presentation/app/widgets/window_tile.dart | 8 ++-- test/process/process_test.dart | 2 +- 13 files changed, 59 insertions(+), 49 deletions(-) rename lib/infrastructure/native_platform/{ => src}/linux/linux.dart (97%) rename lib/{process => infrastructure/native_platform/src/linux}/linux_process.dart (97%) create mode 100644 lib/infrastructure/native_platform/src/native_platform.dart rename lib/{process => infrastructure/native_platform/src}/process.dart (92%) rename lib/infrastructure/native_platform/{ => src}/win32/ffi/dwmapi.dart (100%) rename lib/infrastructure/native_platform/{ => src}/win32/ffi/user32.dart (100%) rename lib/infrastructure/native_platform/{ => src}/win32/win32.dart (98%) rename lib/{process => infrastructure/native_platform/src/win32}/win32_process.dart (98%) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 505abe51..1e4af955 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -5,8 +5,8 @@ import 'package:logging/logging.dart'; import 'package:nyrna/domain/arguments/argument_parser.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:nyrna/process/process.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; +import 'package:nyrna/infrastructure/native_platform/src/process.dart'; import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; diff --git a/lib/infrastructure/native_platform/native_platform.dart b/lib/infrastructure/native_platform/native_platform.dart index 28f18703..fe4f7bf8 100644 --- a/lib/infrastructure/native_platform/native_platform.dart +++ b/lib/infrastructure/native_platform/native_platform.dart @@ -1,37 +1,2 @@ -import 'dart:io'; - -import 'package:nyrna/infrastructure/native_platform/linux/linux.dart'; -import 'package:nyrna/window/window.dart'; - -import 'win32/win32.dart'; - -/// Interact with the native operating system. -/// -/// Abstract class bridges types for specific operating systems. -/// Used by [Linux] and [Win32]. -abstract class NativePlatform { - // Return correct subtype depending on the current operating system. - factory NativePlatform() { - if (Platform.isLinux) { - return Linux(); - } else { - return Win32(); - } - } - - /// Returns the index of the currently active virtual desktop. - Future get currentDesktop; - - /// Returns a Map where the keys are the `pid` and the values are [Window] - /// objects, based on the reported open application windows. - Future> get windows; - - /// Returns the pid associated with the active window. - Future get activeWindowPid; - - /// Returns the unique hex id for the active window. - Future get activeWindowId; - - /// Verify dependencies are present on the system. - Future checkDependencies(); -} +export 'src/native_platform.dart'; +export 'src/process.dart'; diff --git a/lib/infrastructure/native_platform/linux/linux.dart b/lib/infrastructure/native_platform/src/linux/linux.dart similarity index 97% rename from lib/infrastructure/native_platform/linux/linux.dart rename to lib/infrastructure/native_platform/src/linux/linux.dart index ad1cf6aa..d04ee67f 100644 --- a/lib/infrastructure/native_platform/linux/linux.dart +++ b/lib/infrastructure/native_platform/src/linux/linux.dart @@ -1,8 +1,9 @@ import 'dart:io'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/window/window.dart'; +import '../native_platform.dart'; + /// Interact with the native Linux operating system. class Linux implements NativePlatform { int? _desktop; diff --git a/lib/process/linux_process.dart b/lib/infrastructure/native_platform/src/linux/linux_process.dart similarity index 97% rename from lib/process/linux_process.dart rename to lib/infrastructure/native_platform/src/linux/linux_process.dart index 73b54940..461601c1 100644 --- a/lib/process/linux_process.dart +++ b/lib/infrastructure/native_platform/src/linux/linux_process.dart @@ -1,7 +1,8 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; -import 'package:nyrna/process/process.dart'; + +import '../process.dart'; class LinuxProcess with ChangeNotifier implements Process { LinuxProcess(this.pid); diff --git a/lib/infrastructure/native_platform/src/native_platform.dart b/lib/infrastructure/native_platform/src/native_platform.dart new file mode 100644 index 00000000..4b8a9d16 --- /dev/null +++ b/lib/infrastructure/native_platform/src/native_platform.dart @@ -0,0 +1,37 @@ +import 'dart:io'; + +import 'package:nyrna/window/window.dart'; + +import 'linux/linux.dart'; +import 'win32/win32.dart'; + +/// Interact with the native operating system. +/// +/// Abstract class bridges types for specific operating systems. +/// Used by [Linux] and [Win32]. +abstract class NativePlatform { + // Return correct subtype depending on the current operating system. + factory NativePlatform() { + if (Platform.isLinux) { + return Linux(); + } else { + return Win32(); + } + } + + /// Returns the index of the currently active virtual desktop. + Future get currentDesktop; + + /// Returns a Map where the keys are the `pid` and the values are [Window] + /// objects, based on the reported open application windows. + Future> get windows; + + /// Returns the pid associated with the active window. + Future get activeWindowPid; + + /// Returns the unique hex id for the active window. + Future get activeWindowId; + + /// Verify dependencies are present on the system. + Future checkDependencies(); +} diff --git a/lib/process/process.dart b/lib/infrastructure/native_platform/src/process.dart similarity index 92% rename from lib/process/process.dart rename to lib/infrastructure/native_platform/src/process.dart index de97355f..7d378cf1 100644 --- a/lib/process/process.dart +++ b/lib/infrastructure/native_platform/src/process.dart @@ -1,8 +1,9 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; -import 'package:nyrna/process/linux_process.dart'; -import 'package:nyrna/process/win32_process.dart'; + +import 'linux/linux_process.dart'; +import 'win32/win32.dart'; /// Represents the running state of a process. enum ProcessStatus { diff --git a/lib/infrastructure/native_platform/win32/ffi/dwmapi.dart b/lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart similarity index 100% rename from lib/infrastructure/native_platform/win32/ffi/dwmapi.dart rename to lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart diff --git a/lib/infrastructure/native_platform/win32/ffi/user32.dart b/lib/infrastructure/native_platform/src/win32/ffi/user32.dart similarity index 100% rename from lib/infrastructure/native_platform/win32/ffi/user32.dart rename to lib/infrastructure/native_platform/src/win32/ffi/user32.dart diff --git a/lib/infrastructure/native_platform/win32/win32.dart b/lib/infrastructure/native_platform/src/win32/win32.dart similarity index 98% rename from lib/infrastructure/native_platform/win32/win32.dart rename to lib/infrastructure/native_platform/src/win32/win32.dart index 5c39170e..90b1f7ba 100644 --- a/lib/infrastructure/native_platform/win32/win32.dart +++ b/lib/infrastructure/native_platform/src/win32/win32.dart @@ -1,13 +1,15 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import 'package:nyrna/process/win32_process.dart'; // import 'package:nyrna/platform/win32/user32.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/window/window.dart'; import 'package:win32/win32.dart'; import 'ffi/dwmapi.dart'; +import 'win32_process.dart'; + +export 'win32_process.dart'; /// Interact with the native win32 operating system. /// diff --git a/lib/process/win32_process.dart b/lib/infrastructure/native_platform/src/win32/win32_process.dart similarity index 98% rename from lib/process/win32_process.dart rename to lib/infrastructure/native_platform/src/win32/win32_process.dart index 583bb982..802dace5 100644 --- a/lib/process/win32_process.dart +++ b/lib/infrastructure/native_platform/src/win32/win32_process.dart @@ -4,10 +4,11 @@ import 'dart:io' as io; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import 'package:nyrna/process/process.dart'; import 'package:win32/win32.dart'; import 'package:win32_suspend_process/win32_suspend_process.dart' as w32proc; +import '../process.dart'; + class Win32Process with ChangeNotifier implements Process { Win32Process(this.pid); diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 492f1b43..b664abfb 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -7,8 +7,8 @@ import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/app/widgets/window_tile.dart'; -import 'package:nyrna/process/process.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/lib/presentation/app/widgets/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart index 0ec22c9d..625d856b 100644 --- a/lib/presentation/app/widgets/window_tile.dart +++ b/lib/presentation/app/widgets/window_tile.dart @@ -1,7 +1,7 @@ -import 'dart:io'; +import 'dart:io' as io; import 'package:flutter/material.dart'; -import 'package:nyrna/process/process.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/window/window.dart'; import 'package:provider/provider.dart'; @@ -104,7 +104,9 @@ class _WindowTileState extends State { await window!.minimize(); // Small delay on Win32 to ensure the window actually minimizes. // Doesn't seem to be necessary on Linux. - if (Platform.isWindows) await Future.delayed(Duration(milliseconds: 500)); + if (io.Platform.isWindows) { + await Future.delayed(Duration(milliseconds: 500)); + } final successful = await process.toggle(); if (!successful) await _showSnackError(_ToggleError.Suspend); } diff --git a/test/process/process_test.dart b/test/process/process_test.dart index 194bf2f5..12d1080f 100644 --- a/test/process/process_test.dart +++ b/test/process/process_test.dart @@ -1,7 +1,7 @@ import 'dart:io' as io; import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/process/process.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; void main() { final pid = io.pid; // Dart or Nyrna's own pid. From e957ffd822dbac7b5f9ab6f450d9c6d91f1f8ea4 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:22:11 -0400 Subject: [PATCH 17/83] Move Window class to native_platform --- .../active_window/active_window.dart | 1 - lib/application/app/cubit/app_cubit.dart | 1 - .../native_platform/native_platform.dart | 1 + .../native_platform/src/linux/linux.dart | 3 +- .../src/linux/linux_window.dart | 22 +++++++++ .../native_platform/src/native_platform.dart | 2 +- .../native_platform/src/win32/win32.dart | 1 - .../src/win32/win32_window.dart | 12 +++++ .../native_platform/src}/window.dart | 22 ++++++++- lib/presentation/app/widgets/window_tile.dart | 1 - lib/window/window_controls.dart | 48 ------------------- 11 files changed, 58 insertions(+), 56 deletions(-) create mode 100644 lib/infrastructure/native_platform/src/linux/linux_window.dart create mode 100644 lib/infrastructure/native_platform/src/win32/win32_window.dart rename lib/{window => infrastructure/native_platform/src}/window.dart (58%) delete mode 100644 lib/window/window_controls.dart diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 1e4af955..f4c3db1c 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -7,7 +7,6 @@ import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/infrastructure/native_platform/src/process.dart'; -import 'package:nyrna/window/window_controls.dart'; import 'package:win32/win32.dart'; /// Represents the active, foreground window on the system. diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index 8c2d9d52..6c3815d8 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -6,7 +6,6 @@ import 'package:equatable/equatable.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/infrastructure/versions/versions.dart'; -import 'package:nyrna/window/window.dart'; import 'package:url_launcher/url_launcher.dart'; part 'app_state.dart'; diff --git a/lib/infrastructure/native_platform/native_platform.dart b/lib/infrastructure/native_platform/native_platform.dart index fe4f7bf8..f8f8bffe 100644 --- a/lib/infrastructure/native_platform/native_platform.dart +++ b/lib/infrastructure/native_platform/native_platform.dart @@ -1,2 +1,3 @@ export 'src/native_platform.dart'; export 'src/process.dart'; +export 'src/window.dart'; diff --git a/lib/infrastructure/native_platform/src/linux/linux.dart b/lib/infrastructure/native_platform/src/linux/linux.dart index d04ee67f..735a6b13 100644 --- a/lib/infrastructure/native_platform/src/linux/linux.dart +++ b/lib/infrastructure/native_platform/src/linux/linux.dart @@ -1,8 +1,7 @@ import 'dart:io'; -import 'package:nyrna/window/window.dart'; - import '../native_platform.dart'; +import '../window.dart'; /// Interact with the native Linux operating system. class Linux implements NativePlatform { diff --git a/lib/infrastructure/native_platform/src/linux/linux_window.dart b/lib/infrastructure/native_platform/src/linux/linux_window.dart new file mode 100644 index 00000000..628b7f58 --- /dev/null +++ b/lib/infrastructure/native_platform/src/linux/linux_window.dart @@ -0,0 +1,22 @@ +import 'dart:io'; + +import '../window.dart'; + +/// Linux specific window controls using `xdotool`. +class LinuxWindowControls implements WindowControls { + @override + Future minimize(int? id) async { + await Process.run( + 'xdotool', + ['windowminimize', '$id', '--sync'], + ); + } + + @override + Future restore(int? id) async { + await Process.run( + 'xdotool', + ['windowactivate', '$id', '--sync'], + ); + } +} diff --git a/lib/infrastructure/native_platform/src/native_platform.dart b/lib/infrastructure/native_platform/src/native_platform.dart index 4b8a9d16..a71c5145 100644 --- a/lib/infrastructure/native_platform/src/native_platform.dart +++ b/lib/infrastructure/native_platform/src/native_platform.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:nyrna/window/window.dart'; +import 'package:nyrna/infrastructure/native_platform/src/window.dart'; import 'linux/linux.dart'; import 'win32/win32.dart'; diff --git a/lib/infrastructure/native_platform/src/win32/win32.dart b/lib/infrastructure/native_platform/src/win32/win32.dart index 90b1f7ba..741ff79c 100644 --- a/lib/infrastructure/native_platform/src/win32/win32.dart +++ b/lib/infrastructure/native_platform/src/win32/win32.dart @@ -3,7 +3,6 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; // import 'package:nyrna/platform/win32/user32.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:nyrna/window/window.dart'; import 'package:win32/win32.dart'; import 'ffi/dwmapi.dart'; diff --git a/lib/infrastructure/native_platform/src/win32/win32_window.dart b/lib/infrastructure/native_platform/src/win32/win32_window.dart new file mode 100644 index 00000000..62001e31 --- /dev/null +++ b/lib/infrastructure/native_platform/src/win32/win32_window.dart @@ -0,0 +1,12 @@ +import 'package:win32/win32.dart'; + +import '../window.dart'; + +/// Win32 specific window controls using the win32 API. +class Win32WindowControls implements WindowControls { + @override + Future minimize(int? id) async => ShowWindow(id!, SW_FORCEMINIMIZE); + + @override + Future restore(int? id) async => ShowWindow(id!, SW_RESTORE); +} diff --git a/lib/window/window.dart b/lib/infrastructure/native_platform/src/window.dart similarity index 58% rename from lib/window/window.dart rename to lib/infrastructure/native_platform/src/window.dart index cef011a5..bf93553e 100644 --- a/lib/window/window.dart +++ b/lib/infrastructure/native_platform/src/window.dart @@ -1,4 +1,7 @@ -import 'package:nyrna/window/window_controls.dart'; +import 'dart:io'; + +import 'linux/linux_window.dart'; +import 'win32/win32_window.dart'; /// Represents a visible window on the current desktop. class Window { @@ -27,3 +30,20 @@ class Window { /// Restore (un-minimize) this window. Future restore() async => await _windowControls.restore(id); } + +/// Provides window actions like [minimize] & [restore]. +abstract class WindowControls { + factory WindowControls() { + if (Platform.isLinux) { + return LinuxWindowControls(); + } else { + return Win32WindowControls(); + } + } + + /// Minimize the window associated with the given [id]. + Future minimize(int? id); + + /// Restore (un-minimize) the window associated with the given [id]. + Future restore(int? id); +} diff --git a/lib/presentation/app/widgets/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart index 625d856b..371b8ec1 100644 --- a/lib/presentation/app/widgets/window_tile.dart +++ b/lib/presentation/app/widgets/window_tile.dart @@ -2,7 +2,6 @@ import 'dart:io' as io; import 'package:flutter/material.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:nyrna/window/window.dart'; import 'package:provider/provider.dart'; /// Represents a visible window on the desktop, running state and actions. diff --git a/lib/window/window_controls.dart b/lib/window/window_controls.dart deleted file mode 100644 index df850ddf..00000000 --- a/lib/window/window_controls.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:io'; - -import 'package:win32/win32.dart'; - -/// Provides window actions like [minimize] & [restore]. -abstract class WindowControls { - factory WindowControls() { - if (Platform.isLinux) { - return _LinuxWindowControls(); - } else { - return _Win32WindowControls(); - } - } - - /// Minimize the window associated with the given [id]. - Future minimize(int? id); - - /// Restore (un-minimize) the window associated with the given [id]. - Future restore(int? id); -} - -/// Linux specific window controls using `xdotool`. -class _LinuxWindowControls implements WindowControls { - @override - Future minimize(int? id) async { - await Process.run( - 'xdotool', - ['windowminimize', '$id', '--sync'], - ); - } - - @override - Future restore(int? id) async { - await Process.run( - 'xdotool', - ['windowactivate', '$id', '--sync'], - ); - } -} - -/// Win32 specific window controls using the win32 API. -class _Win32WindowControls implements WindowControls { - @override - Future minimize(int? id) async => ShowWindow(id!, SW_FORCEMINIMIZE); - - @override - Future restore(int? id) async => ShowWindow(id!, SW_RESTORE); -} From cfbc384dc3d41bc00354f787950085ee42dac10b Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:24:43 -0400 Subject: [PATCH 18/83] Move icon_manager to infrastructure --- lib/{settings => infrastructure/icon_manager}/icon_manager.dart | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/{settings => infrastructure/icon_manager}/icon_manager.dart (100%) diff --git a/lib/settings/icon_manager.dart b/lib/infrastructure/icon_manager/icon_manager.dart similarity index 100% rename from lib/settings/icon_manager.dart rename to lib/infrastructure/icon_manager/icon_manager.dart From 12d2c38a0ff7994de1812c930fc033cdb835535d Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 09:46:30 -0400 Subject: [PATCH 19/83] Refactor much of Preferences --- .../active_window/active_window.dart | 34 +++++---- lib/application/app/cubit/app_cubit.dart | 29 ++++--- lib/application/app/cubit/app_state.dart | 9 +++ .../preferences/cubit/preferences_cubit.dart | 36 ++++++++- .../preferences/cubit/preferences_state.dart | 28 +++++-- .../preferences/preferences.dart | 69 ++++++----------- lib/main.dart | 2 +- lib/presentation/app/pages/apps_page.dart | 35 +++++---- .../preferences/pages/preferences_page.dart | 76 ++++++++++--------- 9 files changed, 190 insertions(+), 128 deletions(-) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index f4c3db1c..334a2fc6 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -68,6 +68,17 @@ class ActiveWindow { ShowWindow(id, SW_FORCEMINIMIZE); } + int? _getSavedProcess() => Preferences.instance.getInt('savedProcess'); + + Future _setSavedProcess(int pid) async { + await Preferences.instance.setInt(key: 'savedProcess', value: pid); + } + + Future _removeSavedProcess() async { + await Preferences.instance.remove('savedProcess'); + await _settings.setSavedWindowId(0); + } + Future _verifyPid() async { // Verify active window wasn't Nyrna. // This _could_ happen because we have to hide Nyrna's window instead of @@ -77,12 +88,12 @@ class ActiveWindow { if (ArgumentParser.logToFile) await LogFile.instance.write(); io.exit(1); } - if (_settings.savedProcess != 0) await _checkStillExists(); + final savedProcess = _getSavedProcess(); + if (savedProcess != null) await _checkStillExists(savedProcess); } /// Check that saved process still exists. - Future _checkStillExists() async { - final savedPid = _settings.savedProcess; + Future _checkStillExists(int savedPid) async { final savedProcess = Process(savedPid); final exists = await savedProcess.exists(); if (!exists) { @@ -95,8 +106,9 @@ class ActiveWindow { /// Toggle the suspend / resume state of the given process. Future _toggleProcess() async { - if (_settings.savedProcess != 0) { - final successful = await _resume(); + final savedProcess = _getSavedProcess(); + if (savedProcess != null) { + final successful = await _resume(pid: savedProcess); return successful; } else { final successful = await _suspend(); @@ -104,9 +116,10 @@ class ActiveWindow { } } - Future _resume() async { + Future _resume({ + required int pid, + }) async { var successful = false; - pid = _settings.savedProcess; id = _settings.savedWindowId; final process = Process(pid); final _status = await process.status; @@ -126,11 +139,6 @@ class ActiveWindow { return successful; } - Future _removeSavedProcess() async { - await _settings.setSavedProcess(0); - await _settings.setSavedWindowId(0); - } - Future _suspend() async { var successful = false; final process = Process(pid); @@ -141,7 +149,7 @@ class ActiveWindow { await Future.delayed(Duration(milliseconds: 500)); } successful = await process.toggle(); - await _settings.setSavedProcess(pid); + await _setSavedProcess(pid); await _settings.setSavedWindowId(id!); if (!successful) { _log.warning('Failed to suspend PID: $pid'); diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index 6c3815d8..e60980b3 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -3,6 +3,7 @@ import 'dart:io' as io; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/infrastructure/versions/versions.dart'; @@ -26,20 +27,33 @@ class AppCubit extends Cubit { } Future _initialize() async { - _setAutoRefresh(); + await _checkIsPortable(); + setAutoRefresh( + autoRefresh: preferencesCubit.state.autoRefresh, + refreshInterval: preferencesCubit.state.refreshInterval, + ); await _fetchDesktop(); await _fetchVersionData(); } + Future _checkIsPortable() async { + final file = io.File('PORTABLE'); + final isPortable = await file.exists(); + emit(state.copyWith(isPortable: isPortable)); + } + Timer? _timer; /// The timer which auto-refreshes the list of open windows. - void _setAutoRefresh() { + void setAutoRefresh({ + required bool autoRefresh, + required int refreshInterval, + }) { fetchData(); - if (_timer != null) _timer!.cancel(); - if (prefs.autoRefresh) { + if (_timer != null) _timer?.cancel(); + if (autoRefresh) { _timer = Timer.periodic( - Duration(seconds: prefs.refreshInterval), + Duration(seconds: refreshInterval), (timer) => fetchData(), ); } @@ -55,11 +69,6 @@ class AppCubit extends Cubit { emit(state.copyWith(currentDesktop: currentDesktop)); } - Future updateAutoRefresh([bool? autoEnabled]) async { - if (autoEnabled != null) await prefs.setAutoRefresh(autoEnabled); - _setAutoRefresh(); - } - /// Check for which windows are open. Future fetchWindows() async { final newWindows = await nativePlatform.windows; diff --git a/lib/application/app/cubit/app_state.dart b/lib/application/app/cubit/app_state.dart index b1a7b91a..7e58f567 100644 --- a/lib/application/app/cubit/app_state.dart +++ b/lib/application/app/cubit/app_state.dart @@ -1,6 +1,10 @@ part of 'app_cubit.dart'; class AppState extends Equatable { + /// Check for `PORTABLE` file in the Nyrna directory, which should only be + /// present for the portable build on Linux. + final bool isPortable; + final String runningVersion; final String updateVersion; final bool updateAvailable; @@ -11,6 +15,7 @@ class AppState extends Equatable { final Map windows; const AppState({ + required this.isPortable, required this.runningVersion, required this.updateVersion, required this.updateAvailable, @@ -20,6 +25,7 @@ class AppState extends Equatable { factory AppState.initial() { return AppState( + isPortable: false, runningVersion: '', updateVersion: '', updateAvailable: false, @@ -31,6 +37,7 @@ class AppState extends Equatable { @override List get props { return [ + isPortable, runningVersion, updateVersion, updateAvailable, @@ -40,6 +47,7 @@ class AppState extends Equatable { } AppState copyWith({ + bool? isPortable, String? runningVersion, String? updateVersion, bool? updateAvailable, @@ -47,6 +55,7 @@ class AppState extends Equatable { Map? windows, }) { return AppState( + isPortable: isPortable ?? this.isPortable, runningVersion: runningVersion ?? this.runningVersion, updateVersion: updateVersion ?? this.updateVersion, updateAvailable: updateAvailable ?? this.updateAvailable, diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index b7699637..eb752015 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -1,5 +1,8 @@ +import 'dart:io'; + import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/infrastructure/launcher/launcher.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; @@ -8,7 +11,18 @@ part 'preferences_state.dart'; late PreferencesCubit preferencesCubit; class PreferencesCubit extends Cubit { - PreferencesCubit() : super(PreferencesInitial()) { + final Preferences _prefs; + + PreferencesCubit(Preferences prefs) + : _prefs = prefs, + super( + PreferencesState( + autoRefresh: prefs.getBool('autoRefresh') ?? (Platform.isWindows) + ? false + : true, + refreshInterval: prefs.getInt('refreshInterval') ?? 5, + ), + ) { preferencesCubit = this; } @@ -18,6 +32,24 @@ class PreferencesCubit extends Cubit { /// If user wishes to ignore this update, save to SharedPreferences. Future ignoreUpdate(String version) async { - await Preferences.instance.setString(key: 'ignoredUpdate', value: version); + await _prefs.setString(key: 'ignoredUpdate', value: version); + } + + Future setRefreshInterval(int interval) async { + if (interval > 0) { + await _prefs.setInt(key: 'refreshInterval', value: interval); + emit(state.copyWith(refreshInterval: interval)); + } + } + + Future updateAutoRefresh([bool? autoEnabled]) async { + if (autoEnabled != null) { + await _prefs.setBool(key: 'autoRefresh', value: autoEnabled); + appCubit.setAutoRefresh( + autoRefresh: autoEnabled, + refreshInterval: state.refreshInterval, + ); + emit(state.copyWith(autoRefresh: autoEnabled)); + } } } diff --git a/lib/application/preferences/cubit/preferences_state.dart b/lib/application/preferences/cubit/preferences_state.dart index 575db98c..ddc6b6ed 100644 --- a/lib/application/preferences/cubit/preferences_state.dart +++ b/lib/application/preferences/cubit/preferences_state.dart @@ -1,10 +1,28 @@ part of 'preferences_cubit.dart'; -abstract class PreferencesState extends Equatable { - const PreferencesState(); +class PreferencesState extends Equatable { + /// Whether or not to automatically refresh the list of open windows. + final bool autoRefresh; + + /// How often to automatically refresh the list of open windows, in seconds. + final int refreshInterval; + + const PreferencesState({ + required this.autoRefresh, + required this.refreshInterval, + }); @override - List get props => []; -} + List get props => [autoRefresh, refreshInterval]; -class PreferencesInitial extends PreferencesState {} + PreferencesState copyWith({ + bool? autoRefresh, + bool? isPortable, + int? refreshInterval, + }) { + return PreferencesState( + autoRefresh: autoRefresh ?? this.autoRefresh, + refreshInterval: refreshInterval ?? this.refreshInterval, + ); + } +} diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index 310340fd..c49d86fb 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:nyrna/application/theme/enums/app_theme.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -10,78 +8,57 @@ class Preferences { static final Preferences instance = Preferences._privateConstructor(); /// Instance of SharedPreferences for getting and setting preferences. - SharedPreferences? prefs; + SharedPreferences? _prefs; /// Initialize should only need to be called once, in main(). Future initialize() async { - if (prefs != null) return; - prefs = await SharedPreferences.getInstance(); + if (_prefs != null) return; + _prefs = await SharedPreferences.getInstance(); } - Future setString({required String key, required String value}) async { - assert(key != ''); - assert(value != ''); - await prefs?.setString(key, value); + Future setBool({required String key, required bool value}) async { + await _prefs?.setBool(key, value); } - String? getString(String key) => prefs?.getString(key); + bool? getBool(String key) => _prefs?.getBool(key); - /// Whether or not to automatically refresh the list of open windows. - bool get autoRefresh { - bool defaultValue; - defaultValue = (Platform.isWindows) ? false : true; - return prefs!.getBool('autoRefresh') ?? defaultValue; + Future setInt({required String key, required int value}) async { + await _prefs?.setInt(key, value); } - Future setAutoRefresh(bool shouldRefresh) async { - await prefs?.setBool('autoRefresh', shouldRefresh); - } - - /// How often to automatically refresh the list of open windows, in seconds. - int get refreshInterval => prefs!.getInt('refreshInterval') ?? 5; + int? getInt(String key) => _prefs?.getInt(key); - set refreshInterval(int interval) { - if (interval > 0) { - prefs!.setInt('refreshInterval', interval); - } + Future setString({required String key, required String value}) async { + assert(key != ''); + assert(value != ''); + await _prefs?.setString(key, value); } - /// The PID of the process Nyrna suspended via [ActiveWindow.toggle()]. - /// - /// Returns 0 if Nyrna hasn't suspended anything in this fashion. - int get savedProcess => prefs!.getInt('savedProcess') ?? 0; + String? getString(String key) => _prefs?.getString(key); - Future setSavedProcess(int pid) async { - await prefs!.setInt('savedProcess', pid); - } + /// Remove a value from stored preferences. + Future remove(String key) async => await _prefs!.remove(key); /// The unique hex ID of the window suspended via [ActiveWindow.toggle()]. - int? get savedWindowId => prefs!.getInt('savedWindowId'); + int? get savedWindowId => _prefs!.getInt('savedWindowId'); Future setSavedWindowId(int id) async { - await prefs!.setInt('savedWindowId', id); + await _prefs!.setInt('savedWindowId', id); } /// If user has ignored an update that version number is saved here. - String? get ignoredUpdate => prefs!.getString('ignoredUpdate'); - - /// Check for `PORTABLE` file in the Nyrna directory, which should only be - /// present for the portable build on Linux. - Future get isPortable async { - final file = File('PORTABLE'); - return await file.exists(); - } + String? get ignoredUpdate => _prefs!.getString('ignoredUpdate'); static const int _defaultIconColor = 2617291775; - int get iconColor => prefs!.getInt('iconColor') ?? _defaultIconColor; + int get iconColor => _prefs!.getInt('iconColor') ?? _defaultIconColor; Future setIconColor(int color) async { - await prefs!.setInt('iconColor', color); + await _prefs!.setInt('iconColor', color); } AppTheme get appTheme { - final savedTheme = prefs?.getString('appTheme'); + final savedTheme = _prefs?.getString('appTheme'); switch (savedTheme) { case null: return AppTheme.dark; @@ -97,6 +74,6 @@ class Preferences { } set appTheme(AppTheme appTheme) { - prefs?.setString('appTheme', appTheme.toString()); + _prefs?.setString('appTheme', appTheme.toString()); } } diff --git a/lib/main.dart b/lib/main.dart index dc70fdb9..20f38039 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -31,7 +31,7 @@ Future main(List args) async { lazy: false, ), BlocProvider( - create: (context) => PreferencesCubit(), + create: (context) => PreferencesCubit(prefs), lazy: false, ), BlocProvider( diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index b664abfb..db3d0f7a 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -9,7 +9,6 @@ import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/app/widgets/window_tile.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -26,8 +25,6 @@ class AppsPage extends StatefulWidget { class _AppsPageState extends State { static final _log = Logger('RunningAppsScreen'); - final _settings = Preferences.instance; - @override void initState() { _log.info('RunningAppsScreen initialized'); @@ -65,11 +62,7 @@ class _AppsPageState extends State { ), ), // We don't show a manual refresh button with a short auto-refresh. - floatingActionButton: - ((_settings.autoRefresh && _settings.refreshInterval > 5) || - !_settings.autoRefresh) - ? _FloatingActionButton() - : null, + floatingActionButton: _FloatingActionButton(), ); } @@ -167,14 +160,26 @@ class _FloatingActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { - return FloatingActionButton( - backgroundColor: - (state.appTheme == AppTheme.pitchBlack) ? Colors.black : null, - onPressed: () => appCubit.fetchData(), - child: const Icon(Icons.refresh), - ); + final autoRefresh = state.autoRefresh; + final refreshIntervalSufficient = (state.refreshInterval > 5); + final showFloatingActionButton = + ((autoRefresh && refreshIntervalSufficient) || !autoRefresh); + + return showFloatingActionButton + ? BlocBuilder( + builder: (context, state) { + return FloatingActionButton( + backgroundColor: (state.appTheme == AppTheme.pitchBlack) + ? Colors.black + : null, + onPressed: () => appCubit.fetchData(), + child: const Icon(Icons.refresh), + ); + }, + ) + : Container(); }, ); } diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index d7a5d7df..e5867284 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -6,7 +6,7 @@ import 'package:nyrna/application/app/cubit/app_cubit.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/core/core.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; +// import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/presentation/logs/logs.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -27,7 +27,7 @@ class _PreferencesPageState extends State { /// Adds a little space between sections. final _sectionPadding = const SizedBox(height: 50); - Preferences settings = Preferences.instance; + // Preferences settings = Preferences.instance; late final _warningChip = ActionChip( label: Text( @@ -80,22 +80,28 @@ class _PreferencesPageState extends State { if (Platform.isWindows) _warningChip, ], ), - trailing: Switch( - value: settings.autoRefresh, - onChanged: (value) { - setState(() async { - await appCubit.updateAutoRefresh(value); - }); + trailing: BlocBuilder( + builder: (context, state) { + return Switch( + value: state.autoRefresh, + onChanged: (value) async { + await preferencesCubit.updateAutoRefresh(value); + }, + ); }, ), ), _divider, - ListTile( - leading: const Icon(Icons.timelapse), - title: Text('Auto Refresh Interval'), - trailing: Text('${settings.refreshInterval} seconds'), - enabled: settings.autoRefresh, - onTap: () => _refreshIntervalDialog(), + BlocBuilder( + builder: (context, state) { + return ListTile( + leading: const Icon(Icons.timelapse), + title: Text('Auto Refresh Interval'), + trailing: Text('${state.refreshInterval} seconds'), + enabled: state.autoRefresh, + onTap: () => _refreshIntervalDialog(), + ); + }, ), // _divider, // ListTile( @@ -106,25 +112,23 @@ class _PreferencesPageState extends State { // ), // Add shortcuts and icons for portable builds. if (Platform.isLinux) // TODO: Add integration function for Windows. - FutureBuilder( - future: settings.isPortable, - builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data!) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _sectionPadding, - Text('System Integration'), - const SizedBox(height: 8), - ListTile( - leading: Icon(Icons.add_circle_outline), - title: Text('Add Nyrna to launcher'), - onTap: () => _confirmAddToLauncher(context), - ), - ], - ); - } - return const SizedBox(); + BlocBuilder( + builder: (context, state) { + return state.isPortable + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _sectionPadding, + Text('System Integration'), + const SizedBox(height: 8), + ListTile( + leading: Icon(Icons.add_circle_outline), + title: Text('Add Nyrna to launcher'), + onTap: () => _confirmAddToLauncher(context), + ), + ], + ) + : const SizedBox(); }, ), _sectionPadding, @@ -172,13 +176,13 @@ class _PreferencesPageState extends State { context: context, type: InputDialogs.onlyInt, title: 'Auto Refresh Interval', - initialValue: settings.refreshInterval.toString(), + initialValue: preferencesCubit.state.refreshInterval.toString(), ); if (result == null) return; final newInterval = int.tryParse(result); if (newInterval == null) return; - setState(() => settings.refreshInterval = newInterval); - await appCubit.updateAutoRefresh(); + await preferencesCubit.setRefreshInterval(newInterval); + await preferencesCubit.updateAutoRefresh(); } // Future _pickIconColor() async { From 639beb6abd47d7f3e4ce8442808e51325fc0d8e0 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 09:59:27 -0400 Subject: [PATCH 20/83] Refactor saved window id --- .../active_window/active_window.dart | 21 ++++++++++++++----- .../preferences/preferences.dart | 7 ------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 334a2fc6..ac35e653 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -74,9 +74,16 @@ class ActiveWindow { await Preferences.instance.setInt(key: 'savedProcess', value: pid); } + /// The unique hex ID of the window suspended via [ActiveWindow.toggle()]. + int? _getSavedWindowId() => Preferences.instance.getInt('savedWindowId'); + + Future _setSavedWindowId(int id) async { + await Preferences.instance.setInt(key: 'savedWindowId', value: id); + } + Future _removeSavedProcess() async { await Preferences.instance.remove('savedProcess'); - await _settings.setSavedWindowId(0); + await Preferences.instance.remove('savedWindowId'); } Future _verifyPid() async { @@ -107,8 +114,12 @@ class ActiveWindow { /// Toggle the suspend / resume state of the given process. Future _toggleProcess() async { final savedProcess = _getSavedProcess(); - if (savedProcess != null) { - final successful = await _resume(pid: savedProcess); + final savedWindowId = _getSavedWindowId(); + if ((savedProcess != null) && (savedWindowId != null)) { + final successful = await _resume( + pid: savedProcess, + id: savedWindowId, + ); return successful; } else { final successful = await _suspend(); @@ -118,9 +129,9 @@ class ActiveWindow { Future _resume({ required int pid, + required int id, }) async { var successful = false; - id = _settings.savedWindowId; final process = Process(pid); final _status = await process.status; if (_status == ProcessStatus.unknown) { @@ -150,7 +161,7 @@ class ActiveWindow { } successful = await process.toggle(); await _setSavedProcess(pid); - await _settings.setSavedWindowId(id!); + await _setSavedWindowId(id!); if (!successful) { _log.warning('Failed to suspend PID: $pid'); } diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index c49d86fb..7ca6bd79 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -39,13 +39,6 @@ class Preferences { /// Remove a value from stored preferences. Future remove(String key) async => await _prefs!.remove(key); - /// The unique hex ID of the window suspended via [ActiveWindow.toggle()]. - int? get savedWindowId => _prefs!.getInt('savedWindowId'); - - Future setSavedWindowId(int id) async { - await _prefs!.setInt('savedWindowId', id); - } - /// If user has ignored an update that version number is saved here. String? get ignoredUpdate => _prefs!.getString('ignoredUpdate'); From f06327dc894e1361fc33ed6f8a59864280ffc817 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:01:24 -0400 Subject: [PATCH 21/83] Remove old ignoredUpdate --- lib/infrastructure/preferences/preferences.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index 7ca6bd79..bcb18104 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -39,9 +39,6 @@ class Preferences { /// Remove a value from stored preferences. Future remove(String key) async => await _prefs!.remove(key); - /// If user has ignored an update that version number is saved here. - String? get ignoredUpdate => _prefs!.getString('ignoredUpdate'); - static const int _defaultIconColor = 2617291775; int get iconColor => _prefs!.getInt('iconColor') ?? _defaultIconColor; From d0a3620b1e2a43d4cad659d6baf59d2d0a59a0e8 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:05:10 -0400 Subject: [PATCH 22/83] Refactor icon color --- lib/domain/app_icon/app_icon.dart | 3 +++ lib/infrastructure/preferences/preferences.dart | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) create mode 100644 lib/domain/app_icon/app_icon.dart diff --git a/lib/domain/app_icon/app_icon.dart b/lib/domain/app_icon/app_icon.dart new file mode 100644 index 00000000..2bdae9dd --- /dev/null +++ b/lib/domain/app_icon/app_icon.dart @@ -0,0 +1,3 @@ +class AppIcon { + static const int _defaultIconColor = 2617291775; +} diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index bcb18104..b6ee8a0e 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -39,14 +39,6 @@ class Preferences { /// Remove a value from stored preferences. Future remove(String key) async => await _prefs!.remove(key); - static const int _defaultIconColor = 2617291775; - - int get iconColor => _prefs!.getInt('iconColor') ?? _defaultIconColor; - - Future setIconColor(int color) async { - await _prefs!.setInt('iconColor', color); - } - AppTheme get appTheme { final savedTheme = _prefs?.getString('appTheme'); switch (savedTheme) { From 7169d51a9ab36e0bb890bb3aae71e6734d6f673f Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:30:02 -0400 Subject: [PATCH 23/83] Comment temporarily unused code --- lib/domain/app_icon/app_icon.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/domain/app_icon/app_icon.dart b/lib/domain/app_icon/app_icon.dart index 2bdae9dd..cde021ae 100644 --- a/lib/domain/app_icon/app_icon.dart +++ b/lib/domain/app_icon/app_icon.dart @@ -1,3 +1,3 @@ -class AppIcon { - static const int _defaultIconColor = 2617291775; -} +// class AppIcon { +// static const int _defaultIconColor = 2617291775; +// } From 17513c7b91ce5e02b64e7889bb4fe8c1f59208da Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:30:19 -0400 Subject: [PATCH 24/83] Use one preferences instance --- lib/application/active_window/active_window.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index ac35e653..66c91d52 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -19,7 +19,7 @@ class ActiveWindow { static final _log = Logger('ActiveWindow'); - final _settings = Preferences.instance; + final _prefs = Preferences.instance; /// Nyrna's own PID. final int nyrnaPid = io.pid; @@ -68,22 +68,22 @@ class ActiveWindow { ShowWindow(id, SW_FORCEMINIMIZE); } - int? _getSavedProcess() => Preferences.instance.getInt('savedProcess'); + int? _getSavedProcess() => _prefs.getInt('savedProcess'); Future _setSavedProcess(int pid) async { - await Preferences.instance.setInt(key: 'savedProcess', value: pid); + await _prefs.setInt(key: 'savedProcess', value: pid); } /// The unique hex ID of the window suspended via [ActiveWindow.toggle()]. - int? _getSavedWindowId() => Preferences.instance.getInt('savedWindowId'); + int? _getSavedWindowId() => _prefs.getInt('savedWindowId'); Future _setSavedWindowId(int id) async { - await Preferences.instance.setInt(key: 'savedWindowId', value: id); + await _prefs.setInt(key: 'savedWindowId', value: id); } Future _removeSavedProcess() async { - await Preferences.instance.remove('savedProcess'); - await Preferences.instance.remove('savedWindowId'); + await _prefs.remove('savedProcess'); + await _prefs.remove('savedWindowId'); } Future _verifyPid() async { From 949fc6dcbb7b937353da266ee6e5f538b41772d5 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 10:37:53 -0400 Subject: [PATCH 25/83] Refactor appTheme --- lib/application/theme/cubit/theme_cubit.dart | 26 +++++++++++++++++-- .../preferences/preferences.dart | 21 --------------- lib/main.dart | 2 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/lib/application/theme/cubit/theme_cubit.dart b/lib/application/theme/cubit/theme_cubit.dart index 71a48ca2..4880c38a 100644 --- a/lib/application/theme/cubit/theme_cubit.dart +++ b/lib/application/theme/cubit/theme_cubit.dart @@ -9,12 +9,34 @@ part 'theme_state.dart'; late ThemeCubit themeCubit; class ThemeCubit extends Cubit { - ThemeCubit() : super(ThemeState(appTheme: Preferences.instance.appTheme)) { + final Preferences _prefs; + + ThemeCubit(Preferences prefs) + : _prefs = prefs, + super( + ThemeState(appTheme: _getAppTheme(prefs)), + ) { themeCubit = this; } + static AppTheme _getAppTheme(Preferences prefs) { + final savedTheme = prefs.getString('appTheme'); + switch (savedTheme) { + case null: + return AppTheme.dark; + case 'AppTheme.light': + return AppTheme.light; + case 'AppTheme.dark': + return AppTheme.dark; + case 'AppTheme.pitchBlack': + return AppTheme.pitchBlack; + default: + return AppTheme.dark; + } + } + void changeTheme(AppTheme appTheme) { - Preferences.instance.appTheme = appTheme; + _prefs.setString(key: 'appTheme', value: appTheme.toString()); emit(state.copyWith(appTheme: appTheme)); } } diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index b6ee8a0e..94f553c7 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -1,4 +1,3 @@ -import 'package:nyrna/application/theme/enums/app_theme.dart'; import 'package:shared_preferences/shared_preferences.dart'; /// Manages settings & preferences. @@ -38,24 +37,4 @@ class Preferences { /// Remove a value from stored preferences. Future remove(String key) async => await _prefs!.remove(key); - - AppTheme get appTheme { - final savedTheme = _prefs?.getString('appTheme'); - switch (savedTheme) { - case null: - return AppTheme.dark; - case 'AppTheme.light': - return AppTheme.light; - case 'AppTheme.dark': - return AppTheme.dark; - case 'AppTheme.pitchBlack': - return AppTheme.pitchBlack; - default: - return AppTheme.dark; - } - } - - set appTheme(AppTheme appTheme) { - _prefs?.setString('appTheme', appTheme.toString()); - } } diff --git a/lib/main.dart b/lib/main.dart index 20f38039..a9493892 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -35,7 +35,7 @@ Future main(List args) async { lazy: false, ), BlocProvider( - create: (context) => ThemeCubit(), + create: (context) => ThemeCubit(prefs), ), ], child: AppWidget(), From 9b28916779e7daf90bd2767cd2d9c2317ef512a5 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:37:18 -0400 Subject: [PATCH 26/83] Pass SharedPreferences to Preferences constructor --- .../active_window/active_window.dart | 2 +- lib/application/app/cubit/app_cubit.dart | 8 ++--- .../preferences/preferences.dart | 35 ++++++++++--------- lib/main.dart | 7 ++-- test/window/active_window_test.dart | 6 ++-- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 66c91d52..51e19f4f 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -19,7 +19,7 @@ class ActiveWindow { static final _log = Logger('ActiveWindow'); - final _prefs = Preferences.instance; + final _prefs = Preferences(); /// Nyrna's own PID. final int nyrnaPid = io.pid; diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index e60980b3..75e86f37 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -16,11 +16,11 @@ late AppCubit appCubit; class AppCubit extends Cubit { final NativePlatform nativePlatform; - final Preferences prefs; + final Preferences _prefs; - AppCubit() + AppCubit(Preferences prefs) : nativePlatform = NativePlatform(), - prefs = Preferences.instance, + _prefs = prefs, super(AppState.initial()) { appCubit = this; _initialize(); @@ -96,7 +96,7 @@ class AppCubit extends Cubit { final versionRepo = Versions(); final runningVersion = await versionRepo.runningVersion(); final latestVersion = await versionRepo.latestVersion(); - final ignoredUpdate = Preferences.instance.getString('ignoredUpdate'); + final ignoredUpdate = _prefs.getString('ignoredUpdate'); final updateHasBeenIgnored = (latestVersion == ignoredUpdate); final updateAvailable = (updateHasBeenIgnored) ? false : await versionRepo.updateAvailable(); diff --git a/lib/infrastructure/preferences/preferences.dart b/lib/infrastructure/preferences/preferences.dart index 94f553c7..47e18d5b 100644 --- a/lib/infrastructure/preferences/preferences.dart +++ b/lib/infrastructure/preferences/preferences.dart @@ -1,40 +1,43 @@ import 'package:shared_preferences/shared_preferences.dart'; -/// Manages settings & preferences. +/// Persist key value pairs to disk. class Preferences { + /// Instance of SharedPreferences for getting and setting preferences. + final SharedPreferences _prefs; + // Settings is a singleton. - Preferences._privateConstructor(); - static final Preferences instance = Preferences._privateConstructor(); + Preferences._internal(SharedPreferences prefs) : _prefs = prefs; - /// Instance of SharedPreferences for getting and setting preferences. - SharedPreferences? _prefs; + static Preferences? _instance; - /// Initialize should only need to be called once, in main(). - Future initialize() async { - if (_prefs != null) return; - _prefs = await SharedPreferences.getInstance(); + factory Preferences([SharedPreferences? prefs]) { + if (_instance == null) { + assert(prefs != null); + _instance = Preferences._internal(prefs!); + } + return _instance!; } Future setBool({required String key, required bool value}) async { - await _prefs?.setBool(key, value); + await _prefs.setBool(key, value); } - bool? getBool(String key) => _prefs?.getBool(key); + bool? getBool(String key) => _prefs.getBool(key); Future setInt({required String key, required int value}) async { - await _prefs?.setInt(key, value); + await _prefs.setInt(key, value); } - int? getInt(String key) => _prefs?.getInt(key); + int? getInt(String key) => _prefs.getInt(key); Future setString({required String key, required String value}) async { assert(key != ''); assert(value != ''); - await _prefs?.setString(key, value); + await _prefs.setString(key, value); } - String? getString(String key) => _prefs?.getString(key); + String? getString(String key) => _prefs.getString(key); /// Remove a value from stored preferences. - Future remove(String key) async => await _prefs!.remove(key); + Future remove(String key) async => await _prefs.remove(key); } diff --git a/lib/main.dart b/lib/main.dart index a9493892..c5211d3f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/application/active_window/active_window.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'application/app/app.dart'; import 'application/preferences/cubit/preferences_cubit.dart'; @@ -15,8 +16,8 @@ Future main(List args) async { final parser = ArgumentParser(args); await parser.parse(); - final prefs = Preferences.instance; - await prefs.initialize(); + final sharedPreferences = await SharedPreferences.getInstance(); + final prefs = Preferences(sharedPreferences); AppLogger().initialize(); @@ -27,7 +28,7 @@ Future main(List args) async { MultiBlocProvider( providers: [ BlocProvider( - create: (context) => AppCubit(), + create: (context) => AppCubit(prefs), lazy: false, ), BlocProvider( diff --git a/test/window/active_window_test.dart b/test/window/active_window_test.dart index 762daf81..97efae59 100644 --- a/test/window/active_window_test.dart +++ b/test/window/active_window_test.dart @@ -1,10 +1,12 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/application/active_window/active_window.dart'; +import 'package:shared_preferences/shared_preferences.dart'; Future main() async { - final settings = Preferences.instance; - await settings.initialize(); + final sharedPreferences = await SharedPreferences.getInstance(); + // ignore: unused_local_variable + final prefs = Preferences(sharedPreferences); ActiveWindow? activeWindow; From 0ab4db054d74a256685b069e33d096e2f9ff6581 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:43:12 -0400 Subject: [PATCH 27/83] Refactor warningChip --- .../preferences/pages/preferences_page.dart | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index e5867284..8dac04c7 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -6,7 +6,6 @@ import 'package:nyrna/application/app/cubit/app_cubit.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/presentation/core/core.dart'; -// import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/presentation/logs/logs.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -27,36 +26,6 @@ class _PreferencesPageState extends State { /// Adds a little space between sections. final _sectionPadding = const SizedBox(height: 50); - // Preferences settings = Preferences.instance; - - late final _warningChip = ActionChip( - label: Text( - 'Caution', - style: TextStyle(color: Colors.red[800]), - ), - backgroundColor: Colors.yellow, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: Text( - 'Note: Auto refresh can cause issues with memory consumption on ' - 'Windows at the moment. Until the problem is resolved, consider ' - 'keeping auto refresh off if you experience issues.', - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text('Close'), - ), - ], - ); - }, - ); - }, - ); - @override Widget build(BuildContext context) { return Scaffold( @@ -77,7 +46,7 @@ class _PreferencesPageState extends State { children: [ Text('Update window & process info automatically'), const SizedBox(height: 5), - if (Platform.isWindows) _warningChip, + if (Platform.isWindows) _WarningChip(), ], ), trailing: BlocBuilder( @@ -309,3 +278,38 @@ class ThemeSettings extends StatelessWidget { ); } } + +class _WarningChip extends StatelessWidget { + const _WarningChip({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ActionChip( + label: Text( + 'Caution', + style: TextStyle(color: Colors.red[800]), + ), + backgroundColor: Colors.yellow, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + content: const Text( + 'Note: Auto refresh can cause issues with memory consumption on ' + 'Windows at the moment. Until the problem is resolved, consider ' + 'keeping auto refresh off if you experience issues.', + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ); + }, + ); + }, + ); + } +} From b3d7db92c5d70951a27835c0702fcc394c1a01b8 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:44:08 -0400 Subject: [PATCH 28/83] Refactor PreferencesPage to StatelessWidget --- .../preferences/pages/preferences_page.dart | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index 8dac04c7..d01261b7 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -10,14 +10,9 @@ import 'package:nyrna/presentation/logs/logs.dart'; import 'package:url_launcher/url_launcher.dart'; /// Screen with configuration settings for Nyrna. -class PreferencesPage extends StatefulWidget { +class PreferencesPage extends StatelessWidget { static const id = 'settings_screen'; - @override - _PreferencesPageState createState() => _PreferencesPageState(); -} - -class _PreferencesPageState extends State { final _divider = const Divider( indent: 20, endIndent: 20, @@ -68,7 +63,7 @@ class _PreferencesPageState extends State { title: Text('Auto Refresh Interval'), trailing: Text('${state.refreshInterval} seconds'), enabled: state.autoRefresh, - onTap: () => _refreshIntervalDialog(), + onTap: () => _refreshIntervalDialog(context), ); }, ), @@ -140,7 +135,7 @@ class _PreferencesPageState extends State { } /// Allow user to choose reset interval. - void _refreshIntervalDialog() async { + void _refreshIntervalDialog(BuildContext context) async { final result = await showInputDialog( context: context, type: InputDialogs.onlyInt, From 6e122e0cf6fd1164af9148d68fa5681102d98274 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:52:07 -0400 Subject: [PATCH 29/83] Refactor id --- lib/presentation/preferences/pages/preferences_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index d01261b7..cc46e852 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -11,7 +11,7 @@ import 'package:url_launcher/url_launcher.dart'; /// Screen with configuration settings for Nyrna. class PreferencesPage extends StatelessWidget { - static const id = 'settings_screen'; + static const id = 'preferences_page'; final _divider = const Divider( indent: 20, From 60b9a1c604e5ba053c796d0654e2dd79e3ef2f49 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:56:39 -0400 Subject: [PATCH 30/83] Remove Divider --- lib/presentation/preferences/pages/preferences_page.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index cc46e852..c9b5b703 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -13,11 +13,6 @@ import 'package:url_launcher/url_launcher.dart'; class PreferencesPage extends StatelessWidget { static const id = 'preferences_page'; - final _divider = const Divider( - indent: 20, - endIndent: 20, - ); - /// Adds a little space between sections. final _sectionPadding = const SizedBox(height: 50); @@ -55,7 +50,6 @@ class PreferencesPage extends StatelessWidget { }, ), ), - _divider, BlocBuilder( builder: (context, state) { return ListTile( From a0371e65c2461f1050ac55a9a4b7dfdbcd917861 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:44:22 -0400 Subject: [PATCH 31/83] Refactor all of Preferences --- lib/application/bloc_observer.dart | 27 ++ .../preferences/cubit/preferences_cubit.dart | 10 +- lib/main.dart | 3 + .../preferences/pages/preferences_page.dart | 295 +----------------- lib/presentation/preferences/preferences.dart | 1 + .../preferences/widgets/about_section.dart | 36 +++ .../widgets/behaviour_section.dart | 106 +++++++ .../widgets/integration_section.dart | 70 +++++ .../preferences/widgets/theme_section.dart | 123 ++++++++ .../preferences/widgets/widgets.dart | 4 + lib/presentation/styles.dart | 23 ++ linux/flutter/generated_plugin_registrant.cc | 2 - linux/flutter/generated_plugin_registrant.h | 2 - pubspec.lock | 8 +- .../flutter/generated_plugin_registrant.cc | 2 - windows/flutter/generated_plugin_registrant.h | 2 - 16 files changed, 418 insertions(+), 296 deletions(-) create mode 100644 lib/application/bloc_observer.dart create mode 100644 lib/presentation/preferences/widgets/about_section.dart create mode 100644 lib/presentation/preferences/widgets/behaviour_section.dart create mode 100644 lib/presentation/preferences/widgets/integration_section.dart create mode 100644 lib/presentation/preferences/widgets/theme_section.dart create mode 100644 lib/presentation/preferences/widgets/widgets.dart create mode 100644 lib/presentation/styles.dart diff --git a/lib/application/bloc_observer.dart b/lib/application/bloc_observer.dart new file mode 100644 index 00000000..35fd9dcc --- /dev/null +++ b/lib/application/bloc_observer.dart @@ -0,0 +1,27 @@ +import 'package:bloc/bloc.dart'; + +class AppBlocObserver extends BlocObserver { + // @override + // void onEvent(Bloc bloc, Object? event) { + // super.onEvent(bloc, event); + // // TODO: implement onEvent + // } + + // @override + // void onError(BlocBase bloc, Object error, StackTrace stacktrace) { + // // TODO: implement onError + // super.onError(bloc, error, stacktrace); + // } + + @override + void onChange(BlocBase bloc, Change change) { + super.onChange(bloc, change); + // print('${bloc.runtimeType} $change'); + } + + // @override + // void onTransition(Bloc bloc, Transition transition) { + // super.onTransition(bloc, transition); + // // TODO: implement onChange + // } +} diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index eb752015..78801f7b 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -17,15 +17,19 @@ class PreferencesCubit extends Cubit { : _prefs = prefs, super( PreferencesState( - autoRefresh: prefs.getBool('autoRefresh') ?? (Platform.isWindows) - ? false - : true, + autoRefresh: _checkAutoRefresh(prefs), refreshInterval: prefs.getInt('refreshInterval') ?? 5, ), ) { preferencesCubit = this; } + static bool _checkAutoRefresh(Preferences prefs) { + bool? enabled = prefs.getBool('autoRefresh'); + enabled ??= (Platform.isWindows) ? false : true; + return enabled; + } + Future createLauncher() async { await Launcher.add(); } diff --git a/lib/main.dart b/lib/main.dart index c5211d3f..4f23f2ff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/bloc_observer.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; @@ -24,6 +25,8 @@ Future main(List args) async { // `-t` or `--toggle` flag detected. if (parser.toggleFlagged) await ActiveWindow().toggle(); + Bloc.observer = AppBlocObserver(); + runApp( MultiBlocProvider( providers: [ diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index c9b5b703..7e5d5370 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -1,304 +1,37 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:nyrna/application/app/cubit/app_cubit.dart'; -import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; -import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/presentation/core/core.dart'; import 'package:nyrna/presentation/logs/logs.dart'; -import 'package:url_launcher/url_launcher.dart'; +import 'package:nyrna/presentation/styles.dart'; + +import '../preferences.dart'; -/// Screen with configuration settings for Nyrna. class PreferencesPage extends StatelessWidget { static const id = 'preferences_page'; - /// Adds a little space between sections. - final _sectionPadding = const SizedBox(height: 50); - @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Settings')), + appBar: AppBar(title: const Text('Preferences')), body: ListView( - padding: EdgeInsets.symmetric( + padding: const EdgeInsets.symmetric( vertical: 30, horizontal: 130, ), children: [ - Text('Preferences'), - const SizedBox(height: 8), - ListTile( - title: Text('Auto Refresh'), - leading: Icon(Icons.refresh), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Update window & process info automatically'), - const SizedBox(height: 5), - if (Platform.isWindows) _WarningChip(), - ], - ), - trailing: BlocBuilder( - builder: (context, state) { - return Switch( - value: state.autoRefresh, - onChanged: (value) async { - await preferencesCubit.updateAutoRefresh(value); - }, - ); - }, - ), - ), - BlocBuilder( - builder: (context, state) { - return ListTile( - leading: const Icon(Icons.timelapse), - title: Text('Auto Refresh Interval'), - trailing: Text('${state.refreshInterval} seconds'), - enabled: state.autoRefresh, - onTap: () => _refreshIntervalDialog(context), - ); - }, - ), - // _divider, - // ListTile( - // leading: Icon(Icons.color_lens), - // title: Text('Icon color'), - // trailing: ColorIndicator(), - // onTap: () => _pickIconColor(), - // ), - // Add shortcuts and icons for portable builds. - if (Platform.isLinux) // TODO: Add integration function for Windows. - BlocBuilder( - builder: (context, state) { - return state.isPortable - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _sectionPadding, - Text('System Integration'), - const SizedBox(height: 8), - ListTile( - leading: Icon(Icons.add_circle_outline), - title: Text('Add Nyrna to launcher'), - onTap: () => _confirmAddToLauncher(context), - ), - ], - ) - : const SizedBox(); - }, - ), - _sectionPadding, - ThemeSettings(), - _sectionPadding, - Text('Troubleshooting'), + const BehaviourSection(), + Spacers.verticalMedium, + const ThemeSection(), + const IntegrationSection(), + Spacers.verticalMedium, + const Text('Troubleshooting'), ListTile( leading: const Icon(Icons.article_outlined), - title: Text('Logs'), + title: const Text('Logs'), onTap: () => Navigator.pushNamed(context, LogPage.id), ), - _sectionPadding, - Text('About'), - ListTile( - leading: const Icon(Icons.info_outline), - title: Text('Nyrna version'), - subtitle: BlocBuilder( - builder: (context, state) { - return Text(state.runningVersion); - }, - ), - ), - ListTile( - leading: const Icon(Icons.launch), - title: Text('Nyrna homepage'), - onTap: () async { - await launch('https://nyrna.merritt.codes'); - }, - ), - ListTile( - leading: const Icon(Icons.launch), - title: Text('GitHub repository'), - onTap: () async { - await launch('https://github.com/Merrit/nyrna'); - }, - ), + Spacers.verticalMedium, + const AboutSection(), ], ), ); } - - /// Allow user to choose reset interval. - void _refreshIntervalDialog(BuildContext context) async { - final result = await showInputDialog( - context: context, - type: InputDialogs.onlyInt, - title: 'Auto Refresh Interval', - initialValue: preferencesCubit.state.refreshInterval.toString(), - ); - if (result == null) return; - final newInterval = int.tryParse(result); - if (newInterval == null) return; - await preferencesCubit.setRefreshInterval(newInterval); - await preferencesCubit.updateAutoRefresh(); - } - -// Future _pickIconColor() async { -// var iconColor = Color(settings.iconColor); -// final iconManager = IconManager(); -// final iconUint8List = await iconManager.iconUint8List; -// final confirmed = await showDialog( -// context: context, -// builder: (context) { -// return AlertDialog( -// content: StatefulBuilder( -// builder: (context, setState) { -// return Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// ColorPicker( -// // Current color is pre-selected. -// color: iconColor, -// onColorChanged: (Color color) { -// setState(() => iconColor = color); -// }, -// heading: Text('Select color'), -// subheading: Text('Select color shade'), -// pickersEnabled: const { -// ColorPickerType.primary: true, -// ColorPickerType.accent: false, -// }, -// ), -// Image.memory( -// iconUint8List, -// height: 150, -// width: 150, -// color: iconColor, -// ), -// ], -// ); -// }, -// ), -// actions: [ -// TextButton( -// onPressed: () => Navigator.pop(context), -// child: Text('Cancel'), -// ), -// TextButton( -// onPressed: () {}, -// child: Text('Save'), -// ), -// ], -// ); -// }, -// ); -// if (confirmed == null) return; -// // await _updateIcon(); -// // await settings.setIconColor(newColor!.value); -// } -} - -/// Confirm with the user before adding .desktop and icon files. -void _confirmAddToLauncher(BuildContext context) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - insetPadding: const EdgeInsets.symmetric( - horizontal: 150.0, - vertical: 24.0, - ), - content: const Text('This will add a menu item to the system ' - 'launcher with an associated icon so launching Nyrna is easier.' - '\n\n' - 'Continue?'), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () async { - await preferencesCubit.createLauncher(); - Navigator.pop(context); - }, - child: const Text('Continue'), - ), - ], - ); - }, - ); -} - -class ThemeSettings extends StatelessWidget { - const ThemeSettings({ - Key? key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Theme'), - RadioListTile( - title: Text('Dark'), - groupValue: state.appTheme, - value: AppTheme.dark, - onChanged: (value) => themeCubit.changeTheme(value!), - ), - RadioListTile( - title: Text('Pitch Black'), - groupValue: state.appTheme, - value: AppTheme.pitchBlack, - onChanged: (value) => themeCubit.changeTheme(value!), - ), - RadioListTile( - title: Text('Light'), - groupValue: state.appTheme, - value: AppTheme.light, - onChanged: (value) => themeCubit.changeTheme(value!), - ), - ], - ); - }, - ); - } -} - -class _WarningChip extends StatelessWidget { - const _WarningChip({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ActionChip( - label: Text( - 'Caution', - style: TextStyle(color: Colors.red[800]), - ), - backgroundColor: Colors.yellow, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: const Text( - 'Note: Auto refresh can cause issues with memory consumption on ' - 'Windows at the moment. Until the problem is resolved, consider ' - 'keeping auto refresh off if you experience issues.', - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Close'), - ), - ], - ); - }, - ); - }, - ); - } } diff --git a/lib/presentation/preferences/preferences.dart b/lib/presentation/preferences/preferences.dart index 91719565..309e1ebb 100644 --- a/lib/presentation/preferences/preferences.dart +++ b/lib/presentation/preferences/preferences.dart @@ -1 +1,2 @@ export 'pages/pages.dart'; +export 'widgets/widgets.dart'; diff --git a/lib/presentation/preferences/widgets/about_section.dart b/lib/presentation/preferences/widgets/about_section.dart new file mode 100644 index 00000000..07c05c6f --- /dev/null +++ b/lib/presentation/preferences/widgets/about_section.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/app/app.dart'; + +class AboutSection extends StatelessWidget { + const AboutSection({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('About'), + ListTile( + leading: const Icon(Icons.info_outline), + title: const Text('Nyrna version'), + subtitle: BlocBuilder( + builder: (context, state) { + return Text(state.runningVersion); + }, + ), + ), + ListTile( + leading: const Icon(Icons.launch), + title: const Text('Nyrna homepage'), + onTap: () => appCubit.launchURL('https://nyrna.merritt.codes'), + ), + ListTile( + leading: const Icon(Icons.launch), + title: const Text('GitHub repository'), + onTap: () => appCubit.launchURL('https://github.com/Merrit/nyrna'), + ), + ], + ); + } +} diff --git a/lib/presentation/preferences/widgets/behaviour_section.dart b/lib/presentation/preferences/widgets/behaviour_section.dart new file mode 100644 index 00000000..32d71a29 --- /dev/null +++ b/lib/presentation/preferences/widgets/behaviour_section.dart @@ -0,0 +1,106 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; +import 'package:nyrna/presentation/core/core.dart'; + +import '../../styles.dart'; + +class BehaviourSection extends StatelessWidget { + const BehaviourSection({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Behaviour'), + Spacers.verticalXtraSmall, + ListTile( + title: const Text('Auto Refresh'), + leading: const Icon(Icons.refresh), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Update window & process info automatically'), + const SizedBox(height: 5), + if (Platform.isWindows) const _WarningChip(), + ], + ), + trailing: BlocBuilder( + builder: (context, state) { + return Switch( + value: state.autoRefresh, + onChanged: (value) async { + await preferencesCubit.updateAutoRefresh(value); + }, + ); + }, + ), + ), + BlocBuilder( + builder: (context, state) { + return ListTile( + leading: const Icon(Icons.timelapse), + title: const Text('Auto Refresh Interval'), + trailing: Text('${state.refreshInterval} seconds'), + enabled: state.autoRefresh, + onTap: () => _refreshIntervalDialog(context), + ); + }, + ), + ], + ); + } + + /// Allow user to choose reset interval. + void _refreshIntervalDialog(BuildContext context) async { + final result = await showInputDialog( + context: context, + type: InputDialogs.onlyInt, + title: 'Auto Refresh Interval', + initialValue: preferencesCubit.state.refreshInterval.toString(), + ); + if (result == null) return; + final newInterval = int.tryParse(result); + if (newInterval == null) return; + await preferencesCubit.setRefreshInterval(newInterval); + await preferencesCubit.updateAutoRefresh(); + } +} + +class _WarningChip extends StatelessWidget { + const _WarningChip({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ActionChip( + label: Text( + 'Caution', + style: TextStyle(color: Colors.red[800]), + ), + backgroundColor: Colors.yellow, + onPressed: () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + content: const Text( + 'Note: Auto refresh can cause issues with memory consumption on ' + 'Windows at the moment. Until the problem is resolved, consider ' + 'keeping auto refresh off if you experience issues.', + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ); + }, + ); + }, + ); + } +} diff --git a/lib/presentation/preferences/widgets/integration_section.dart b/lib/presentation/preferences/widgets/integration_section.dart new file mode 100644 index 00000000..93dce607 --- /dev/null +++ b/lib/presentation/preferences/widgets/integration_section.dart @@ -0,0 +1,70 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; + +import '../../styles.dart'; + +/// Add shortcuts and icons for portable builds. +class IntegrationSection extends StatelessWidget { + const IntegrationSection({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return (!Platform.isLinux) // TODO: Add integration function for Windows. + ? const SizedBox() + : BlocBuilder( + builder: (context, state) { + return state.isPortable + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Spacers.verticalMedium, + const Text('System Integration'), + const SizedBox(height: 8), + ListTile( + leading: const Icon(Icons.add_circle_outline), + title: const Text('Add Nyrna to launcher'), + onTap: () => _confirmAddToLauncher(context), + ), + ], + ) + : const SizedBox(); + }, + ); + } + + /// Confirm with the user before adding .desktop and icon files. + void _confirmAddToLauncher(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric( + horizontal: 150.0, + vertical: 24.0, + ), + content: const Text('This will add a menu item to the system ' + 'launcher with an associated icon so launching Nyrna is easier.' + '\n\n' + 'Continue?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () async { + await preferencesCubit.createLauncher(); + Navigator.pop(context); + }, + child: const Text('Continue'), + ), + ], + ); + }, + ); + } +} diff --git a/lib/presentation/preferences/widgets/theme_section.dart b/lib/presentation/preferences/widgets/theme_section.dart new file mode 100644 index 00000000..6b47fd4c --- /dev/null +++ b/lib/presentation/preferences/widgets/theme_section.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/theme/theme.dart'; + +class ThemeSection extends StatelessWidget { + const ThemeSection({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const _ThemeChooser(), + // const _IconCustomizer(), + ], + ); + } +} + +class _ThemeChooser extends StatelessWidget { + const _ThemeChooser({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Theme'), + RadioListTile( + title: const Text('Dark'), + groupValue: state.appTheme, + value: AppTheme.dark, + onChanged: (value) => themeCubit.changeTheme(value!), + ), + RadioListTile( + title: const Text('Pitch Black'), + groupValue: state.appTheme, + value: AppTheme.pitchBlack, + onChanged: (value) => themeCubit.changeTheme(value!), + ), + RadioListTile( + title: const Text('Light'), + groupValue: state.appTheme, + value: AppTheme.light, + onChanged: (value) => themeCubit.changeTheme(value!), + ), + ], + ); + }, + ); + } +} + +// class _IconCustomizer extends StatelessWidget { +// const _IconCustomizer({Key? key}) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// return ListTile( +// leading: Icon(Icons.color_lens), +// title: Text('Icon color'), +// trailing: ColorIndicator(), +// onTap: () => _pickIconColor(), +// ); +// } + +// Future _pickIconColor() async { +// var iconColor = Color(settings.iconColor); +// final iconManager = IconManager(); +// final iconUint8List = await iconManager.iconUint8List; +// final confirmed = await showDialog( +// context: context, +// builder: (context) { +// return AlertDialog( +// content: StatefulBuilder( +// builder: (context, setState) { +// return Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// ColorPicker( +// // Current color is pre-selected. +// color: iconColor, +// onColorChanged: (Color color) { +// setState(() => iconColor = color); +// }, +// heading: Text('Select color'), +// subheading: Text('Select color shade'), +// pickersEnabled: const { +// ColorPickerType.primary: true, +// ColorPickerType.accent: false, +// }, +// ), +// Image.memory( +// iconUint8List, +// height: 150, +// width: 150, +// color: iconColor, +// ), +// ], +// ); +// }, +// ), +// actions: [ +// TextButton( +// onPressed: () => Navigator.pop(context), +// child: Text('Cancel'), +// ), +// TextButton( +// onPressed: () {}, +// child: Text('Save'), +// ), +// ], +// ); +// }, +// ); +// if (confirmed == null) return; +// // await _updateIcon(); +// // await settings.setIconColor(newColor!.value); +// } +// } diff --git a/lib/presentation/preferences/widgets/widgets.dart b/lib/presentation/preferences/widgets/widgets.dart new file mode 100644 index 00000000..62e5e86e --- /dev/null +++ b/lib/presentation/preferences/widgets/widgets.dart @@ -0,0 +1,4 @@ +export 'about_section.dart'; +export 'behaviour_section.dart'; +export 'integration_section.dart'; +export 'theme_section.dart'; diff --git a/lib/presentation/styles.dart b/lib/presentation/styles.dart new file mode 100644 index 00000000..aefdf164 --- /dev/null +++ b/lib/presentation/styles.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +abstract class BorderRadii { + static BorderRadius gentlyRounded = BorderRadius.circular(10); +} + +abstract class Spacers { + static const horizontalSmall = SizedBox(width: 20); + + static const verticalXtraSmall = SizedBox(height: 10); + static const verticalSmall = SizedBox(height: 20); + static const verticalMedium = SizedBox(height: 30); +} + +class TextStyles { + static const TextStyle base = TextStyle(); + + static TextStyle body1 = base.copyWith(fontSize: 15); + + static TextStyle link1 = body1.copyWith(color: Colors.lightBlueAccent); + + static TextStyle headline1 = base.copyWith(fontSize: 20); +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index f6f23bfe..026851fa 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #include "generated_plugin_registrant.h" #include diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h index e0f0a47b..9bf74789 100644 --- a/linux/flutter/generated_plugin_registrant.h +++ b/linux/flutter/generated_plugin_registrant.h @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/pubspec.lock b/pubspec.lock index 4f631bc9..4b27239e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,7 +21,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.7.0" + version: "2.6.1" bloc: dependency: transitive description: @@ -98,7 +98,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.1" + version: "6.1.0" flex_color_picker: dependency: "direct main" description: @@ -184,7 +184,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.3.0" nested: dependency: transitive description: @@ -371,7 +371,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.0" + version: "0.3.0" typed_data: dependency: transitive description: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index d9fdd539..ddfcf7c3 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #include "generated_plugin_registrant.h" #include diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h index dc139d85..9846246b 100644 --- a/windows/flutter/generated_plugin_registrant.h +++ b/windows/flutter/generated_plugin_registrant.h @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ From 9b8c933494304f4efe9ac417b8702621abca08b4 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 28 Jul 2021 12:48:18 -0400 Subject: [PATCH 32/83] Refactor log page --- lib/application/log/cubit/log_cubit.dart | 41 +++++ lib/application/log/cubit/log_state.dart | 26 ++++ lib/presentation/logs/pages/log_page.dart | 176 ++++++++++------------ 3 files changed, 149 insertions(+), 94 deletions(-) create mode 100644 lib/application/log/cubit/log_cubit.dart create mode 100644 lib/application/log/cubit/log_state.dart diff --git a/lib/application/log/cubit/log_cubit.dart b/lib/application/log/cubit/log_cubit.dart new file mode 100644 index 00000000..8aac41b9 --- /dev/null +++ b/lib/application/log/cubit/log_cubit.dart @@ -0,0 +1,41 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:logging/logging.dart'; +import 'package:nyrna/infrastructure/logger/log_file.dart'; + +part 'log_state.dart'; + +late LogCubit logCubit; + +class LogCubit extends Cubit { + LogCubit() + : super( + LogState( + logLevel: Level.INFO, + logsText: '', + ), + ) { + logCubit = this; + getLogsText(state.logLevel); + } + + void getLogsText(Level level) { + String logsText = ''; + LogFile.logs.forEach( + (LogRecord record) { + // Add if the record's level matches the user's choice. + if (record.level == level || level == Level.ALL) { + logsText = '${record.time} \n' + '${record.level.name} \n' + 'Logger: ${record.loggerName} \n' + '${record.message} \n' + '\n'; + } + }, + ); + emit(state.copyWith( + logLevel: level, + logsText: logsText, + )); + } +} diff --git a/lib/application/log/cubit/log_state.dart b/lib/application/log/cubit/log_state.dart new file mode 100644 index 00000000..150bee1f --- /dev/null +++ b/lib/application/log/cubit/log_state.dart @@ -0,0 +1,26 @@ +part of 'log_cubit.dart'; + +class LogState extends Equatable { + /// The level of logs to show, changed with the DropdownButton. + final Level logLevel; + + final String logsText; + + const LogState({ + required this.logLevel, + required this.logsText, + }); + + @override + List get props => [logLevel, logsText]; + + LogState copyWith({ + Level? logLevel, + String? logsText, + }) { + return LogState( + logLevel: logLevel ?? this.logLevel, + logsText: logsText ?? this.logsText, + ); + } +} diff --git a/lib/presentation/logs/pages/log_page.dart b/lib/presentation/logs/pages/log_page.dart index 4ada6ab5..ec6df627 100644 --- a/lib/presentation/logs/pages/log_page.dart +++ b/lib/presentation/logs/pages/log_page.dart @@ -1,111 +1,99 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:logging/logging.dart'; -import 'package:nyrna/infrastructure/logger/log_file.dart'; +import 'package:nyrna/application/log/cubit/log_cubit.dart'; /// Display Nyrna's logs. -class LogPage extends StatefulWidget { - static final id = 'LogScreen'; - - @override - _LogPageState createState() => _LogPageState(); -} - -class _LogPageState extends State { - /// The level of logs to show, changed with the DropdownButton. - Level level = Level.INFO; - - String logsText = ''; +class LogPage extends StatelessWidget { + static final id = 'log_page'; @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(), - body: Padding( - padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 30), - child: Column( - children: [ - Row( - children: [ - const Text('Log level'), - const SizedBox(width: 10), - DropdownButton( - value: level, - onChanged: (Level? newLevel) { - setState(() => level = newLevel!); - }, - items: const [ - DropdownMenuItem( - value: Level.INFO, - child: Text('INFO'), - ), - DropdownMenuItem( - value: Level.WARNING, - child: Text('WARNING'), - ), - DropdownMenuItem( - value: Level.SEVERE, - child: Text('SEVERE'), - ), - DropdownMenuItem( - value: Level.ALL, - child: Text('ALL'), + return BlocProvider( + create: (context) => LogCubit(), + child: Scaffold( + appBar: AppBar(), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 30), + child: Column( + children: [ + Row( + children: [ + const Text('Log level'), + const SizedBox(width: 10), + BlocBuilder( + builder: (context, state) { + return DropdownButton( + value: state.logLevel, + onChanged: (level) => logCubit.getLogsText(level!), + items: const [ + DropdownMenuItem( + value: Level.INFO, + child: Text('INFO'), + ), + DropdownMenuItem( + value: Level.WARNING, + child: Text('WARNING'), + ), + DropdownMenuItem( + value: Level.SEVERE, + child: Text('SEVERE'), + ), + DropdownMenuItem( + value: Level.ALL, + child: Text('ALL'), + ), + ], + ); + }, + ), + Spacer(), + BlocBuilder( + builder: (context, state) { + return ElevatedButton( + onPressed: () async { + // Copy the visible logs to user's clipboard. + await Clipboard.setData( + ClipboardData(text: state.logsText), + ); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Logs copied to clipboard'), + ), + ); + }, + child: const Text('Copy'), + ); + }, + ), + ], + ), + Flexible( + child: Container( + color: Colors.grey[800], + width: double.infinity, + height: double.infinity, + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 15, + ), + child: Scrollbar( + isAlwaysShown: true, + child: SingleChildScrollView( + child: BlocBuilder( + builder: (context, state) { + return SelectableText(state.logsText); + }, + ), ), - ], - ), - // Add spacing so the button is at the far right. - Expanded(child: Container()), - ElevatedButton( - onPressed: () async { - // Copy the visible logs to user's clipboard. - await Clipboard.setData(ClipboardData(text: logsText)); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Logs copied to clipboard')), - ); - }, - child: Text('Copy'), - ), - ], - ), - Flexible( - flex: 1, - child: Container( - color: Colors.grey[800], - width: double.infinity, - height: double.infinity, - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 15, - ), - child: Scrollbar( - isAlwaysShown: true, - child: SingleChildScrollView( - child: _logText(), ), ), ), - ), - ], + ], + ), ), ), ); } - - SelectableText _logText() { - logsText = ''; - LogFile.logs.forEach( - (LogRecord record) { - // Add if the record's level matches the user's choice. - if (record.level == level || level == Level.ALL) { - logsText = logsText + - '${record.time} \n' - '${record.level.name} \n' - 'Logger: ${record.loggerName} \n' - '${record.message} \n' - '\n'; - } - }, - ); - return SelectableText(logsText); - } } From f7659117512f3c8f315e3d5713c1c813bcab758c Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 31 Jul 2021 13:33:20 -0400 Subject: [PATCH 33/83] Strain the spaghetti --- .../active_window/active_window.dart | 15 +- lib/application/app/cubit/app_cubit.dart | 57 +++-- lib/application/app/cubit/app_state.dart | 6 +- .../window/cubit/window_cubit.dart | 91 ++++++++ .../window/cubit/window_state.dart | 45 ++++ lib/domain/native_platform/models/models.dart | 2 + .../native_platform/models/process.dart | 36 +++ lib/domain/native_platform/models/window.dart | 21 ++ .../native_platform/native_platform.dart | 1 + .../native_platform/native_platform.dart | 3 +- .../native_platform/src/linux/linux.dart | 71 ++++-- .../src/linux/linux_process.dart | 17 +- .../src/linux/linux_window.dart | 22 -- .../native_platform/src/native_platform.dart | 17 +- .../src/{process.dart => native_process.dart} | 19 +- .../native_platform/src/win32/win32.dart | 62 +++--- .../src/win32/win32_process.dart | 12 +- .../src/win32/win32_window.dart | 12 - .../native_platform/src/window.dart | 49 ----- lib/main.dart | 8 +- lib/presentation/app/pages/apps_page.dart | 32 +-- lib/presentation/app/widgets/widgets.dart | 1 + lib/presentation/app/widgets/window_tile.dart | 208 +++++++++--------- pubspec.lock | 2 +- pubspec.yaml | 1 - test/platform/native_platform_test.dart | 13 +- test/process/process_test.dart | 7 +- 27 files changed, 506 insertions(+), 324 deletions(-) create mode 100644 lib/application/window/cubit/window_cubit.dart create mode 100644 lib/application/window/cubit/window_state.dart create mode 100644 lib/domain/native_platform/models/models.dart create mode 100644 lib/domain/native_platform/models/process.dart create mode 100644 lib/domain/native_platform/models/window.dart create mode 100644 lib/domain/native_platform/native_platform.dart delete mode 100644 lib/infrastructure/native_platform/src/linux/linux_window.dart rename lib/infrastructure/native_platform/src/{process.dart => native_process.dart} (81%) delete mode 100644 lib/infrastructure/native_platform/src/win32/win32_window.dart delete mode 100644 lib/infrastructure/native_platform/src/window.dart diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index 51e19f4f..db819473 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -3,10 +3,11 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:nyrna/domain/arguments/argument_parser.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/infrastructure/native_platform/src/process.dart'; +import 'package:nyrna/infrastructure/native_platform/src/native_process.dart'; import 'package:win32/win32.dart'; /// Represents the active, foreground window on the system. @@ -15,8 +16,6 @@ import 'package:win32/win32.dart'; class ActiveWindow { final _nativePlatform = NativePlatform(); - final _windowControls = WindowControls(); - static final _log = Logger('ActiveWindow'); final _prefs = Preferences(); @@ -101,7 +100,7 @@ class ActiveWindow { /// Check that saved process still exists. Future _checkStillExists(int savedPid) async { - final savedProcess = Process(savedPid); + final savedProcess = NativeProcess(savedPid); final exists = await savedProcess.exists(); if (!exists) { await _removeSavedProcess(); @@ -132,7 +131,7 @@ class ActiveWindow { required int id, }) async { var successful = false; - final process = Process(pid); + final process = NativeProcess(pid); final _status = await process.status; if (_status == ProcessStatus.unknown) { await _removeSavedProcess(); @@ -145,15 +144,15 @@ class ActiveWindow { _log.warning('Failed to resume PID: $pid'); return successful; } - await _windowControls.restore(id); + await NativePlatform().restoreWindow(id); } return successful; } Future _suspend() async { var successful = false; - final process = Process(pid); - await _windowControls.minimize(id); + final process = NativeProcess(pid); + await NativePlatform().minimizeWindow(id!); // Small delay on Windows to ensure the window actually minimizes. // Doesn't seem to be necessary on Linux. if (io.Platform.isWindows) { diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index 75e86f37..de99e1e1 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -4,6 +4,7 @@ import 'dart:io' as io; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/infrastructure/versions/versions.dart'; @@ -15,11 +16,13 @@ part 'app_state.dart'; late AppCubit appCubit; class AppCubit extends Cubit { - final NativePlatform nativePlatform; + final NativePlatform _nativePlatform; final Preferences _prefs; - AppCubit(Preferences prefs) - : nativePlatform = NativePlatform(), + AppCubit({ + required NativePlatform nativePlatform, + required Preferences prefs, + }) : _nativePlatform = nativePlatform, _prefs = prefs, super(AppState.initial()) { appCubit = this; @@ -61,34 +64,24 @@ class AppCubit extends Cubit { Future fetchData() async { await _fetchDesktop(); - await fetchWindows(); + await _fetchWindows(); } Future _fetchDesktop() async { - final currentDesktop = await nativePlatform.currentDesktop; + final currentDesktop = await _nativePlatform.currentDesktop; emit(state.copyWith(currentDesktop: currentDesktop)); } - /// Check for which windows are open. - Future fetchWindows() async { - final newWindows = await nativePlatform.windows; - final windows = Map.from(state.windows); - // Remove if window no longer present, or title has changed. - windows.removeWhere((pid, window) { - if (!newWindows.containsKey(pid) || // Window no longer present. - (newWindows[pid]!.title != window.title)) // Window title changed. - { - return true; - } else { - return false; - } - }); - // Filter out Nyrna's own window / process. - newWindows.removeWhere((pid, window) => pid == io.pid.toString()); - // Add new windows (and those whose title changed). - newWindows.forEach((pid, window) { - if (!windows.containsKey(pid)) windows[pid] = window; + /// Populate the list of visible windows. + Future _fetchWindows() async { + final windows = await _nativePlatform.windows(); + await Future.forEach(windows, (window) async { + final process = await _nativePlatform.windowProcess(window.id); + window.process = process; }); + windows.removeWhere( + (window) => _filteredWindows.contains(window.process!.executable), + ); emit(state.copyWith(windows: windows)); } @@ -113,3 +106,19 @@ class AppCubit extends Cubit { : throw 'Could not launch url: $url'; } } + +/// System-level or non-app executables. Nyrna shouldn't show these. +List _filteredWindows = [ + 'nyrna.exe', + 'ApplicationFrameHost.exe', // Manages UWP (Universal Windows Platform) apps + 'explorer.exe', // Windows File Explorer + 'googledrivesync.exe', + 'LogiOverlay.exe', // Logitech Options + 'PenTablet.exe', // XP-PEN driver + 'perfmon.exe', // Resource Monitor + 'Rainmeter.exe', + 'SystemSettings.exe', // Windows system settings + 'Taskmgr.exe', // Windows Task Manager + 'TextInputHost.exe', // Microsoft Text Input Application + 'WinStore.App.exe', // Windows Store +]; diff --git a/lib/application/app/cubit/app_state.dart b/lib/application/app/cubit/app_state.dart index 7e58f567..0e6bff7d 100644 --- a/lib/application/app/cubit/app_state.dart +++ b/lib/application/app/cubit/app_state.dart @@ -12,7 +12,7 @@ class AppState extends Equatable { /// The index of the currently active virtual desktop. final int currentDesktop; - final Map windows; + final List windows; const AppState({ required this.isPortable, @@ -30,7 +30,7 @@ class AppState extends Equatable { updateVersion: '', updateAvailable: false, currentDesktop: 0, - windows: {}, + windows: [], ); } @@ -52,7 +52,7 @@ class AppState extends Equatable { String? updateVersion, bool? updateAvailable, int? currentDesktop, - Map? windows, + List? windows, }) { return AppState( isPortable: isPortable ?? this.isPortable, diff --git a/lib/application/window/cubit/window_cubit.dart b/lib/application/window/cubit/window_cubit.dart new file mode 100644 index 00000000..fb1206ea --- /dev/null +++ b/lib/application/window/cubit/window_cubit.dart @@ -0,0 +1,91 @@ +import 'package:collection/collection.dart'; +import 'dart:io' as io; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; +import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; + +part 'window_state.dart'; + +enum ToggleError { + None, + Suspend, + Resume, +} + +class WindowCubit extends Cubit { + final AppCubit _appCubit; + final NativePlatform _nativePlatform; + final Window _window; + + WindowCubit({ + required AppCubit appCubit, + required NativePlatform nativePlatform, + required Window window, + }) : _appCubit = appCubit, + _nativePlatform = nativePlatform, + _window = window, + super( + WindowState( + executable: window.process?.executable ?? '', + pid: window.process?.pid ?? 0, + processStatus: window.process?.status ?? ProcessStatus.unknown, + title: window.title, + toggleError: ToggleError.None, + ), + ) { + _initialize(); + } + + Future _initialize() async { + _listen(); + } + + void _listen() { + _appCubit.stream.listen((event) { + final window = event.windows.firstWhereOrNull((e) => e.id == _window.id); + if (window != null) { + emit(state.copyWith( + processStatus: window.process?.status, + title: window.title, + )); + } else { + close(); + } + }); + } + + /// Toggle suspend / resume for the process associated with the given window. + Future toggle() async { + if (state.processStatus == ProcessStatus.suspended) { + await _resume(); + } else { + await _suspend(); + } + } + + Future _resume() async { + final nativeProcess = NativeProcess(state.pid); + final successful = await nativeProcess.resume(); + if (!successful) emit(state.copyWith(toggleError: ToggleError.Resume)); + // Restore the window _after_ resuming or it might not restore. + await _nativePlatform.restoreWindow(_window.id); + } + + Future _suspend() async { + // Minimize the window before suspending or it might not minimize. + await _nativePlatform.minimizeWindow(_window.id); + // Small delay on Win32 to ensure the window actually minimizes. + // Doesn't seem to be necessary on Linux. + if (io.Platform.isWindows) { + await Future.delayed(Duration(milliseconds: 500)); + } + final nativeProcess = NativeProcess(state.pid); + final successful = await nativeProcess.suspend(); + if (!successful) emit(state.copyWith(toggleError: ToggleError.Suspend)); + await _appCubit.fetchData(); + } +} diff --git a/lib/application/window/cubit/window_state.dart b/lib/application/window/cubit/window_state.dart new file mode 100644 index 00000000..ecc0e593 --- /dev/null +++ b/lib/application/window/cubit/window_state.dart @@ -0,0 +1,45 @@ +part of 'window_cubit.dart'; + +@immutable +class WindowState extends Equatable { + final String executable; + final int pid; + final ProcessStatus processStatus; + final String title; + final ToggleError toggleError; + + const WindowState({ + required this.executable, + required this.pid, + required this.processStatus, + required this.title, + required this.toggleError, + }); + + @override + List get props { + return [ + executable, + pid, + processStatus, + title, + toggleError, + ]; + } + + WindowState copyWith({ + String? executable, + int? pid, + ProcessStatus? processStatus, + String? title, + ToggleError? toggleError, + }) { + return WindowState( + executable: executable ?? this.executable, + pid: pid ?? this.pid, + processStatus: processStatus ?? this.processStatus, + title: title ?? this.title, + toggleError: toggleError ?? this.toggleError, + ); + } +} diff --git a/lib/domain/native_platform/models/models.dart b/lib/domain/native_platform/models/models.dart new file mode 100644 index 00000000..068bb754 --- /dev/null +++ b/lib/domain/native_platform/models/models.dart @@ -0,0 +1,2 @@ +export 'process.dart'; +export 'window.dart'; diff --git a/lib/domain/native_platform/models/process.dart b/lib/domain/native_platform/models/process.dart new file mode 100644 index 00000000..338c782e --- /dev/null +++ b/lib/domain/native_platform/models/process.dart @@ -0,0 +1,36 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter/foundation.dart'; + +enum ProcessStatus { + normal, + suspended, + unknown, +} + +@immutable +class Process extends Equatable { + final String executable; + final int pid; + final ProcessStatus status; + + Process({ + required this.executable, + required this.pid, + required this.status, + }); + + @override + List get props => [executable, pid, status]; + + Process copyWith({ + String? executable, + int? pid, + ProcessStatus? status, + }) { + return Process( + executable: executable ?? this.executable, + pid: pid ?? this.pid, + status: status ?? this.status, + ); + } +} diff --git a/lib/domain/native_platform/models/window.dart b/lib/domain/native_platform/models/window.dart new file mode 100644 index 00000000..d688edf2 --- /dev/null +++ b/lib/domain/native_platform/models/window.dart @@ -0,0 +1,21 @@ +import '../native_platform.dart'; + +/// Represents a visible window on the current desktop. +class Window { + /// The unique window ID number associated with this window. + final int id; + + /// The process associated with this window. + Process? process; + + /// The title of this window, often shown on the window's 'Title Bar'. + /// + /// Can & does change, for example a browser shows the title of the page. + final String title; + + Window({ + required this.id, + this.process, + required this.title, + }); +} diff --git a/lib/domain/native_platform/native_platform.dart b/lib/domain/native_platform/native_platform.dart new file mode 100644 index 00000000..51b02151 --- /dev/null +++ b/lib/domain/native_platform/native_platform.dart @@ -0,0 +1 @@ +export 'models/models.dart'; diff --git a/lib/infrastructure/native_platform/native_platform.dart b/lib/infrastructure/native_platform/native_platform.dart index f8f8bffe..70a6bf66 100644 --- a/lib/infrastructure/native_platform/native_platform.dart +++ b/lib/infrastructure/native_platform/native_platform.dart @@ -1,3 +1,2 @@ export 'src/native_platform.dart'; -export 'src/process.dart'; -export 'src/window.dart'; +export 'src/native_process.dart'; diff --git a/lib/infrastructure/native_platform/src/linux/linux.dart b/lib/infrastructure/native_platform/src/linux/linux.dart index 735a6b13..be76bd36 100644 --- a/lib/infrastructure/native_platform/src/linux/linux.dart +++ b/lib/infrastructure/native_platform/src/linux/linux.dart @@ -1,7 +1,9 @@ -import 'dart:io'; +import 'dart:io' as io; + +import 'package:nyrna/domain/native_platform/native_platform.dart'; +import 'package:nyrna/infrastructure/native_platform/src/linux/linux_process.dart'; import '../native_platform.dart'; -import '../window.dart'; /// Interact with the native Linux operating system. class Linux implements NativePlatform { @@ -10,7 +12,7 @@ class Linux implements NativePlatform { // Active virtual desktop as reported by wmctrl. @override Future get currentDesktop async { - final result = await Process.run('wmctrl', ['-d']); + final result = await io.Process.run('wmctrl', ['-d']); final lines = result.stdout.toString().split('\n'); lines.forEach((line) { if (line.contains('*')) _desktop = int.tryParse(line[0]); @@ -20,10 +22,10 @@ class Linux implements NativePlatform { // Gets all open windows as reported by wmctrl. @override - Future> get windows async { + Future> windows() async { await currentDesktop; - final windows = {}; - final result = await Process.run('bash', ['-c', 'wmctrl -lp']); + final windows = []; + final result = await io.Process.run('bash', ['-c', 'wmctrl -lp']); // Each line from wmctrl will be something like: // 0x03600041 1 1459 SHODAN Inbox - Unified Folders - Mozilla Thunderbird // windowId, desktopId, pid, user, window title @@ -38,11 +40,10 @@ class Linux implements NativePlatform { final pid = int.tryParse(parts[2]); final id = int.tryParse(parts[0]); if ((pid == null) || (id == null)) return; - windows[pid.toString()] = Window( - title: parts.sublist(4).join(' '), - pid: pid, + windows.add(Window( id: id, - ); + title: parts.sublist(4).join(' '), + )); } } }); @@ -52,7 +53,7 @@ class Linux implements NativePlatform { // Returns the PID of the active window as reported by xdotool. @override Future get activeWindowPid async { - final result = await Process.run( + final result = await io.Process.run( 'xdotool', ['getactivewindow', 'getwindowpid'], ); @@ -63,7 +64,7 @@ class Linux implements NativePlatform { // Returns the unique hex ID of the active window as reported by xdotool. @override Future get activeWindowId async { - final result = await Process.run('xdotool', ['getactivewindow']); + final result = await io.Process.run('xdotool', ['getactivewindow']); final _windowId = int.tryParse(result.stdout.toString().trim()); return _windowId ?? 0; } @@ -72,15 +73,57 @@ class Linux implements NativePlatform { @override Future checkDependencies() async { try { - await Process.run('wmctrl', ['-d']); + await io.Process.run('wmctrl', ['-d']); } catch (err) { return false; } try { - await Process.run('xdotool', ['getactivewindow']); + await io.Process.run('xdotool', ['getactivewindow']); } catch (err) { return false; } return true; } + + @override + Future windowPid(int windowId) async { + final result = await io.Process.run( + 'xdotool', + ['$windowId', 'getwindowpid'], + ); + final _pid = int.tryParse(result.stdout.toString().trim()); + return _pid ?? 0; + } + + @override + Future windowProcess(int windowId) async { + final pid = await windowPid(windowId); + final linuxProcess = LinuxProcess(pid); + final executable = await linuxProcess.executable; + final status = await linuxProcess.status; + final process = Process(executable: executable, pid: pid, status: status); + return process; + } + + @override + Future minimizeWindow(int windowId) async { + final result = await io.Process.run( + 'xdotool', + ['windowminimize', '$windowId', '--sync'], + ); + return true; + // TODO: Check for possible stderr for meaningful return value. + // result.stderr + } + + @override + Future restoreWindow(int windowId) async { + final result = await io.Process.run( + 'xdotool', + ['windowactivate', '$windowId', '--sync'], + ); + return true; + // TODO: Check for possible stderr for meaningful return value. + // result.stderr + } } diff --git a/lib/infrastructure/native_platform/src/linux/linux_process.dart b/lib/infrastructure/native_platform/src/linux/linux_process.dart index 461601c1..6598c448 100644 --- a/lib/infrastructure/native_platform/src/linux/linux_process.dart +++ b/lib/infrastructure/native_platform/src/linux/linux_process.dart @@ -1,10 +1,10 @@ import 'dart:io' as io; -import 'package:flutter/foundation.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; -import '../process.dart'; +import '../native_process.dart'; -class LinuxProcess with ChangeNotifier implements Process { +class LinuxProcess implements NativeProcess { LinuxProcess(this.pid); @override @@ -52,7 +52,6 @@ class LinuxProcess with ChangeNotifier implements Process { ? io.ProcessSignal.sigstop : io.ProcessSignal.sigcont; final successful = io.Process.killPid(pid, signal); - notifyListeners(); return successful; } @@ -65,4 +64,14 @@ class LinuxProcess with ChangeNotifier implements Process { final checkedPid = int.tryParse(result.stdout.toString().trim()); return (checkedPid == pid) ? true : false; } + + @override + Future resume() async { + return io.Process.killPid(pid, io.ProcessSignal.sigcont); + } + + @override + Future suspend() async { + return io.Process.killPid(pid, io.ProcessSignal.sigstop); + } } diff --git a/lib/infrastructure/native_platform/src/linux/linux_window.dart b/lib/infrastructure/native_platform/src/linux/linux_window.dart deleted file mode 100644 index 628b7f58..00000000 --- a/lib/infrastructure/native_platform/src/linux/linux_window.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'dart:io'; - -import '../window.dart'; - -/// Linux specific window controls using `xdotool`. -class LinuxWindowControls implements WindowControls { - @override - Future minimize(int? id) async { - await Process.run( - 'xdotool', - ['windowminimize', '$id', '--sync'], - ); - } - - @override - Future restore(int? id) async { - await Process.run( - 'xdotool', - ['windowactivate', '$id', '--sync'], - ); - } -} diff --git a/lib/infrastructure/native_platform/src/native_platform.dart b/lib/infrastructure/native_platform/src/native_platform.dart index a71c5145..4dce97ef 100644 --- a/lib/infrastructure/native_platform/src/native_platform.dart +++ b/lib/infrastructure/native_platform/src/native_platform.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:nyrna/infrastructure/native_platform/src/window.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'linux/linux.dart'; import 'win32/win32.dart'; @@ -22,9 +22,14 @@ abstract class NativePlatform { /// Returns the index of the currently active virtual desktop. Future get currentDesktop; - /// Returns a Map where the keys are the `pid` and the values are [Window] - /// objects, based on the reported open application windows. - Future> get windows; + /// The PID associated with a window. + Future windowPid(int windowId); + + /// The process associated with a window. + Future windowProcess(int windowId); + + /// List of [Window] objects for every visible window with title text. + Future> windows(); /// Returns the pid associated with the active window. Future get activeWindowPid; @@ -34,4 +39,8 @@ abstract class NativePlatform { /// Verify dependencies are present on the system. Future checkDependencies(); + + Future minimizeWindow(int windowId); + + Future restoreWindow(int windowId); } diff --git a/lib/infrastructure/native_platform/src/process.dart b/lib/infrastructure/native_platform/src/native_process.dart similarity index 81% rename from lib/infrastructure/native_platform/src/process.dart rename to lib/infrastructure/native_platform/src/native_process.dart index 7d378cf1..0468e619 100644 --- a/lib/infrastructure/native_platform/src/process.dart +++ b/lib/infrastructure/native_platform/src/native_process.dart @@ -1,27 +1,20 @@ import 'dart:io' as io; -import 'package:flutter/foundation.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'linux/linux_process.dart'; import 'win32/win32.dart'; -/// Represents the running state of a process. -enum ProcessStatus { - normal, - suspended, - unknown, -} - /// Represents a process including its metadata and controls. /// /// Abstract class bridges types for specific operating systems. /// Used by [LinuxProcess] and [Win32Process]. -abstract class Process with ChangeNotifier { +abstract class NativeProcess { // ignore: unused_element - Process._unused(this.pid); + NativeProcess._unused(this.pid); // Return correct subtype depending on the current operating system. - factory Process(int pid) { + factory NativeProcess(int pid) { if (io.Platform.isLinux) { return LinuxProcess(pid); } else { @@ -48,4 +41,8 @@ abstract class Process with ChangeNotifier { /// /// ActiveWindow uses this to check a saved pid is still around. Future exists(); + + Future suspend(); + + Future resume(); } diff --git a/lib/infrastructure/native_platform/src/win32/win32.dart b/lib/infrastructure/native_platform/src/win32/win32.dart index 741ff79c..d8f4617e 100644 --- a/lib/infrastructure/native_platform/src/win32/win32.dart +++ b/lib/infrastructure/native_platform/src/win32/win32.dart @@ -1,7 +1,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -// import 'package:nyrna/platform/win32/user32.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:win32/win32.dart'; @@ -19,19 +19,21 @@ class Win32 implements NativePlatform { Future get currentDesktop async => 0; @override - Future> get windows async { - // Clear the map to ensure we are starting fresh each time. - WindowBuilder.windows.clear(); + Future> windows() async { // Process open windows. EnumWindows(WindowBuilder.callback, 0); - return WindowBuilder.windows; + final windows = List.from(WindowBuilder.windows); + // Clear the map to ensure we are starting fresh each time. + WindowBuilder.windows.clear(); + return windows; } late int _windowPid; /// Takes the window handle as an argument and returns the /// pid of the associated process. - int getWindowPid(int windowId) { + @override + Future windowPid(int windowId) async { // GetWindowThreadProcessId will assign the PID to this pointer. final _pid = calloc(); // Populate the `_pid` pointer. @@ -46,7 +48,7 @@ class Win32 implements NativePlatform { @override Future get activeWindowPid async { final windowId = await activeWindowId; - return getWindowPid(windowId); + return windowPid(windowId); } @override @@ -55,6 +57,28 @@ class Win32 implements NativePlatform { // No external dependencies for Win32, so always return true. @override Future checkDependencies() async => true; + + @override + Future windowProcess(int windowId) async { + final pid = await windowPid(windowId); + final win32Process = Win32Process(pid); + final executable = await win32Process.executable; + final status = await win32Process.status; + final process = Process(executable: executable, pid: pid, status: status); + return process; + } + + @override + Future minimizeWindow(int windowId) async { + ShowWindow(windowId, SW_FORCEMINIMIZE); + return true; // [ShowWindow] return value doesn't confirm success. + } + + @override + Future restoreWindow(int windowId) async { + ShowWindow(windowId, SW_RESTORE); + return true; // [ShowWindow] return value doesn't confirm success. + } } // Static methods required because the win32 callback is required to be static. @@ -117,30 +141,10 @@ class WindowBuilder { return (cloakedReason == 0) ? false : true; } - static Map windows = {}; + static List windows = []; /// Called during the callback for every window to map the data. static Future _buildWindowMap(int windowId, String title) async { - final pid = Win32().getWindowPid(windowId); - final process = Win32Process(pid); - final executable = await process.executable; - if (!_filterWindows.contains(executable)) { - windows[pid.toString()] = Window( - title: title, - id: windowId, - pid: pid, - ); - } + windows.add(Window(id: windowId, title: title)); } } - -/// System-level executables. Nyrna shouldn't show these. -List _filterWindows = [ - 'ApplicationFrameHost.exe', // Manages UWP (Universal Windows Platform) apps - 'explorer.exe', // Windows File Explorer - 'perfmon.exe', // Resource Monitor - 'SystemSettings.exe', // Windows system settings - 'Taskmgr.exe', // Windows Task Manager - 'TextInputHost.exe', // Microsoft Text Input Application - 'WinStore.App.exe', // Windows Store -]; diff --git a/lib/infrastructure/native_platform/src/win32/win32_process.dart b/lib/infrastructure/native_platform/src/win32/win32_process.dart index 802dace5..0d3874cb 100644 --- a/lib/infrastructure/native_platform/src/win32/win32_process.dart +++ b/lib/infrastructure/native_platform/src/win32/win32_process.dart @@ -2,14 +2,14 @@ import 'dart:ffi'; import 'dart:io' as io; import 'package:ffi/ffi.dart'; -import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:win32/win32.dart'; import 'package:win32_suspend_process/win32_suspend_process.dart' as w32proc; -import '../process.dart'; +import '../native_process.dart'; -class Win32Process with ChangeNotifier implements Process { +class Win32Process implements NativeProcess { Win32Process(this.pid); @override @@ -108,6 +108,12 @@ class Win32Process with ChangeNotifier implements Process { return _success; } + @override + Future suspend() async => w32proc.Win32Process(pid).suspend(); + + @override + Future resume() async => w32proc.Win32Process(pid).resume(); + // If the pid doesn't exist this won't be able to return the exe name. @override Future exists() async { diff --git a/lib/infrastructure/native_platform/src/win32/win32_window.dart b/lib/infrastructure/native_platform/src/win32/win32_window.dart deleted file mode 100644 index 62001e31..00000000 --- a/lib/infrastructure/native_platform/src/win32/win32_window.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:win32/win32.dart'; - -import '../window.dart'; - -/// Win32 specific window controls using the win32 API. -class Win32WindowControls implements WindowControls { - @override - Future minimize(int? id) async => ShowWindow(id!, SW_FORCEMINIMIZE); - - @override - Future restore(int? id) async => ShowWindow(id!, SW_RESTORE); -} diff --git a/lib/infrastructure/native_platform/src/window.dart b/lib/infrastructure/native_platform/src/window.dart deleted file mode 100644 index bf93553e..00000000 --- a/lib/infrastructure/native_platform/src/window.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:io'; - -import 'linux/linux_window.dart'; -import 'win32/win32_window.dart'; - -/// Represents a visible window on the current desktop. -class Window { - Window({ - required this.id, - required this.pid, - required this.title, - }); - - final _windowControls = WindowControls(); - - /// The unique window ID number associated with this window. - final int id; - - /// The PID of the process associated with this window. - final int pid; - - /// The title of this window, often shown on the window's 'Title Bar'. - /// - /// Can & does change, for example a browser shows the title of the page. - final String title; - - /// Minimize this window. - Future minimize() async => await _windowControls.minimize(id); - - /// Restore (un-minimize) this window. - Future restore() async => await _windowControls.restore(id); -} - -/// Provides window actions like [minimize] & [restore]. -abstract class WindowControls { - factory WindowControls() { - if (Platform.isLinux) { - return LinuxWindowControls(); - } else { - return Win32WindowControls(); - } - } - - /// Minimize the window associated with the given [id]. - Future minimize(int? id); - - /// Restore (un-minimize) the window associated with the given [id]. - Future restore(int? id); -} diff --git a/lib/main.dart b/lib/main.dart index 4f23f2ff..d5b8e247 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/bloc_observer.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; +import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/application/active_window/active_window.dart'; @@ -27,11 +28,16 @@ Future main(List args) async { Bloc.observer = AppBlocObserver(); + final nativePlatform = NativePlatform(); + runApp( MultiBlocProvider( providers: [ BlocProvider( - create: (context) => AppCubit(prefs), + create: (context) => AppCubit( + nativePlatform: nativePlatform, + prefs: prefs, + ), lazy: false, ), BlocProvider( diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index db3d0f7a..f1b44f18 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -6,10 +6,10 @@ import 'package:logging/logging.dart'; import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; +import 'package:nyrna/application/window/cubit/window_cubit.dart'; import 'package:nyrna/presentation/app/widgets/window_tile.dart'; import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; /// The main screen for Nyrna. @@ -40,22 +40,22 @@ class _AppsPageState extends State { width: MediaQuery.of(context).size.width / 1.20, child: BlocBuilder( builder: (context, state) { - return ListView.builder( + return ListView( padding: const EdgeInsets.only(top: 40), - itemCount: state.windows.length, - itemBuilder: (context, index) { - if (state.windows.isEmpty) return Container(); - var keys = state.windows.keys.toList(); - var window = state.windows[keys[index]]!; - return ChangeNotifierProvider( - key: ValueKey('${window.pid}${window.title}'), - create: (context) => Process(window.pid), - child: WindowTile( - key: ValueKey('${window.pid}${window.title}'), - window: window, - ), - ); - }, + children: [ + ...state.windows + .map( + (window) => BlocProvider( + create: (context) => WindowCubit( + appCubit: appCubit, + nativePlatform: NativePlatform(), + window: window, + ), + child: WindowTile(key: ValueKey(window.id)), + ), + ) + .toList(), + ], ); }, ), diff --git a/lib/presentation/app/widgets/widgets.dart b/lib/presentation/app/widgets/widgets.dart index e69de29b..2d6d7979 100644 --- a/lib/presentation/app/widgets/widgets.dart +++ b/lib/presentation/app/widgets/widgets.dart @@ -0,0 +1 @@ +export 'window_tile.dart'; diff --git a/lib/presentation/app/widgets/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart index 371b8ec1..2c18e26a 100644 --- a/lib/presentation/app/widgets/window_tile.dart +++ b/lib/presentation/app/widgets/window_tile.dart @@ -1,134 +1,122 @@ -import 'dart:io' as io; - import 'package:flutter/material.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/window/cubit/window_cubit.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; /// Represents a visible window on the desktop, running state and actions. -class WindowTile extends StatefulWidget { - WindowTile({this.window, this.key}); - - /// Key is overridden to ensure unique, non-double entries. - @override - final Key? key; - - /// The visible window. - final Window? window; - - @override - _WindowTileState createState() => _WindowTileState(); -} - -class _WindowTileState extends State { - /// The process associated with the window. - late Process process; - - /// The visible window. - Window? window; - - @override - void initState() { - super.initState(); - window = widget.window; - WidgetsBinding.instance!.addPostFrameCallback((_) { - process = Provider.of(context, listen: false); - }); - } +class WindowTile extends StatelessWidget { + const WindowTile({ + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { - return Card( - child: ListTile( - leading: _statusWidget(), - title: Text(window!.title), - subtitle: _executableNameWidget(), - contentPadding: const EdgeInsets.symmetric( - vertical: 2, - horizontal: 20, + return BlocListener( + listener: (context, state) { + if (state.toggleError == ToggleError.Suspend) { + _showSnackError(context, ToggleError.Suspend); + } else if (state.toggleError == ToggleError.Resume) { + _showSnackError(context, ToggleError.Resume); + } + }, + child: Card( + child: ListTile( + leading: _StatusWidget(), + title: _TitleWidget(), + subtitle: _DetailsWidget(), + contentPadding: const EdgeInsets.symmetric( + vertical: 2, + horizontal: 20, + ), + onTap: () => context.read().toggle(), ), - onTap: () => _toggle(), ), ); } - /// Show the process' suspend status. Green = normal, orange = suspended. - Widget _statusWidget() { - return Consumer( - builder: (context, process, widget) { - return FutureBuilder( - future: process.status, - builder: (context, snapshot) { - return Container( - height: 20, - width: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: (snapshot.data == ProcessStatus.suspended) - ? Colors.orange[700] - : Colors.green, - ), - ); - }, - ); - }, - ); + Future _showSnackError( + BuildContext context, + ToggleError errorType, + ) async { + final state = context.read().state; + final name = state.executable; + final suspendMessage = 'There was a problem suspending $name'; + final resumeMessage = 'There was a problem resuming $name'; + final message = + (errorType == ToggleError.Suspend) ? suspendMessage : resumeMessage; + final snackBar = SnackBar(content: Text(message)); + ScaffoldMessenger.of(context).showSnackBar(snackBar); } +} + +class _StatusWidget extends StatelessWidget { + const _StatusWidget({ + Key? key, + }) : super(key: key); - /// Executable name, for example 'firefox' or 'firefox-bin'. - Widget _executableNameWidget() { - return FutureBuilder( - future: Provider.of(context, listen: false).executable, - builder: (BuildContext context, AsyncSnapshot snapshot) { - final executable = snapshot.data ?? ''; - if (snapshot.hasData) { - return Text(executable); + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + Color _color; + switch (state.processStatus) { + case ProcessStatus.normal: + _color = Colors.green; + break; + case ProcessStatus.suspended: + _color = Colors.orange[700]!; + break; + case ProcessStatus.unknown: + _color = Colors.grey; } - return const Text(''); + + return Container( + height: 20, + width: 20, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _color, + ), + ); }, ); } +} - /// Toggle suspend / resume for the process associated with the given window. - Future _toggle() async { - final _status = await process.status; - if (_status == ProcessStatus.suspended) { - await _resume(); - } else { - await _suspend(); - } - } +class _TitleWidget extends StatelessWidget { + const _TitleWidget({ + Key? key, + }) : super(key: key); - Future _suspend() async { - // Minimize the window before suspending or it might not minimize. - await window!.minimize(); - // Small delay on Win32 to ensure the window actually minimizes. - // Doesn't seem to be necessary on Linux. - if (io.Platform.isWindows) { - await Future.delayed(Duration(milliseconds: 500)); - } - final successful = await process.toggle(); - if (!successful) await _showSnackError(_ToggleError.Suspend); + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Text(state.title); + }, + ); } +} - Future _resume() async { - final successful = await process.toggle(); - if (!successful) await _showSnackError(_ToggleError.Resume); - // Restore the window _after_ resuming or it might not restore. - await window!.restore(); - } +class _DetailsWidget extends StatelessWidget { + const _DetailsWidget({Key? key}) : super(key: key); - Future _showSnackError(_ToggleError errorType) async { - final name = await process.executable; - final suspendMessage = 'There was a problem suspending $name'; - final resumeMessage = 'There was a problem resuming $name'; - final message = - (errorType == _ToggleError.Suspend) ? suspendMessage : resumeMessage; - final snackBar = SnackBar(content: Text(message)); - ScaffoldMessenger.of(context).showSnackBar(snackBar); + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + BlocBuilder( + builder: (context, state) { + return Text('PID: ${state.pid}'); + }, + ), + BlocBuilder( + builder: (context, state) { + return Text(state.executable); + }, + ), + ], + ); } } - -enum _ToggleError { - Suspend, - Resume, -} diff --git a/pubspec.lock b/pubspec.lock index 4b27239e..0d638c80 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -263,7 +263,7 @@ packages: source: hosted version: "4.2.1" provider: - dependency: "direct main" + dependency: transitive description: name: provider url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 9b02b51e..55d0186b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,6 @@ dependencies: http: ^0.13.3 logging: ^1.0.1 path_provider: ^2.0.1 - provider: ^5.0.0 pub_semver: ^2.0.0 shared_preferences: ^2.0.5 url_launcher: ^6.0.4 diff --git a/test/platform/native_platform_test.dart b/test/platform/native_platform_test.dart index 0b4ec735..b843bdbc 100644 --- a/test/platform/native_platform_test.dart +++ b/test/platform/native_platform_test.dart @@ -2,23 +2,22 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; void main() { - NativePlatform? nativePlatform; + NativePlatform nativePlatform = NativePlatform(); setUp(() => nativePlatform = NativePlatform()); - tearDown(() => nativePlatform = null); test('Can instantiate NativePlatform', () { expect(nativePlatform, isA()); }); test('currentDesktop is not null', () async { - var currentDesktop = await nativePlatform!.currentDesktop; + var currentDesktop = await nativePlatform.currentDesktop; print('currentDesktop: $currentDesktop'); expect(currentDesktop, isNotNull); }); test('windows getter is not empty', () async { - var windows = await nativePlatform!.windows; + var windows = await nativePlatform.windows(); print('windows found: ${windows.length}'); expect(windows, isNotEmpty); }); @@ -26,7 +25,7 @@ void main() { test( 'activeWindowPid is not null', () async { - var pid = await nativePlatform!.activeWindowPid; + var pid = await nativePlatform.activeWindowPid; print('Active window pid: $pid'); expect(pid, isNot(null)); }, @@ -34,14 +33,14 @@ void main() { test( 'activeWindowId is not null', () async { - var id = await nativePlatform!.activeWindowId; + var id = await nativePlatform.activeWindowId; print('Active window id: $id'); expect(id, isNot(null)); }, ); test('checkDependencies is not null', () async { - var haveDependencies = await nativePlatform!.checkDependencies(); + var haveDependencies = await nativePlatform.checkDependencies(); print('haveDependencies: $haveDependencies'); expect(haveDependencies, isA()); }); diff --git a/test/process/process_test.dart b/test/process/process_test.dart index 12d1080f..5b9f9626 100644 --- a/test/process/process_test.dart +++ b/test/process/process_test.dart @@ -1,17 +1,18 @@ import 'dart:io' as io; import 'package:flutter_test/flutter_test.dart'; +import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; void main() { final pid = io.pid; // Dart or Nyrna's own pid. - Process? process; + NativeProcess? process; - setUp(() => process = Process(pid)); + setUp(() => process = NativeProcess(pid)); tearDown(() => process = null); test('Can instantiate Process', () { - expect(process, isA()); + expect(process, isA()); }); group('pid', () { From c52d5f92e665721f38f13c2a44b5a62564630f8f Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 1 Aug 2021 09:39:11 -0400 Subject: [PATCH 34/83] Upgrade flutter_bloc --- pubspec.lock | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 0d638c80..69fb1631 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -117,7 +117,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "7.0.1" + version: "7.1.0" flutter_driver: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 55d0186b..97740c12 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,7 @@ dependencies: args: ^2.1.0 equatable: ^2.0.3 flex_color_picker: ^2.0.1 - flutter_bloc: ^7.0.1 + flutter_bloc: ^7.1.0 http: ^0.13.3 logging: ^1.0.1 path_provider: ^2.0.1 From d3a2c0bbf6f5a08261ef7512d66975c6a1712afe Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 1 Aug 2021 10:41:06 -0400 Subject: [PATCH 35/83] Update theme to correct snackbar color --- lib/application/theme/cubit/theme_state.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/application/theme/cubit/theme_state.dart b/lib/application/theme/cubit/theme_state.dart index 47bf6e8f..686853df 100644 --- a/lib/application/theme/cubit/theme_state.dart +++ b/lib/application/theme/cubit/theme_state.dart @@ -19,18 +19,13 @@ class ThemeState extends Equatable { backgroundColor: isPitchBlack ? pitchBlack : null, ); final cardColor = isPitchBlack ? pitchBlack : null; - final colorScheme = ThemeData().colorScheme.copyWith( - brightness: brightness, - secondary: Colors.lightBlueAccent, - ); final scaffoldBackgroundColor = isPitchBlack ? pitchBlack : null; - final toggleableActiveColor = isPitchBlack ? Colors.blue[900] : Colors.lightBlueAccent; return ThemeData( appBarTheme: appBarTheme, + brightness: brightness, cardColor: cardColor, - colorScheme: colorScheme, scaffoldBackgroundColor: scaffoldBackgroundColor, toggleableActiveColor: toggleableActiveColor, ); From d1d0ef2cc86a83895a36fe714eea44db3167fd36 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sun, 1 Aug 2021 10:43:38 -0400 Subject: [PATCH 36/83] Refactor app page --- lib/presentation/app/pages/apps_page.dart | 113 +----------------- .../app/widgets/custom_app_bar.dart | 100 ++++++++++++++++ lib/presentation/app/widgets/widgets.dart | 1 + 3 files changed, 105 insertions(+), 109 deletions(-) create mode 100644 lib/presentation/app/widgets/custom_app_bar.dart diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index f1b44f18..5a1fbb1f 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -1,40 +1,23 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:logging/logging.dart'; import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; import 'package:nyrna/application/window/cubit/window_cubit.dart'; -import 'package:nyrna/presentation/app/widgets/window_tile.dart'; -import 'package:nyrna/presentation/preferences/pages/preferences_page.dart'; import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; -import 'package:url_launcher/url_launcher.dart'; + +import '../app.dart'; /// The main screen for Nyrna. /// /// Shows a ListView with tiles for each open window on the current desktop. -class AppsPage extends StatefulWidget { +class AppsPage extends StatelessWidget { static const id = 'running_apps_screen'; - @override - _AppsPageState createState() => _AppsPageState(); -} - -class _AppsPageState extends State { - static final _log = Logger('RunningAppsScreen'); - - @override - void initState() { - _log.info('RunningAppsScreen initialized'); - super.initState(); - } - @override Widget build(BuildContext context) { return Scaffold( - appBar: _appBar(context), + appBar: CustomAppBar(), body: Center( child: Container( width: MediaQuery.of(context).size.width / 1.20, @@ -65,94 +48,6 @@ class _AppsPageState extends State { floatingActionButton: _FloatingActionButton(), ); } - - AppBar _appBar(BuildContext context) { - return AppBar( - // Display the current desktop index, only for Linux. - // For Win32 this would require wrapping something like - // GetWindowDesktopId() with FFI. - // https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ivirtualdesktopmanager-getwindowdesktopid - title: (Platform.isLinux) - ? BlocBuilder( - builder: (context, state) { - return Text('Current Desktop: ${state.currentDesktop}'); - }, - ) - : null, - actions: [ - _updateIcon(), - IconButton( - icon: const Icon(Icons.settings), - onPressed: () { - _log.info('User clicked settings button'); - Navigator.pushNamed(context, PreferencesPage.id); - }, - ), - ], - ); - } - - /// Show an icon if a newer version of Nyrna is available. - Widget _updateIcon() { - return BlocBuilder( - builder: (context, state) { - return state.updateAvailable - ? IconButton( - icon: Icon( - Icons.notifications_active, - color: Colors.pink[400], - ), - onPressed: () => _showUpdateDialog(), - ) - : Container(); - }, - ); - } - - /// Inform user about new version of Nyrna, download link, etc. - Future _showUpdateDialog() async { - final state = appCubit.state; - final currentVersion = state.runningVersion; - final latestVersion = state.updateVersion; - const url = 'https://nyrna.merritt.codes/download'; - var _message = 'An update for Nyrna is available!\n\n' - 'Current version: $currentVersion\n' - 'Latest version: $latestVersion'; - await showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Update available'), - content: Text(_message), - actions: [ - TextButton( - onPressed: () async { - await canLaunch(url) - ? launch(url) - : setState(() { - _message = 'Error launching browser.'; - }); - }, - child: const Text('Open download page'), - ), - TextButton( - onPressed: () { - preferencesCubit.ignoreUpdate(latestVersion); - setState(() { - Navigator.pushReplacementNamed(context, AppsPage.id); - }); - }, - child: const Text('Dismiss'), - ), - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Close'), - ), - ], - ); - }, - ); - } } class _FloatingActionButton extends StatelessWidget { diff --git a/lib/presentation/app/widgets/custom_app_bar.dart b/lib/presentation/app/widgets/custom_app_bar.dart new file mode 100644 index 00000000..d7c22f3b --- /dev/null +++ b/lib/presentation/app/widgets/custom_app_bar.dart @@ -0,0 +1,100 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; +import 'package:nyrna/presentation/preferences/preferences.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../app.dart'; + +class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { + @override + final preferredSize = Size.fromHeight(kToolbarHeight); + + CustomAppBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AppBar( + // Display the current desktop index, only for Linux. + // For Win32 this would require wrapping something like + // GetWindowDesktopId() with FFI. + // https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ivirtualdesktopmanager-getwindowdesktopid + title: (Platform.isLinux) + ? BlocBuilder( + builder: (context, state) { + return Text('Current Desktop: ${state.currentDesktop}'); + }, + ) + : null, + actions: [ + BlocBuilder( + builder: (context, state) { + return state.updateAvailable + ? IconButton( + icon: Icon( + Icons.notifications_active, + color: Colors.pink[400], + ), + onPressed: () => _showUpdateDialog(context), + ) + : Container(); + }, + ), + IconButton( + icon: const Icon(Icons.settings), + onPressed: () { + Navigator.pushNamed(context, PreferencesPage.id); + }, + ), + ], + ); + } + + /// Inform user about new version of Nyrna, download link, etc. + Future _showUpdateDialog(BuildContext context) async { + final state = appCubit.state; + final currentVersion = state.runningVersion; + final latestVersion = state.updateVersion; + const url = 'https://nyrna.merritt.codes/download'; + var _message = 'An update for Nyrna is available!\n\n' + 'Current version: $currentVersion\n' + 'Latest version: $latestVersion'; + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Update available'), + content: Text(_message), + actions: [ + TextButton( + onPressed: () async { + await canLaunch(url) + ? launch(url) + : ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error launching browser'), + ), + ); + }, + child: const Text('Open download page'), + ), + TextButton( + onPressed: () { + preferencesCubit.ignoreUpdate(latestVersion); + Navigator.pushReplacementNamed(context, AppsPage.id); + }, + child: const Text('Dismiss'), + ), + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ); + }, + ); + } +} diff --git a/lib/presentation/app/widgets/widgets.dart b/lib/presentation/app/widgets/widgets.dart index 2d6d7979..6695d9d1 100644 --- a/lib/presentation/app/widgets/widgets.dart +++ b/lib/presentation/app/widgets/widgets.dart @@ -1 +1,2 @@ +export 'custom_app_bar.dart'; export 'window_tile.dart'; From 567f99be8a8483534c5e40d1b4555918ec1b1a33 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 2 Aug 2021 14:30:51 -0400 Subject: [PATCH 37/83] Refactor NativePlatform to seperate plugin package --- .../active_window/active_window.dart | 4 +- lib/application/app/cubit/app_cubit.dart | 66 ++++-- .../loading/cubit/loading_cubit.dart | 2 +- .../window/cubit/window_cubit.dart | 91 -------- .../window/cubit/window_state.dart | 45 ---- lib/domain/native_platform/models/models.dart | 2 - lib/domain/native_platform/models/window.dart | 21 -- .../native_platform/native_platform.dart | 1 - .../native_platform/native_platform.dart | 2 - .../native_platform/src/win32/ffi/dwmapi.dart | 30 --- lib/main.dart | 25 ++- lib/presentation/app/pages/apps_page.dart | 12 +- lib/presentation/app/widgets/window_tile.dart | 117 +++++----- linux/flutter/generated_plugin_registrant.cc | 2 + linux/flutter/generated_plugin_registrant.h | 2 + packages/native_platform/.gitignore | 10 + packages/native_platform/CHANGELOG.md | 3 + packages/native_platform/README.md | 1 + .../native_platform/analysis_options.yaml | 5 + .../native_platform/lib/native_platform.dart | 7 + .../native_platform/lib}/src/linux/linux.dart | 35 +-- .../lib}/src/linux/linux_process.dart | 3 +- .../lib}/src/native_platform.dart | 6 +- .../lib}/src/native_process.dart | 3 +- .../native_platform/lib/src}/process.dart | 3 +- .../lib}/src/win32/ffi/user32.dart | 0 .../native_platform/lib}/src/win32/win32.dart | 63 ++++-- .../lib}/src/win32/win32_process.dart | 2 +- packages/native_platform/lib/src/window.dart | 40 ++++ packages/native_platform/pubspec.yaml | 14 ++ .../test/src/native_process_test.dart | 6 +- pubspec.lock | 203 +++++++++++++++++- pubspec.yaml | 3 + test/platform/native_platform_test.dart | 47 ---- .../flutter/generated_plugin_registrant.cc | 2 + windows/flutter/generated_plugin_registrant.h | 2 + 36 files changed, 493 insertions(+), 387 deletions(-) delete mode 100644 lib/application/window/cubit/window_cubit.dart delete mode 100644 lib/application/window/cubit/window_state.dart delete mode 100644 lib/domain/native_platform/models/models.dart delete mode 100644 lib/domain/native_platform/models/window.dart delete mode 100644 lib/domain/native_platform/native_platform.dart delete mode 100644 lib/infrastructure/native_platform/native_platform.dart delete mode 100644 lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart create mode 100644 packages/native_platform/.gitignore create mode 100644 packages/native_platform/CHANGELOG.md create mode 100644 packages/native_platform/README.md create mode 100644 packages/native_platform/analysis_options.yaml create mode 100644 packages/native_platform/lib/native_platform.dart rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/linux/linux.dart (82%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/linux/linux_process.dart (96%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/native_platform.dart (90%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/native_process.dart (94%) rename {lib/domain/native_platform/models => packages/native_platform/lib/src}/process.dart (88%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/win32/ffi/user32.dart (100%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/win32/win32.dart (75%) rename {lib/infrastructure/native_platform => packages/native_platform/lib}/src/win32/win32_process.dart (98%) create mode 100644 packages/native_platform/lib/src/window.dart create mode 100644 packages/native_platform/pubspec.yaml rename test/process/process_test.dart => packages/native_platform/test/src/native_process_test.dart (87%) delete mode 100644 test/platform/native_platform_test.dart diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart index db819473..1da7591d 100644 --- a/lib/application/active_window/active_window.dart +++ b/lib/application/active_window/active_window.dart @@ -2,12 +2,10 @@ import 'dart:io' as io; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; +import 'package:native_platform/native_platform.dart'; import 'package:nyrna/domain/arguments/argument_parser.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/logger/log_file.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/infrastructure/native_platform/src/native_process.dart'; import 'package:win32/win32.dart'; /// Represents the active, foreground window on the system. diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index de99e1e1..a50bcd4c 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -3,9 +3,9 @@ import 'dart:io' as io; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:native_platform/native_platform.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/infrastructure/versions/versions.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -18,12 +18,18 @@ late AppCubit appCubit; class AppCubit extends Cubit { final NativePlatform _nativePlatform; final Preferences _prefs; + final PreferencesCubit _prefsCubit; + final Versions _versionRepo; AppCubit({ required NativePlatform nativePlatform, required Preferences prefs, + required PreferencesCubit prefsCubit, + required Versions versionRepository, }) : _nativePlatform = nativePlatform, _prefs = prefs, + _prefsCubit = prefsCubit, + _versionRepo = versionRepository, super(AppState.initial()) { appCubit = this; _initialize(); @@ -32,11 +38,11 @@ class AppCubit extends Cubit { Future _initialize() async { await _checkIsPortable(); setAutoRefresh( - autoRefresh: preferencesCubit.state.autoRefresh, - refreshInterval: preferencesCubit.state.refreshInterval, + autoRefresh: _prefsCubit.state.autoRefresh, + refreshInterval: _prefsCubit.state.refreshInterval, ); await _fetchDesktop(); - await _fetchVersionData(); + await fetchVersionData(); } Future _checkIsPortable() async { @@ -75,24 +81,20 @@ class AppCubit extends Cubit { /// Populate the list of visible windows. Future _fetchWindows() async { final windows = await _nativePlatform.windows(); - await Future.forEach(windows, (window) async { - final process = await _nativePlatform.windowProcess(window.id); - window.process = process; - }); windows.removeWhere( - (window) => _filteredWindows.contains(window.process!.executable), + (window) => _filteredWindows.contains(window.process.executable), ); emit(state.copyWith(windows: windows)); } - Future _fetchVersionData() async { - final versionRepo = Versions(); - final runningVersion = await versionRepo.runningVersion(); - final latestVersion = await versionRepo.latestVersion(); + @visibleForTesting + Future fetchVersionData() async { + final runningVersion = await _versionRepo.runningVersion(); + final latestVersion = await _versionRepo.latestVersion(); final ignoredUpdate = _prefs.getString('ignoredUpdate'); final updateHasBeenIgnored = (latestVersion == ignoredUpdate); final updateAvailable = - (updateHasBeenIgnored) ? false : await versionRepo.updateAvailable(); + (updateHasBeenIgnored) ? false : await _versionRepo.updateAvailable(); emit(state.copyWith( runningVersion: runningVersion, updateVersion: latestVersion, @@ -100,6 +102,40 @@ class AppCubit extends Cubit { )); } + /// Toggle suspend / resume for the process associated with the given window. + Future toggle(Window window) async { + bool success; + if (window.process.status == ProcessStatus.suspended) { + success = await _resume(window); + } else { + success = await _suspend(window); + } + return success; + } + + Future _resume(Window window) async { + final nativeProcess = NativeProcess(window.process.pid); + final success = await nativeProcess.resume(); + // Restore the window _after_ resuming or it might not restore. + await _nativePlatform.restoreWindow(window.id); + await fetchData(); + return (success) ? true : false; + } + + Future _suspend(Window window) async { + // Minimize the window before suspending or it might not minimize. + await _nativePlatform.minimizeWindow(window.id); + // Small delay on Win32 to ensure the window actually minimizes. + // Doesn't seem to be necessary on Linux. + if (io.Platform.isWindows) { + await Future.delayed(Duration(milliseconds: 500)); + } + final nativeProcess = NativeProcess(window.process.pid); + final success = await nativeProcess.suspend(); + await fetchData(); + return (success) ? true : false; + } + Future launchURL(String url) async { await canLaunch(url) ? await launch(url) diff --git a/lib/application/loading/cubit/loading_cubit.dart b/lib/application/loading/cubit/loading_cubit.dart index 9804311b..19cf58b6 100644 --- a/lib/application/loading/cubit/loading_cubit.dart +++ b/lib/application/loading/cubit/loading_cubit.dart @@ -1,6 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; +import 'package:native_platform/native_platform.dart'; part 'loading_state.dart'; diff --git a/lib/application/window/cubit/window_cubit.dart b/lib/application/window/cubit/window_cubit.dart deleted file mode 100644 index fb1206ea..00000000 --- a/lib/application/window/cubit/window_cubit.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:collection/collection.dart'; -import 'dart:io' as io; - -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; -import 'package:nyrna/application/app/app.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; - -part 'window_state.dart'; - -enum ToggleError { - None, - Suspend, - Resume, -} - -class WindowCubit extends Cubit { - final AppCubit _appCubit; - final NativePlatform _nativePlatform; - final Window _window; - - WindowCubit({ - required AppCubit appCubit, - required NativePlatform nativePlatform, - required Window window, - }) : _appCubit = appCubit, - _nativePlatform = nativePlatform, - _window = window, - super( - WindowState( - executable: window.process?.executable ?? '', - pid: window.process?.pid ?? 0, - processStatus: window.process?.status ?? ProcessStatus.unknown, - title: window.title, - toggleError: ToggleError.None, - ), - ) { - _initialize(); - } - - Future _initialize() async { - _listen(); - } - - void _listen() { - _appCubit.stream.listen((event) { - final window = event.windows.firstWhereOrNull((e) => e.id == _window.id); - if (window != null) { - emit(state.copyWith( - processStatus: window.process?.status, - title: window.title, - )); - } else { - close(); - } - }); - } - - /// Toggle suspend / resume for the process associated with the given window. - Future toggle() async { - if (state.processStatus == ProcessStatus.suspended) { - await _resume(); - } else { - await _suspend(); - } - } - - Future _resume() async { - final nativeProcess = NativeProcess(state.pid); - final successful = await nativeProcess.resume(); - if (!successful) emit(state.copyWith(toggleError: ToggleError.Resume)); - // Restore the window _after_ resuming or it might not restore. - await _nativePlatform.restoreWindow(_window.id); - } - - Future _suspend() async { - // Minimize the window before suspending or it might not minimize. - await _nativePlatform.minimizeWindow(_window.id); - // Small delay on Win32 to ensure the window actually minimizes. - // Doesn't seem to be necessary on Linux. - if (io.Platform.isWindows) { - await Future.delayed(Duration(milliseconds: 500)); - } - final nativeProcess = NativeProcess(state.pid); - final successful = await nativeProcess.suspend(); - if (!successful) emit(state.copyWith(toggleError: ToggleError.Suspend)); - await _appCubit.fetchData(); - } -} diff --git a/lib/application/window/cubit/window_state.dart b/lib/application/window/cubit/window_state.dart deleted file mode 100644 index ecc0e593..00000000 --- a/lib/application/window/cubit/window_state.dart +++ /dev/null @@ -1,45 +0,0 @@ -part of 'window_cubit.dart'; - -@immutable -class WindowState extends Equatable { - final String executable; - final int pid; - final ProcessStatus processStatus; - final String title; - final ToggleError toggleError; - - const WindowState({ - required this.executable, - required this.pid, - required this.processStatus, - required this.title, - required this.toggleError, - }); - - @override - List get props { - return [ - executable, - pid, - processStatus, - title, - toggleError, - ]; - } - - WindowState copyWith({ - String? executable, - int? pid, - ProcessStatus? processStatus, - String? title, - ToggleError? toggleError, - }) { - return WindowState( - executable: executable ?? this.executable, - pid: pid ?? this.pid, - processStatus: processStatus ?? this.processStatus, - title: title ?? this.title, - toggleError: toggleError ?? this.toggleError, - ); - } -} diff --git a/lib/domain/native_platform/models/models.dart b/lib/domain/native_platform/models/models.dart deleted file mode 100644 index 068bb754..00000000 --- a/lib/domain/native_platform/models/models.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'process.dart'; -export 'window.dart'; diff --git a/lib/domain/native_platform/models/window.dart b/lib/domain/native_platform/models/window.dart deleted file mode 100644 index d688edf2..00000000 --- a/lib/domain/native_platform/models/window.dart +++ /dev/null @@ -1,21 +0,0 @@ -import '../native_platform.dart'; - -/// Represents a visible window on the current desktop. -class Window { - /// The unique window ID number associated with this window. - final int id; - - /// The process associated with this window. - Process? process; - - /// The title of this window, often shown on the window's 'Title Bar'. - /// - /// Can & does change, for example a browser shows the title of the page. - final String title; - - Window({ - required this.id, - this.process, - required this.title, - }); -} diff --git a/lib/domain/native_platform/native_platform.dart b/lib/domain/native_platform/native_platform.dart deleted file mode 100644 index 51b02151..00000000 --- a/lib/domain/native_platform/native_platform.dart +++ /dev/null @@ -1 +0,0 @@ -export 'models/models.dart'; diff --git a/lib/infrastructure/native_platform/native_platform.dart b/lib/infrastructure/native_platform/native_platform.dart deleted file mode 100644 index 70a6bf66..00000000 --- a/lib/infrastructure/native_platform/native_platform.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'src/native_platform.dart'; -export 'src/native_process.dart'; diff --git a/lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart b/lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart deleted file mode 100644 index b8b3f6b3..00000000 --- a/lib/infrastructure/native_platform/src/win32/ffi/dwmapi.dart +++ /dev/null @@ -1,30 +0,0 @@ -/// Win32 wrapper for dwmapi.dll API syscalls. -/// -/// https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/ - -import 'dart:ffi'; - -final _dwmapi = DynamicLibrary.open('Dwmapi.dll'); - -const DWMWA_CLOAKED = 14; - -/// Retrieves the current value of a specified -/// Desktop Window Manager (DWM) attribute applied to a window. -/// -/// ```cpp -// DWMAPI DwmGetWindowAttribute( -// HWND hwnd, -// DWORD dwAttribute, -// PVOID pvAttribute, -// DWORD cbAttribute -// ); -/// ``` -int DwmGetWindowAttribute( - int hwnd, int dwAttribute, Pointer pvAttribute, int cbAttribute) { - final _DwmGetWindowAttribute = _dwmapi.lookupFunction< - Int32 Function(Int32 hwnd, Uint32 dwAttribute, Pointer pvAttribute, - Uint32 cbAttribute), - int Function(int hwnd, int dwAttribute, Pointer pvAttribute, - int cbAttribute)>('DwmGetWindowAttribute'); - return _DwmGetWindowAttribute(hwnd, dwAttribute, pvAttribute, cbAttribute); -} diff --git a/lib/main.dart b/lib/main.dart index d5b8e247..98295cde 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:native_platform/native_platform.dart'; import 'package:nyrna/application/bloc_observer.dart'; import 'package:nyrna/infrastructure/logger/app_logger.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; +import 'package:nyrna/infrastructure/versions/versions.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; import 'package:nyrna/application/active_window/active_window.dart'; @@ -33,13 +34,6 @@ Future main(List args) async { runApp( MultiBlocProvider( providers: [ - BlocProvider( - create: (context) => AppCubit( - nativePlatform: nativePlatform, - prefs: prefs, - ), - lazy: false, - ), BlocProvider( create: (context) => PreferencesCubit(prefs), lazy: false, @@ -48,7 +42,20 @@ Future main(List args) async { create: (context) => ThemeCubit(prefs), ), ], - child: AppWidget(), + child: Builder( + builder: (context) { + return BlocProvider( + create: (context) => AppCubit( + nativePlatform: nativePlatform, + prefs: prefs, + prefsCubit: context.read(), + versionRepository: Versions(), + ), + lazy: false, + child: AppWidget(), + ); + }, + ), ), ); } diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 5a1fbb1f..5067a0aa 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -3,8 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/app/app.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; -import 'package:nyrna/application/window/cubit/window_cubit.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import '../app.dart'; @@ -28,13 +26,9 @@ class AppsPage extends StatelessWidget { children: [ ...state.windows .map( - (window) => BlocProvider( - create: (context) => WindowCubit( - appCubit: appCubit, - nativePlatform: NativePlatform(), - window: window, - ), - child: WindowTile(key: ValueKey(window.id)), + (window) => WindowTile( + key: ValueKey(window), + window: window, ), ) .toList(), diff --git a/lib/presentation/app/widgets/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart index 2c18e26a..0521f570 100644 --- a/lib/presentation/app/widgets/window_tile.dart +++ b/lib/presentation/app/widgets/window_tile.dart @@ -1,121 +1,108 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:nyrna/application/window/cubit/window_cubit.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; +import 'package:native_platform/native_platform.dart'; +import 'package:nyrna/application/app/app.dart'; /// Represents a visible window on the desktop, running state and actions. class WindowTile extends StatelessWidget { + final Window window; + const WindowTile({ Key? key, + required this.window, }) : super(key: key); @override Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - if (state.toggleError == ToggleError.Suspend) { - _showSnackError(context, ToggleError.Suspend); - } else if (state.toggleError == ToggleError.Resume) { - _showSnackError(context, ToggleError.Resume); - } - }, - child: Card( - child: ListTile( - leading: _StatusWidget(), - title: _TitleWidget(), - subtitle: _DetailsWidget(), - contentPadding: const EdgeInsets.symmetric( - vertical: 2, - horizontal: 20, - ), - onTap: () => context.read().toggle(), + return Card( + child: ListTile( + leading: _StatusWidget(window: window), + title: _TitleWidget(window: window), + subtitle: _DetailsWidget(window: window), + contentPadding: const EdgeInsets.symmetric( + vertical: 2, + horizontal: 20, ), + onTap: () async { + final success = await context.read().toggle(window); + if (!success) await _showSnackError(context); + }, ), ); } Future _showSnackError( BuildContext context, - ToggleError errorType, ) async { - final state = context.read().state; - final name = state.executable; - final suspendMessage = 'There was a problem suspending $name'; - final resumeMessage = 'There was a problem resuming $name'; - final message = - (errorType == ToggleError.Suspend) ? suspendMessage : resumeMessage; + final name = window.process.executable; + final message = 'There was a problem interacting with $name'; final snackBar = SnackBar(content: Text(message)); ScaffoldMessenger.of(context).showSnackBar(snackBar); } } class _StatusWidget extends StatelessWidget { + final Window window; + const _StatusWidget({ Key? key, + required this.window, }) : super(key: key); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - Color _color; - switch (state.processStatus) { - case ProcessStatus.normal: - _color = Colors.green; - break; - case ProcessStatus.suspended: - _color = Colors.orange[700]!; - break; - case ProcessStatus.unknown: - _color = Colors.grey; - } + Color _color; + switch (window.process.status) { + case ProcessStatus.normal: + _color = Colors.green; + break; + case ProcessStatus.suspended: + _color = Colors.orange[700]!; + break; + case ProcessStatus.unknown: + _color = Colors.grey; + } - return Container( - height: 20, - width: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _color, - ), - ); - }, + return Container( + height: 20, + width: 20, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _color, + ), ); } } class _TitleWidget extends StatelessWidget { + final Window window; + const _TitleWidget({ Key? key, + required this.window, }) : super(key: key); @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Text(state.title); - }, - ); + return Text(window.title); } } class _DetailsWidget extends StatelessWidget { - const _DetailsWidget({Key? key}) : super(key: key); + final Window window; + + const _DetailsWidget({ + Key? key, + required this.window, + }) : super(key: key); @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - BlocBuilder( - builder: (context, state) { - return Text('PID: ${state.pid}'); - }, - ), - BlocBuilder( - builder: (context, state) { - return Text(state.executable); - }, - ), + Text('PID: ${window.process.pid}'), + Text(window.process.executable), ], ); } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 026851fa..f6f23bfe 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" #include diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h index 9bf74789..e0f0a47b 100644 --- a/linux/flutter/generated_plugin_registrant.h +++ b/linux/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/packages/native_platform/.gitignore b/packages/native_platform/.gitignore new file mode 100644 index 00000000..65c34dc8 --- /dev/null +++ b/packages/native_platform/.gitignore @@ -0,0 +1,10 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build outputs. +build/ + +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/packages/native_platform/CHANGELOG.md b/packages/native_platform/CHANGELOG.md new file mode 100644 index 00000000..effe43c8 --- /dev/null +++ b/packages/native_platform/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/packages/native_platform/README.md b/packages/native_platform/README.md new file mode 100644 index 00000000..daeedfd2 --- /dev/null +++ b/packages/native_platform/README.md @@ -0,0 +1 @@ +Nyrna's package to interactive with the native platform. \ No newline at end of file diff --git a/packages/native_platform/analysis_options.yaml b/packages/native_platform/analysis_options.yaml new file mode 100644 index 00000000..11fda60d --- /dev/null +++ b/packages/native_platform/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + errors: + omit_local_variable_types: ignore diff --git a/packages/native_platform/lib/native_platform.dart b/packages/native_platform/lib/native_platform.dart new file mode 100644 index 00000000..a09deaa4 --- /dev/null +++ b/packages/native_platform/lib/native_platform.dart @@ -0,0 +1,7 @@ +/// Nyrna's package to interactive with the native platform. +library native_platform; + +export 'src/native_platform.dart'; +export 'src/native_process.dart'; +export 'src/process.dart'; +export 'src/window.dart'; diff --git a/lib/infrastructure/native_platform/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart similarity index 82% rename from lib/infrastructure/native_platform/src/linux/linux.dart rename to packages/native_platform/lib/src/linux/linux.dart index be76bd36..699a3b45 100644 --- a/lib/infrastructure/native_platform/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -1,9 +1,10 @@ import 'dart:io' as io; -import 'package:nyrna/domain/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/native_platform/src/linux/linux_process.dart'; - import '../native_platform.dart'; +import '../native_process.dart'; +import '../process.dart'; +import '../window.dart'; +import 'linux_process.dart'; /// Interact with the native Linux operating system. class Linux implements NativePlatform { @@ -30,7 +31,7 @@ class Linux implements NativePlatform { // 0x03600041 1 1459 SHODAN Inbox - Unified Folders - Mozilla Thunderbird // windowId, desktopId, pid, user, window title final lines = result.stdout.toString().split('\n'); - lines.forEach((line) { + lines.forEach((line) async { final parts = line.split(' '); parts.removeWhere((part) => part == ''); // Happens with multiple spaces. if (parts.length > 1) { @@ -40,10 +41,21 @@ class Linux implements NativePlatform { final pid = int.tryParse(parts[2]); final id = int.tryParse(parts[0]); if ((pid == null) || (id == null)) return; - windows.add(Window( - id: id, - title: parts.sublist(4).join(' '), - )); + final linuxProcess = LinuxProcess(pid); + final executable = await linuxProcess.executable; + final status = await linuxProcess.status; + final process = Process( + executable: executable, + pid: pid, + status: status, + ); + windows.add( + Window( + id: id, + process: process, + title: parts.sublist(4).join(' '), + ), + ); } } }); @@ -96,12 +108,9 @@ class Linux implements NativePlatform { } @override - Future windowProcess(int windowId) async { + Future windowProcess(int windowId) async { final pid = await windowPid(windowId); - final linuxProcess = LinuxProcess(pid); - final executable = await linuxProcess.executable; - final status = await linuxProcess.status; - final process = Process(executable: executable, pid: pid, status: status); + final process = LinuxProcess(pid); return process; } diff --git a/lib/infrastructure/native_platform/src/linux/linux_process.dart b/packages/native_platform/lib/src/linux/linux_process.dart similarity index 96% rename from lib/infrastructure/native_platform/src/linux/linux_process.dart rename to packages/native_platform/lib/src/linux/linux_process.dart index 6598c448..55d8e535 100644 --- a/lib/infrastructure/native_platform/src/linux/linux_process.dart +++ b/packages/native_platform/lib/src/linux/linux_process.dart @@ -1,8 +1,7 @@ import 'dart:io' as io; -import 'package:nyrna/domain/native_platform/native_platform.dart'; - import '../native_process.dart'; +import '../process.dart'; class LinuxProcess implements NativeProcess { LinuxProcess(this.pid); diff --git a/lib/infrastructure/native_platform/src/native_platform.dart b/packages/native_platform/lib/src/native_platform.dart similarity index 90% rename from lib/infrastructure/native_platform/src/native_platform.dart rename to packages/native_platform/lib/src/native_platform.dart index 4dce97ef..5734bdc3 100644 --- a/lib/infrastructure/native_platform/src/native_platform.dart +++ b/packages/native_platform/lib/src/native_platform.dart @@ -1,9 +1,9 @@ import 'dart:io'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; - import 'linux/linux.dart'; +import 'native_process.dart'; import 'win32/win32.dart'; +import 'window.dart'; /// Interact with the native operating system. /// @@ -26,7 +26,7 @@ abstract class NativePlatform { Future windowPid(int windowId); /// The process associated with a window. - Future windowProcess(int windowId); + Future windowProcess(int windowId); /// List of [Window] objects for every visible window with title text. Future> windows(); diff --git a/lib/infrastructure/native_platform/src/native_process.dart b/packages/native_platform/lib/src/native_process.dart similarity index 94% rename from lib/infrastructure/native_platform/src/native_process.dart rename to packages/native_platform/lib/src/native_process.dart index 0468e619..71522b46 100644 --- a/lib/infrastructure/native_platform/src/native_process.dart +++ b/packages/native_platform/lib/src/native_process.dart @@ -1,8 +1,7 @@ import 'dart:io' as io; -import 'package:nyrna/domain/native_platform/native_platform.dart'; - import 'linux/linux_process.dart'; +import 'process.dart'; import 'win32/win32.dart'; /// Represents a process including its metadata and controls. diff --git a/lib/domain/native_platform/models/process.dart b/packages/native_platform/lib/src/process.dart similarity index 88% rename from lib/domain/native_platform/models/process.dart rename to packages/native_platform/lib/src/process.dart index 338c782e..8e29ba70 100644 --- a/lib/domain/native_platform/models/process.dart +++ b/packages/native_platform/lib/src/process.dart @@ -1,5 +1,5 @@ import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; +import 'package:meta/meta.dart'; enum ProcessStatus { normal, @@ -7,6 +7,7 @@ enum ProcessStatus { unknown, } +/// Friendly representation of a running process. @immutable class Process extends Equatable { final String executable; diff --git a/lib/infrastructure/native_platform/src/win32/ffi/user32.dart b/packages/native_platform/lib/src/win32/ffi/user32.dart similarity index 100% rename from lib/infrastructure/native_platform/src/win32/ffi/user32.dart rename to packages/native_platform/lib/src/win32/ffi/user32.dart diff --git a/lib/infrastructure/native_platform/src/win32/win32.dart b/packages/native_platform/lib/src/win32/win32.dart similarity index 75% rename from lib/infrastructure/native_platform/src/win32/win32.dart rename to packages/native_platform/lib/src/win32/win32.dart index d8f4617e..1f5f7991 100644 --- a/lib/infrastructure/native_platform/src/win32/win32.dart +++ b/packages/native_platform/lib/src/win32/win32.dart @@ -1,11 +1,12 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; import 'package:win32/win32.dart'; -import 'ffi/dwmapi.dart'; +import '../native_platform.dart'; +import '../native_process.dart'; +import '../process.dart'; +import '../window.dart'; import 'win32_process.dart'; export 'win32_process.dart'; @@ -20,11 +21,17 @@ class Win32 implements NativePlatform { @override Future> windows() async { - // Process open windows. - EnumWindows(WindowBuilder.callback, 0); - final windows = List.from(WindowBuilder.windows); // Clear the map to ensure we are starting fresh each time. WindowBuilder.windows.clear(); + // Process open windows. + /// [EnumWindows] returns 0 for failure. + final result = EnumWindows(WindowBuilder.callback, 0); + if (result == 0) { + print('Error from EnumWindows getting open windows'); + return []; + } + final windowMap = WindowBuilder.windows; + final windows = await buildWindows(windowMap); return windows; } @@ -59,12 +66,9 @@ class Win32 implements NativePlatform { Future checkDependencies() async => true; @override - Future windowProcess(int windowId) async { + Future windowProcess(int windowId) async { final pid = await windowPid(windowId); - final win32Process = Win32Process(pid); - final executable = await win32Process.executable; - final status = await win32Process.status; - final process = Process(executable: executable, pid: pid, status: status); + final process = Win32Process(pid); return process; } @@ -79,6 +83,34 @@ class Win32 implements NativePlatform { ShowWindow(windowId, SW_RESTORE); return true; // [ShowWindow] return value doesn't confirm success. } + + Future> buildWindows(List> windowMaps) async { + final windows = []; + await Future.forEach( + windowMaps, + (Map window) async { + final windowId = window.keys.first; + final title = window.values.first; + final win32Process = await windowProcess(windowId); + final executable = await win32Process.executable; + final pid = win32Process.pid; + final status = await win32Process.status; + final process = Process( + executable: executable, + pid: pid, + status: status, + ); + windows.add( + Window( + id: windowId, + process: process, + title: title, + ), + ); + }, + ); + return windows; + } } // Static methods required because the win32 callback is required to be static. @@ -129,6 +161,7 @@ class WindowBuilder { // Initialize memory for the result pointer. final result = calloc(); // Populate into the `result` pointer. + const DWMWA_CLOAKED = 14; DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, result, sizeOf()); // Pull the value from the pointer. var cloakedReason = result.value; @@ -141,10 +174,12 @@ class WindowBuilder { return (cloakedReason == 0) ? false : true; } - static List windows = []; + static List> windows = []; /// Called during the callback for every window to map the data. - static Future _buildWindowMap(int windowId, String title) async { - windows.add(Window(id: windowId, title: title)); + static void _buildWindowMap(int windowId, String title) { + windows.add({ + windowId: title, + }); } } diff --git a/lib/infrastructure/native_platform/src/win32/win32_process.dart b/packages/native_platform/lib/src/win32/win32_process.dart similarity index 98% rename from lib/infrastructure/native_platform/src/win32/win32_process.dart rename to packages/native_platform/lib/src/win32/win32_process.dart index 0d3874cb..e1e2186f 100644 --- a/lib/infrastructure/native_platform/src/win32/win32_process.dart +++ b/packages/native_platform/lib/src/win32/win32_process.dart @@ -3,11 +3,11 @@ import 'dart:io' as io; import 'package:ffi/ffi.dart'; import 'package:logging/logging.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; import 'package:win32/win32.dart'; import 'package:win32_suspend_process/win32_suspend_process.dart' as w32proc; import '../native_process.dart'; +import '../process.dart'; class Win32Process implements NativeProcess { Win32Process(this.pid); diff --git a/packages/native_platform/lib/src/window.dart b/packages/native_platform/lib/src/window.dart new file mode 100644 index 00000000..332f1935 --- /dev/null +++ b/packages/native_platform/lib/src/window.dart @@ -0,0 +1,40 @@ +import 'package:equatable/equatable.dart'; +import 'package:meta/meta.dart'; + +import 'process.dart'; + +/// Friendly representation of a visible window. +@immutable +class Window extends Equatable { + /// The unique window ID number associated with this window. + final int id; + + /// The process associated with this window. + final Process process; + + /// The title of this window, often shown on the window's 'Title Bar'. + /// + /// Can & does change, for example a browser shows the title of the page. + final String title; + + Window({ + required this.id, + required this.process, + required this.title, + }); + + @override + List get props => [id, process, title]; + + Window copyWith({ + int? id, + Process? process, + String? title, + }) { + return Window( + id: id ?? this.id, + process: process ?? this.process, + title: title ?? this.title, + ); + } +} diff --git a/packages/native_platform/pubspec.yaml b/packages/native_platform/pubspec.yaml new file mode 100644 index 00000000..03a8225d --- /dev/null +++ b/packages/native_platform/pubspec.yaml @@ -0,0 +1,14 @@ +name: native_platform +description: Nyrna's package to interactive with the native platform. +version: 1.0.0 +environment: + sdk: '>=2.12.0 <3.0.0' + +dependencies: + equatable: ^2.0.3 + win32: ^2.2.5 + win32_suspend_process: ^1.0.0 + +dev_dependencies: + pedantic: ^1.10.0 + test: ^1.16.0 diff --git a/test/process/process_test.dart b/packages/native_platform/test/src/native_process_test.dart similarity index 87% rename from test/process/process_test.dart rename to packages/native_platform/test/src/native_process_test.dart index 5b9f9626..c06680ff 100644 --- a/test/process/process_test.dart +++ b/packages/native_platform/test/src/native_process_test.dart @@ -1,8 +1,8 @@ import 'dart:io' as io; -import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/domain/native_platform/native_platform.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; +import 'package:native_platform/native_platform.dart'; +import 'package:native_platform/src/native_process.dart'; +import 'package:test/test.dart'; void main() { final pid = io.pid; // Dart or Nyrna's own pid. diff --git a/pubspec.lock b/pubspec.lock index 69fb1631..f8fb9f3b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "22.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.2" archive: dependency: transitive description: @@ -21,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.7.0" bloc: dependency: transitive description: @@ -29,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.0.0" + bloc_test: + dependency: "direct main" + description: + name: bloc_test + url: "https://pub.dartlang.org" + source: hosted + version: "8.1.0" boolean_selector: dependency: transitive description: @@ -49,7 +70,14 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.3" clock: dependency: transitive description: @@ -64,6 +92,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" crypto: dependency: transitive description: @@ -98,7 +140,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.0" + version: "6.1.2" flex_color_picker: dependency: "direct main" description: @@ -133,11 +175,25 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter source: sdk version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" http: dependency: "direct main" description: @@ -145,6 +201,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.3" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" http_parser: dependency: transitive description: @@ -157,6 +220,13 @@ packages: description: flutter source: sdk version: "0.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" js: dependency: transitive description: @@ -184,7 +254,28 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + mocktail: + dependency: transitive + description: + name: mocktail + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + native_platform: + dependency: "direct main" + description: + path: "packages/native_platform" + relative: true + source: path + version: "1.0.0" nested: dependency: transitive description: @@ -192,6 +283,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -255,6 +360,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" process: dependency: transitive description: @@ -318,11 +430,53 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" source_span: dependency: transitive description: @@ -365,13 +519,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + test: + dependency: transitive + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.17.9" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.1" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.29" typed_data: dependency: transitive description: @@ -434,7 +602,21 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "6.2.0" + version: "7.1.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" webdriver: dependency: transitive description: @@ -442,13 +624,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" win32: dependency: "direct main" description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.2.5" win32_suspend_process: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 97740c12..9cf4da52 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,7 +9,10 @@ environment: dependencies: flutter: sdk: flutter + native_platform: + path: packages/native_platform args: ^2.1.0 + bloc_test: ^8.1.0 equatable: ^2.0.3 flex_color_picker: ^2.0.1 flutter_bloc: ^7.1.0 diff --git a/test/platform/native_platform_test.dart b/test/platform/native_platform_test.dart deleted file mode 100644 index b843bdbc..00000000 --- a/test/platform/native_platform_test.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/infrastructure/native_platform/native_platform.dart'; - -void main() { - NativePlatform nativePlatform = NativePlatform(); - - setUp(() => nativePlatform = NativePlatform()); - - test('Can instantiate NativePlatform', () { - expect(nativePlatform, isA()); - }); - - test('currentDesktop is not null', () async { - var currentDesktop = await nativePlatform.currentDesktop; - print('currentDesktop: $currentDesktop'); - expect(currentDesktop, isNotNull); - }); - - test('windows getter is not empty', () async { - var windows = await nativePlatform.windows(); - print('windows found: ${windows.length}'); - expect(windows, isNotEmpty); - }); - - test( - 'activeWindowPid is not null', - () async { - var pid = await nativePlatform.activeWindowPid; - print('Active window pid: $pid'); - expect(pid, isNot(null)); - }, - ); - test( - 'activeWindowId is not null', - () async { - var id = await nativePlatform.activeWindowId; - print('Active window id: $id'); - expect(id, isNot(null)); - }, - ); - - test('checkDependencies is not null', () async { - var haveDependencies = await nativePlatform.checkDependencies(); - print('haveDependencies: $haveDependencies'); - expect(haveDependencies, isA()); - }); -} diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index ddfcf7c3..d9fdd539 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" #include diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h index 9846246b..dc139d85 100644 --- a/windows/flutter/generated_plugin_registrant.h +++ b/windows/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ From 78c4ea06e12b581bc742816d7eed0614fa939c1a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 2 Aug 2021 14:52:27 -0400 Subject: [PATCH 38/83] Add progress indicator on app startup --- lib/application/app/cubit/app_cubit.dart | 3 +-- lib/presentation/app/pages/apps_page.dart | 31 +++++++++++++---------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index a50bcd4c..b878424b 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -36,12 +36,12 @@ class AppCubit extends Cubit { } Future _initialize() async { + await fetchData(); await _checkIsPortable(); setAutoRefresh( autoRefresh: _prefsCubit.state.autoRefresh, refreshInterval: _prefsCubit.state.refreshInterval, ); - await _fetchDesktop(); await fetchVersionData(); } @@ -58,7 +58,6 @@ class AppCubit extends Cubit { required bool autoRefresh, required int refreshInterval, }) { - fetchData(); if (_timer != null) _timer?.cancel(); if (autoRefresh) { _timer = Timer.periodic( diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 5067a0aa..32b92a0d 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -21,19 +21,24 @@ class AppsPage extends StatelessWidget { width: MediaQuery.of(context).size.width / 1.20, child: BlocBuilder( builder: (context, state) { - return ListView( - padding: const EdgeInsets.only(top: 40), - children: [ - ...state.windows - .map( - (window) => WindowTile( - key: ValueKey(window), - window: window, - ), - ) - .toList(), - ], - ); + return (state == AppState.initial()) + ? Transform.scale( + scale: 2, + child: Center(child: CircularProgressIndicator()), + ) + : ListView( + padding: const EdgeInsets.only(top: 40), + children: [ + ...state.windows + .map( + (window) => WindowTile( + key: ValueKey(window), + window: window, + ), + ) + .toList(), + ], + ); }, ), ), From 7f5dbbdce7a6087e9b496d71ed3e9ac26c7fc29a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 2 Aug 2021 15:23:41 -0400 Subject: [PATCH 39/83] Add progress indicator to manual refresh --- lib/application/app/cubit/app_cubit.dart | 7 +++ lib/application/app/cubit/app_state.dart | 7 +++ lib/presentation/app/pages/apps_page.dart | 77 +++++++++++++++-------- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index b878424b..e7cb8380 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -37,6 +37,7 @@ class AppCubit extends Cubit { Future _initialize() async { await fetchData(); + emit(state.copyWith(loading: false)); await _checkIsPortable(); setAutoRefresh( autoRefresh: _prefsCubit.state.autoRefresh, @@ -86,6 +87,12 @@ class AppCubit extends Cubit { emit(state.copyWith(windows: windows)); } + Future manualRefresh() async { + emit(state.copyWith(loading: true)); + await fetchData(); + emit(state.copyWith(loading: false)); + } + @visibleForTesting Future fetchVersionData() async { final runningVersion = await _versionRepo.runningVersion(); diff --git a/lib/application/app/cubit/app_state.dart b/lib/application/app/cubit/app_state.dart index 0e6bff7d..37aad83e 100644 --- a/lib/application/app/cubit/app_state.dart +++ b/lib/application/app/cubit/app_state.dart @@ -5,6 +5,8 @@ class AppState extends Equatable { /// present for the portable build on Linux. final bool isPortable; + final bool loading; + final String runningVersion; final String updateVersion; final bool updateAvailable; @@ -16,6 +18,7 @@ class AppState extends Equatable { const AppState({ required this.isPortable, + required this.loading, required this.runningVersion, required this.updateVersion, required this.updateAvailable, @@ -26,6 +29,7 @@ class AppState extends Equatable { factory AppState.initial() { return AppState( isPortable: false, + loading: true, runningVersion: '', updateVersion: '', updateAvailable: false, @@ -38,6 +42,7 @@ class AppState extends Equatable { List get props { return [ isPortable, + loading, runningVersion, updateVersion, updateAvailable, @@ -48,6 +53,7 @@ class AppState extends Equatable { AppState copyWith({ bool? isPortable, + bool? loading, String? runningVersion, String? updateVersion, bool? updateAvailable, @@ -56,6 +62,7 @@ class AppState extends Equatable { }) { return AppState( isPortable: isPortable ?? this.isPortable, + loading: loading ?? this.loading, runningVersion: runningVersion ?? this.runningVersion, updateVersion: updateVersion ?? this.updateVersion, updateAvailable: updateAvailable ?? this.updateAvailable, diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 32b92a0d..a4f9f06e 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -16,32 +16,32 @@ class AppsPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar(), - body: Center( - child: Container( - width: MediaQuery.of(context).size.width / 1.20, - child: BlocBuilder( - builder: (context, state) { - return (state == AppState.initial()) - ? Transform.scale( - scale: 2, - child: Center(child: CircularProgressIndicator()), - ) - : ListView( - padding: const EdgeInsets.only(top: 40), - children: [ - ...state.windows - .map( - (window) => WindowTile( - key: ValueKey(window), - window: window, - ), - ) - .toList(), - ], - ); - }, - ), - ), + body: BlocBuilder( + builder: (context, state) { + return Stack( + children: [ + Center( + child: Container( + width: MediaQuery.of(context).size.width / 1.20, + child: ListView( + padding: const EdgeInsets.only(top: 40), + children: [ + ...state.windows + .map( + (window) => WindowTile( + key: ValueKey(window), + window: window, + ), + ) + .toList(), + ], + ), + ), + ), + _ProgressOverlay(), + ], + ); + }, ), // We don't show a manual refresh button with a short auto-refresh. floatingActionButton: _FloatingActionButton(), @@ -49,6 +49,29 @@ class AppsPage extends StatelessWidget { } } +class _ProgressOverlay extends StatelessWidget { + const _ProgressOverlay({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return (state.loading) + ? Stack( + children: [ + ModalBarrier(color: Colors.grey.withOpacity(0.1)), + Transform.scale( + scale: 2, + child: Center(child: CircularProgressIndicator()), + ), + ], + ) + : const SizedBox(); + }, + ); + } +} + class _FloatingActionButton extends StatelessWidget { _FloatingActionButton({Key? key}) : super(key: key); @@ -68,7 +91,7 @@ class _FloatingActionButton extends StatelessWidget { backgroundColor: (state.appTheme == AppTheme.pitchBlack) ? Colors.black : null, - onPressed: () => appCubit.fetchData(), + onPressed: () => appCubit.manualRefresh(), child: const Icon(Icons.refresh), ); }, From d81f48381a41aa975a4ce147a487dda4da839647 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 3 Aug 2021 10:20:15 -0400 Subject: [PATCH 40/83] Add progress indicator when suspending or resuming --- lib/presentation/app/widgets/window_tile.dart | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/presentation/app/widgets/window_tile.dart b/lib/presentation/app/widgets/window_tile.dart index 0521f570..9626fcfa 100644 --- a/lib/presentation/app/widgets/window_tile.dart +++ b/lib/presentation/app/widgets/window_tile.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:native_platform/native_platform.dart'; + import 'package:nyrna/application/app/app.dart'; /// Represents a visible window on the desktop, running state and actions. -class WindowTile extends StatelessWidget { +class WindowTile extends StatefulWidget { final Window window; const WindowTile({ @@ -12,21 +13,36 @@ class WindowTile extends StatelessWidget { required this.window, }) : super(key: key); + @override + State createState() => _WindowTileState(); +} + +class _WindowTileState extends State { + bool loading = false; + @override Widget build(BuildContext context) { + final window = widget.window; + return Card( - child: ListTile( - leading: _StatusWidget(window: window), - title: _TitleWidget(window: window), - subtitle: _DetailsWidget(window: window), - contentPadding: const EdgeInsets.symmetric( - vertical: 2, - horizontal: 20, - ), - onTap: () async { - final success = await context.read().toggle(window); - if (!success) await _showSnackError(context); - }, + child: Stack( + children: [ + ListTile( + leading: _StatusWidget(loading: loading, window: window), + title: _TitleWidget(window: window), + subtitle: _DetailsWidget(window: window), + contentPadding: const EdgeInsets.symmetric( + vertical: 2, + horizontal: 20, + ), + onTap: () async { + setState(() => loading = true); + final success = await context.read().toggle(window); + if (!success) await _showSnackError(context); + setState(() => loading = false); + }, + ), + ], ), ); } @@ -34,7 +50,7 @@ class WindowTile extends StatelessWidget { Future _showSnackError( BuildContext context, ) async { - final name = window.process.executable; + final name = widget.window.process.executable; final message = 'There was a problem interacting with $name'; final snackBar = SnackBar(content: Text(message)); ScaffoldMessenger.of(context).showSnackBar(snackBar); @@ -43,10 +59,12 @@ class WindowTile extends StatelessWidget { class _StatusWidget extends StatelessWidget { final Window window; + final bool loading; const _StatusWidget({ Key? key, required this.window, + required this.loading, }) : super(key: key); @override @@ -64,12 +82,13 @@ class _StatusWidget extends StatelessWidget { } return Container( - height: 20, - width: 20, + height: 25, + width: 25, decoration: BoxDecoration( shape: BoxShape.circle, - color: _color, + color: (loading) ? null : _color, ), + child: (loading) ? CircularProgressIndicator() : null, ); } } From 7915a75888df0addbd9b3a1b4dae292bc2496fef Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 11:05:55 -0400 Subject: [PATCH 41/83] Fix high CPU usage on Windows due to RunLoop issue https://github.com/flutter/flutter/issues/78517#issuecomment-814843107 --- windows/runner/run_loop.cpp | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/windows/runner/run_loop.cpp b/windows/runner/run_loop.cpp index 2d6636ab..f23c5f21 100644 --- a/windows/runner/run_loop.cpp +++ b/windows/runner/run_loop.cpp @@ -9,37 +9,10 @@ RunLoop::RunLoop() {} RunLoop::~RunLoop() {} void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } + MSG msg; + while (GetMessage(&msg, nullptr, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); } } From 9dc2390cc3edcf079773f1224ce2a2771e1a6f4b Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 13:21:16 -0400 Subject: [PATCH 42/83] Only get status on start & interactions This should resolve the memory leak on Windows --- lib/application/app/cubit/app_cubit.dart | 50 +++++++++++++++++-- .../native_platform/lib/src/win32/win32.dart | 3 +- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index e7cb8380..d4bc5267 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io' as io; import 'package:bloc/bloc.dart'; +import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; import 'package:native_platform/native_platform.dart'; @@ -80,13 +81,43 @@ class AppCubit extends Cubit { /// Populate the list of visible windows. Future _fetchWindows() async { - final windows = await _nativePlatform.windows(); + var windows = await _nativePlatform.windows(); windows.removeWhere( (window) => _filteredWindows.contains(window.process.executable), ); + windows = await _checkWindowStatuses(windows); emit(state.copyWith(windows: windows)); } + Future _getProcessStatus(int pid) async { + final process = NativeProcess(pid); + final status = await process.status; + return status; + } + + Future> _checkWindowStatuses(List windows) async { + final processedWindows = []; + for (var window in windows) { + final existingWindow = state.windows.singleWhereOrNull( + (stateWindow) => stateWindow.id == window.id, + ); + if (existingWindow != null) { + processedWindows.add( + window.copyWith(process: existingWindow.process), + ); + } else { + final pid = window.process.pid; + final status = await _getProcessStatus(pid); + processedWindows.add( + window.copyWith( + process: window.process.copyWith(status: status), + ), + ); + } + } + return processedWindows; + } + Future manualRefresh() async { emit(state.copyWith(loading: true)); await fetchData(); @@ -110,12 +141,25 @@ class AppCubit extends Cubit { /// Toggle suspend / resume for the process associated with the given window. Future toggle(Window window) async { + final pid = window.process.pid; + ProcessStatus status = await _getProcessStatus(pid); bool success; - if (window.process.status == ProcessStatus.suspended) { + if (status == ProcessStatus.suspended) { success = await _resume(window); + status = await _getProcessStatus(pid); + if (status != ProcessStatus.normal) success = false; } else { success = await _suspend(window); + status = await _getProcessStatus(pid); + if (status != ProcessStatus.suspended) success = false; } + final updatedWindow = window.copyWith( + process: window.process.copyWith(status: status), + ); + final windows = List.from(state.windows); + windows.removeWhere((e) => e.id == window.id); + windows.add(updatedWindow); + emit(state.copyWith(windows: windows)); return success; } @@ -124,7 +168,6 @@ class AppCubit extends Cubit { final success = await nativeProcess.resume(); // Restore the window _after_ resuming or it might not restore. await _nativePlatform.restoreWindow(window.id); - await fetchData(); return (success) ? true : false; } @@ -138,7 +181,6 @@ class AppCubit extends Cubit { } final nativeProcess = NativeProcess(window.process.pid); final success = await nativeProcess.suspend(); - await fetchData(); return (success) ? true : false; } diff --git a/packages/native_platform/lib/src/win32/win32.dart b/packages/native_platform/lib/src/win32/win32.dart index 1f5f7991..c9dacef2 100644 --- a/packages/native_platform/lib/src/win32/win32.dart +++ b/packages/native_platform/lib/src/win32/win32.dart @@ -94,11 +94,10 @@ class Win32 implements NativePlatform { final win32Process = await windowProcess(windowId); final executable = await win32Process.executable; final pid = win32Process.pid; - final status = await win32Process.status; final process = Process( executable: executable, pid: pid, - status: status, + status: ProcessStatus.unknown, ); windows.add( Window( From 683f53b5cdd8deffa771126e0399d8f5ebca601e Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 13:44:26 -0400 Subject: [PATCH 43/83] Sort windows alphabetically by executable name No more jumping around the list.. --- lib/application/app/cubit/app_cubit.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/application/app/cubit/app_cubit.dart b/lib/application/app/cubit/app_cubit.dart index d4bc5267..adc39524 100644 --- a/lib/application/app/cubit/app_cubit.dart +++ b/lib/application/app/cubit/app_cubit.dart @@ -79,6 +79,12 @@ class AppCubit extends Cubit { emit(state.copyWith(currentDesktop: currentDesktop)); } + List _sortWindows(List windows) { + return windows.sortedBy( + (window) => window.process.executable.toLowerCase(), + ); + } + /// Populate the list of visible windows. Future _fetchWindows() async { var windows = await _nativePlatform.windows(); @@ -86,7 +92,8 @@ class AppCubit extends Cubit { (window) => _filteredWindows.contains(window.process.executable), ); windows = await _checkWindowStatuses(windows); - emit(state.copyWith(windows: windows)); + final sortedWindows = _sortWindows(windows); + emit(state.copyWith(windows: sortedWindows)); } Future _getProcessStatus(int pid) async { @@ -159,7 +166,8 @@ class AppCubit extends Cubit { final windows = List.from(state.windows); windows.removeWhere((e) => e.id == window.id); windows.add(updatedWindow); - emit(state.copyWith(windows: windows)); + final sortedWindows = _sortWindows(windows); + emit(state.copyWith(windows: sortedWindows)); return success; } From 3aca534da78a5a5ed91c5d2d3f0c9f622a2f853f Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:17:23 -0400 Subject: [PATCH 44/83] Add c# dll experiment --- .../DesignTimeBuild/.dtbcache.v2 | Bin 0 -> 61678 bytes .../.vs/process_status_dll/v16/.suo | Bin 0 -> 72192 bytes .../process_status_dll/process_status_dll.sln | 31 ++++++ .../process_status_dll/Processes.cs | 80 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 36 +++++++ .../bin/Debug/process_status_dll.dll | Bin 0 -> 6144 bytes .../bin/Debug/process_status_dll.pdb | Bin 0 -> 22016 bytes .../bin/Release/process_status_dll.dll | Bin 0 -> 5632 bytes .../bin/Release/process_status_dll.pdb | Bin 0 -> 19968 bytes ...ework,Version=v4.7.2.AssemblyAttributes.cs | 4 + ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6728 bytes ..._status_dll.csproj.CoreCompileInputs.cache | 1 + ...ess_status_dll.csproj.FileListAbsolute.txt | 6 ++ ...s_status_dll.csprojAssemblyReference.cache | Bin 0 -> 8212 bytes .../obj/Debug/process_status_dll.dll | Bin 0 -> 6144 bytes .../obj/Debug/process_status_dll.pdb | Bin 0 -> 22016 bytes ...ework,Version=v4.7.2.AssemblyAttributes.cs | 4 + ...gnTimeResolveAssemblyReferencesInput.cache | Bin 0 -> 6732 bytes ..._status_dll.csproj.CoreCompileInputs.cache | 1 + ...ess_status_dll.csproj.FileListAbsolute.txt | 6 ++ ...s_status_dll.csprojAssemblyReference.cache | Bin 0 -> 424 bytes .../obj/Release/process_status_dll.dll | Bin 0 -> 5632 bytes .../obj/Release/process_status_dll.pdb | Bin 0 -> 19968 bytes .../process_status_dll.csproj | 48 ++++++++++ packages/process_status_dll/tester/Program.cs | 14 +++ .../netcoreapp3.1/process_status_dll.dll | Bin 0 -> 6144 bytes .../netcoreapp3.1/process_status_dll.pdb | Bin 0 -> 22016 bytes .../bin/Debug/netcoreapp3.1/tester.deps.json | 36 +++++++ .../tester/bin/Debug/netcoreapp3.1/tester.dll | Bin 0 -> 4608 bytes .../tester/bin/Debug/netcoreapp3.1/tester.exe | Bin 0 -> 174592 bytes .../tester/bin/Debug/netcoreapp3.1/tester.pdb | Bin 0 -> 9596 bytes .../tester.runtimeconfig.dev.json | 8 ++ .../netcoreapp3.1/tester.runtimeconfig.json | 9 ++ .../netcoreapp3.1/process_status_dll.dll | Bin 0 -> 5632 bytes .../netcoreapp3.1/process_status_dll.pdb | Bin 0 -> 19968 bytes .../Release/netcoreapp3.1/tester.deps.json | 36 +++++++ .../bin/Release/netcoreapp3.1/tester.dll | Bin 0 -> 4608 bytes .../bin/Release/netcoreapp3.1/tester.exe | Bin 0 -> 174592 bytes .../bin/Release/netcoreapp3.1/tester.pdb | Bin 0 -> 9548 bytes .../tester.runtimeconfig.dev.json | 8 ++ .../netcoreapp3.1/tester.runtimeconfig.json | 9 ++ ...CoreApp,Version=v3.1.AssemblyAttributes.cs | 4 + .../obj/Debug/netcoreapp3.1/apphost.exe | Bin 0 -> 174592 bytes .../netcoreapp3.1/tester.AssemblyInfo.cs | 23 +++++ .../tester.AssemblyInfoInputs.cache | 1 + .../Debug/netcoreapp3.1/tester.assets.cache | Bin 0 -> 142 bytes .../netcoreapp3.1/tester.csproj.CopyComplete | 0 .../tester.csproj.CoreCompileInputs.cache | 1 + .../tester.csproj.FileListAbsolute.txt | 16 ++++ .../tester.csprojAssemblyReference.cache | Bin 0 -> 107348 bytes .../tester/obj/Debug/netcoreapp3.1/tester.dll | Bin 0 -> 4608 bytes .../tester.genruntimeconfig.cache | 1 + .../tester/obj/Debug/netcoreapp3.1/tester.pdb | Bin 0 -> 9596 bytes ...CoreApp,Version=v3.1.AssemblyAttributes.cs | 4 + .../obj/Release/netcoreapp3.1/apphost.exe | Bin 0 -> 174592 bytes .../netcoreapp3.1/tester.AssemblyInfo.cs | 23 +++++ .../tester.AssemblyInfoInputs.cache | 1 + .../Release/netcoreapp3.1/tester.assets.cache | Bin 0 -> 142 bytes .../netcoreapp3.1/tester.csproj.CopyComplete | 0 .../tester.csproj.CoreCompileInputs.cache | 1 + .../tester.csproj.FileListAbsolute.txt | 16 ++++ .../tester.csprojAssemblyReference.cache | Bin 0 -> 3539 bytes .../obj/Release/netcoreapp3.1/tester.dll | Bin 0 -> 4608 bytes .../tester.genruntimeconfig.cache | 1 + .../obj/Release/netcoreapp3.1/tester.pdb | Bin 0 -> 9548 bytes .../tester/obj/project.assets.json | 89 ++++++++++++++++++ .../tester/obj/project.nuget.cache | 8 ++ .../obj/tester.csproj.nuget.dgspec.json | 76 +++++++++++++++ .../tester/obj/tester.csproj.nuget.g.props | 18 ++++ .../tester/obj/tester.csproj.nuget.g.targets | 6 ++ .../process_status_dll/tester/tester.csproj | 12 +++ 71 files changed, 638 insertions(+) create mode 100644 packages/process_status_dll/.vs/process_status_dll/DesignTimeBuild/.dtbcache.v2 create mode 100644 packages/process_status_dll/.vs/process_status_dll/v16/.suo create mode 100644 packages/process_status_dll/process_status_dll.sln create mode 100644 packages/process_status_dll/process_status_dll/Processes.cs create mode 100644 packages/process_status_dll/process_status_dll/Properties/AssemblyInfo.cs create mode 100644 packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.dll create mode 100644 packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.pdb create mode 100644 packages/process_status_dll/process_status_dll/bin/Release/process_status_dll.dll create mode 100644 packages/process_status_dll/process_status_dll/bin/Release/process_status_dll.pdb create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.CoreCompileInputs.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.FileListAbsolute.txt create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csprojAssemblyReference.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.dll create mode 100644 packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.pdb create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.csproj.CoreCompileInputs.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.csproj.FileListAbsolute.txt create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.csprojAssemblyReference.cache create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.dll create mode 100644 packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.pdb create mode 100644 packages/process_status_dll/process_status_dll/process_status_dll.csproj create mode 100644 packages/process_status_dll/tester/Program.cs create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.dll create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.pdb create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.deps.json create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.dll create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.exe create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.pdb create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.runtimeconfig.dev.json create mode 100644 packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.runtimeconfig.json create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/process_status_dll.dll create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/process_status_dll.pdb create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.deps.json create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.dll create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.exe create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.pdb create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.runtimeconfig.dev.json create mode 100644 packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.runtimeconfig.json create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/apphost.exe create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.AssemblyInfo.cs create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.AssemblyInfoInputs.cache create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.assets.cache create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CopyComplete create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CoreCompileInputs.cache create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.FileListAbsolute.txt create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csprojAssemblyReference.cache create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.dll create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.genruntimeconfig.cache create mode 100644 packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.pdb create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/apphost.exe create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.AssemblyInfo.cs create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.AssemblyInfoInputs.cache create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.assets.cache create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.csproj.CopyComplete create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.csproj.CoreCompileInputs.cache create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.csproj.FileListAbsolute.txt create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.csprojAssemblyReference.cache create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.dll create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.genruntimeconfig.cache create mode 100644 packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.pdb create mode 100644 packages/process_status_dll/tester/obj/project.assets.json create mode 100644 packages/process_status_dll/tester/obj/project.nuget.cache create mode 100644 packages/process_status_dll/tester/obj/tester.csproj.nuget.dgspec.json create mode 100644 packages/process_status_dll/tester/obj/tester.csproj.nuget.g.props create mode 100644 packages/process_status_dll/tester/obj/tester.csproj.nuget.g.targets create mode 100644 packages/process_status_dll/tester/tester.csproj diff --git a/packages/process_status_dll/.vs/process_status_dll/DesignTimeBuild/.dtbcache.v2 b/packages/process_status_dll/.vs/process_status_dll/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000000000000000000000000000000000000..50ff670b048d32429216f5638cd85c1ada0eb495 GIT binary patch literal 61678 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 Ctx4bj literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll.sln b/packages/process_status_dll/process_status_dll.sln new file mode 100644 index 00000000..f4b549c0 --- /dev/null +++ b/packages/process_status_dll/process_status_dll.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31205.134 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "process_status_dll", "process_status_dll\process_status_dll.csproj", "{F530A5A2-5FA8-4B70-98C0-DC537BE8D974}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tester", "tester\tester.csproj", "{B110497C-FE20-45CF-A1CF-BE7055750B9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F530A5A2-5FA8-4B70-98C0-DC537BE8D974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F530A5A2-5FA8-4B70-98C0-DC537BE8D974}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F530A5A2-5FA8-4B70-98C0-DC537BE8D974}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F530A5A2-5FA8-4B70-98C0-DC537BE8D974}.Release|Any CPU.Build.0 = Release|Any CPU + {B110497C-FE20-45CF-A1CF-BE7055750B9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B110497C-FE20-45CF-A1CF-BE7055750B9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B110497C-FE20-45CF-A1CF-BE7055750B9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B110497C-FE20-45CF-A1CF-BE7055750B9C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {966BC76F-2532-430E-A98B-7903FC5CFA65} + EndGlobalSection +EndGlobal diff --git a/packages/process_status_dll/process_status_dll/Processes.cs b/packages/process_status_dll/process_status_dll/Processes.cs new file mode 100644 index 00000000..43b65e9f --- /dev/null +++ b/packages/process_status_dll/process_status_dll/Processes.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +// This works and is clean, however it is quite slow at getting the suspended state. +// +// Getting the status of just 4 or 5 processes takes ~7 - 10 seconds, compared to less than +// half that for a PowerShell call directly from dart. + +namespace process_status_dll +{ + static public class Processes + { + static public String check() + { + var processes = Process.GetProcesses(); + foreach (Process process in processes) + { + var shouldFilter = filteredWindows.Contains(process.ProcessName); + if (shouldFilter) continue; + var hasNoTitle = (process.MainWindowTitle != ""); + if (hasNoTitle) continue; + var pid = process.Id; + var name = process.ProcessName; + var windowTitle = process.MainWindowTitle; + var threadsWaiting = threadsAreWaiting(process.Threads); + var suspended = (threadsWaiting) ? threadsAreSuspended(process.Threads) : false; + Console.WriteLine( + $"pid: {pid},\n" + + $"name: {name}\n" + + $"windowTitle: {windowTitle}\n" + + $"suspended: {suspended}\n" + ); + } + return "boop"; + } + + private static bool threadsAreWaiting(ProcessThreadCollection threads) { + foreach(ProcessThread thread in threads) + { + if (thread.ThreadState != ThreadState.Wait) return false; + } + return true; + } + + private static bool threadsAreSuspended(ProcessThreadCollection threads) + { + foreach (ProcessThread thread in threads) + { + if (thread.WaitReason != ThreadWaitReason.Suspended) return false; + } + return true; + } + + private static List filteredWindows = new List { + "nyrna", + "ApplicationFrameHost", // Manages UWP (Universal Windows Platform) apps + "Calculator", + "devenv", + "explorer", // Windows File Explorer + "googledrivesync", + "HxCalendarAppImm", + "HxOutlook", + "LogiOverlay", // Logitech Options + "Microsoft.Notes", + "PenTablet", // XP-PEN driver + "perfmon", // Resource Monitor + "Rainmeter", + "SystemSettings", // Windows system settings + "Taskmgr", // Windows Task Manager + "TextInputHost", // Microsoft Text Input Application + "VsDebugConsole", + "WinStore.App", // Windows Store + }; + } +} diff --git a/packages/process_status_dll/process_status_dll/Properties/AssemblyInfo.cs b/packages/process_status_dll/process_status_dll/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f4c8be07 --- /dev/null +++ b/packages/process_status_dll/process_status_dll/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("process_status_dll")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("process_status_dll")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f530a5a2-5fa8-4b70-98c0-dc537be8d974")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.dll b/packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..2a5e25404f6c8980fd1b013fbb724b2e4c868915 GIT binary patch literal 6144 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 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.pdb b/packages/process_status_dll/process_status_dll/bin/Debug/process_status_dll.pdb new file mode 100644 index 0000000000000000000000000000000000000000..9639210da4a8a312430271679f7b30077b1f6b8c GIT binary patch literal 22016 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 +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/packages/process_status_dll/process_status_dll/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000000000000000000000000000000000000..b604483fe4ef437d96b8e016c4c7010e10f8fec7 GIT binary patch literal 6728 zcmeHMZBH9V5VpZwFoYCSN(dzBrH$Gobx(G9kHm-6#tCXb$aZKYY&q+@vDt7h?(QDo zB7RGMLDiqw&YbNt0Ya4xeeYda2w`K=33lh3VJiCS1vYu+b#&^z=vzP@!G#V>B2)KS-& zdY@mf;?b4q`S{gmpGnRzb2RG#1(qr8W98- z>$yUoFy*>Sz$*H#;tq6|T-MZylAQM?6rlkETvSyMo`Xt1qNaPI*BgXI8_`BJEfyO^ zITDY@HT*>x8~J0b)RqbyOi$cjQ&GYhZ@>k?P2(K~>qGY7;D#x9BKDc>!ye<}!^?1L zNeS*Y)4C%~PuRTPKV!@P`G~Epu@!S=HM_C244L(fYWgNSZmFqJ#GyLau-`E{1_*ZBr!o^ z62*je7iCPFLXkf!cA3+w5)$bXCZH0M-HNfhRSr31`gqw`GhU{96tqh>w@%Nsd#K6H zy{f#I$UiGPAOu&cl8568ax`K>H6mlatXZ~wU6)t?h_mZ{6QxAzSw?zP1nJqwAs6m* zA;V{M5=GGsaS8 zDZ7#U3jdBxq$tGntId%xPPpq>+I?&%4D?Bx4_a^vsbCjq4pD!OF+tkaME0%+WL|%E zy1x3n5;~)IgNcOqLfAt~Kiz;z$JqWvBUd_Pq7_)MfN(4lxE|9BU=|U^iUcO4q5=Y> zhlq3>B~qR#W{@a>>c5i(*pH(2GQg(9d5lQ4D7_?*uMy-hN|0Sp##^O2nW!V08711U zjvegMlc?Pypm*H;jnEQwvkv*dkPi&>&3DjrI{1pJVa36bV>QWthw<8Rrv!#0eLE*6Tef;+0em)xJgXK9VawMYJ`*c#4fg z0ZW;2qObw4y=Y9FIPI0*6p>tdQbcsgUhO*+^JlqhYpdtl_c%Ip_LjSfs%cba+s4Cl zu06y4g|qVYg~Rr__8i9t!<}ECrm3?cJ0XHdrNwjY2khFy@cv&qUFU9>PN#?^(>sEe xMiI@HX+NUsY9!fEU?#JW8m9sljxcwE6rlW|XY|kEjrMQ<&KTZkVVSu)`48HyxYYmv literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.CoreCompileInputs.cache b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..569d9630 --- /dev/null +++ b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +9b75548cf48f936b891133670e593c4645f1fba7 diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.FileListAbsolute.txt b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..ae9a0871 --- /dev/null +++ b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csproj.FileListAbsolute.txt @@ -0,0 +1,6 @@ +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\bin\Debug\process_status_dll.dll +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\bin\Debug\process_status_dll.pdb +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\obj\Debug\process_status_dll.csprojAssemblyReference.cache +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\obj\Debug\process_status_dll.csproj.CoreCompileInputs.cache +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\obj\Debug\process_status_dll.dll +C:\Users\Merritt\Dev\process_status_dll\process_status_dll\obj\Debug\process_status_dll.pdb diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csprojAssemblyReference.cache b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.csprojAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..fe6fe18bc4810510796c503263c6089eaff4edbc GIT binary patch literal 8212 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 ZF=v$Wz>0Q&rQ!k6i!& literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.dll b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..2a5e25404f6c8980fd1b013fbb724b2e4c868915 GIT binary patch literal 6144 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 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.pdb b/packages/process_status_dll/process_status_dll/obj/Debug/process_status_dll.pdb new file mode 100644 index 0000000000000000000000000000000000000000..9639210da4a8a312430271679f7b30077b1f6b8c GIT binary patch literal 22016 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 +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] diff --git a/packages/process_status_dll/process_status_dll/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache b/packages/process_status_dll/process_status_dll/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000000000000000000000000000000000000..6cfcf195d07f3b31c6478792cc396ea5a7247655 GIT binary patch literal 6732 zcmeHMZBH9V5VpZwFoYCSN(dzBrH$Gobx(G9kHm-6#tCXb$aZKYY&q+@vDt7h?(QDo zB7RGMLDiqw&YbNt0Ya4xeeYda2w`K=33lh3VJiCS1vYu+b#&^z=vzP@!G#V>B2)KS-& zdY@mf;?b4q`S{gmpGnRzb2RG#1(qr8W98- z>$yUoFy*>Sz$*H#;tq6|T-MZylAQM?6rlkETvSyMo`Xt1qNaPI*BgXI8_`BJEfyO^ zITDY@HT*>x8~J0b)RqbyOi$cjQ&GYhZ@>k?P2(K~>qGY7;D#x9BKDc>!ye<}!^?1L zNeS*Y)4C%~PuRTPKV!@P`G~Epu@!S=HM_C244L(fYWgNSZmFqJ#GyLau-`E{1_*ZBr!o^ z62*je7iCPFLXkf!cA3+w5)$bXCZH0M-HNfhRSr31`gqw`GhU{96tqh>w@%Nsd#I_E zdsTTak$+ZpKnSi>B@f3Hf%YDC6-S+i{Wx-PH&u~GyZm;_uUk$jesAQeG+_HoFD z`)tTCnRy7wFUW~$6c0bOvq$j9nD zpPjC+K1Xl6)K2e)6DjY7z=xK8x&@VvvHgigu5`#mE3jYz;aDVaJ+2qPEFz2*2~0>v z1q4VB5$QNeq&!p1AW;I7?EmGdPyK(BgkQtAiJQ9w@P&~QAad0 zO0-`cJJ_WsQM*Mz@3{LLp(W^U9WsI;BN*tr@1O~F@D)|Vnu8<9YLfpBeT(9KBv*Wjh--lH z6dQ>G7Bk~SVgqJ-(U>@~+AF;&qPg^>i0YEP+IJ}C&vMsRSI@QYadhVFEq4{w)2Pt4 zjfdx4dxrfBXXWclhwXFiIgSs8J-}Rpp$U8=jriQbXplTSbpJz?D-PR+VEOw%(E40BhxMO(~=YB(Lrvabr5Lri8Tzk4)WV{y}1ut;6WAS8a> z!sG8JpF&FPtdC&$6_^(btwc(lgq|Xze_JQM;owF=e+ivcdVjZ1>f_dG^9maEl;$?# z4I^JPlNCsZhOv;vaXLNP<+#(m7(xDM-XG4+{b-g%o+w2U6Omm+r9X7EW%?wZNB_As P7-T^(BOzf%VnX@}lm~U4 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.dll b/packages/process_status_dll/process_status_dll/obj/Release/process_status_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..78da3027601752c37b6a2fea38f08f1036dd1acb GIT binary patch literal 5632 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 + + + + Debug + AnyCPU + {F530A5A2-5FA8-4B70-98C0-DC537BE8D974} + Library + Properties + process_status_dll + process_status_dll + v4.7.2 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/process_status_dll/tester/Program.cs b/packages/process_status_dll/tester/Program.cs new file mode 100644 index 00000000..2e616f82 --- /dev/null +++ b/packages/process_status_dll/tester/Program.cs @@ -0,0 +1,14 @@ +using process_status_dll; +using System; + +namespace tester +{ + class Program + { + static void Main(string[] args) + { + var check = Processes.check(); + Console.WriteLine(check); + } + } +} diff --git a/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.dll b/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..2a5e25404f6c8980fd1b013fbb724b2e4c868915 GIT binary patch literal 6144 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 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.pdb b/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/process_status_dll.pdb new file mode 100644 index 0000000000000000000000000000000000000000..9639210da4a8a312430271679f7b30077b1f6b8c GIT binary patch literal 22016 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 ke4iO_CjkO8 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.exe b/packages/process_status_dll/tester/bin/Debug/netcoreapp3.1/tester.exe new file mode 100644 index 0000000000000000000000000000000000000000..91b4f9f6cd5eb9af7920cf983fcf09745692b5d2 GIT binary patch literal 174592 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≻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
    ix_kEZm|>N4?>*%xwNCk!Of|Dr?6 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 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.exe b/packages/process_status_dll/tester/bin/Release/netcoreapp3.1/tester.exe new file mode 100644 index 0000000000000000000000000000000000000000..91b4f9f6cd5eb9af7920cf983fcf09745692b5d2 GIT binary patch literal 174592 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≻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

      ix_kEZm|>N4?>*%xwNCk!Of|Dr?6 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 +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.1", FrameworkDisplayName = "")] diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/apphost.exe b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/apphost.exe new file mode 100644 index 0000000000000000000000000000000000000000..91b4f9f6cd5eb9af7920cf983fcf09745692b5d2 GIT binary patch literal 174592 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≻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
        ix_kEZm|>N4?>*%xwNCk!Of|Dr?6 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 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("tester")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("tester")] +[assembly: System.Reflection.AssemblyTitleAttribute("tester")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.AssemblyInfoInputs.cache b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.AssemblyInfoInputs.cache new file mode 100644 index 00000000..b4bb6d54 --- /dev/null +++ b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +4adf57fbc026b45674d6234a508d7e8e94097f00 diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.assets.cache b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.assets.cache new file mode 100644 index 0000000000000000000000000000000000000000..1940a5277dccf1239ad8888c16b6073ba35ec489 GIT binary patch literal 142 zcmWIWc6a1rU|{G-wa(>U{cdy0N&h_uD$lk8T|hO203%R= oqO(;@XmM&$ag1+jQBh_|NsL}zX?ki&OhICDc4B&JaST3F0BnjLNB{r; literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CopyComplete b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CopyComplete new file mode 100644 index 00000000..e69de29b diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CoreCompileInputs.cache b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..677f0137 --- /dev/null +++ b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +dbd3a080d0828087bd0465cd04fb8fb18bfd6a9c diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.FileListAbsolute.txt b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..d0fbaa14 --- /dev/null +++ b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csproj.FileListAbsolute.txt @@ -0,0 +1,16 @@ +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.exe +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.deps.json +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.runtimeconfig.json +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.runtimeconfig.dev.json +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.dll +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\tester.pdb +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\process_status_dll.dll +C:\Users\Merritt\Dev\process_status_dll\tester\bin\Debug\netcoreapp3.1\process_status_dll.pdb +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.csprojAssemblyReference.cache +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.AssemblyInfoInputs.cache +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.AssemblyInfo.cs +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.csproj.CoreCompileInputs.cache +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.csproj.CopyComplete +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.dll +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.pdb +C:\Users\Merritt\Dev\process_status_dll\tester\obj\Debug\netcoreapp3.1\tester.genruntimeconfig.cache diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csprojAssemblyReference.cache b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.csprojAssemblyReference.cache new file mode 100644 index 0000000000000000000000000000000000000000..026a3bcdb1cede27807bdb49f3c192d4160884b2 GIT binary patch literal 107348 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 aH}1^~(ChbUFF{@6}S z^IG+;@0ojk?)kev=X&+qFHjE=^`hUpMf4`V+%g(|GPnZv@K@d*rZ@Jz_u!kx%6ktM zDy|Z>Ferz1RXDcq2azaB5!QX-`XYNKFRDRFT0=wWhZ5DfMWPj>hyI!S#w#srH_4>^ z#stwIDBRJ0_f-IaoXe>gPp!W=qGek3e z391rTIk={!2?Lg?KsLv*qm=kcqYS2Xr5MST%zU!<3f$ADeb z*mH-jK|A6Br7yLQuEDnvz<#>h_bx)q4d{afTYApo53Ow0D&({6Otx9@2bR)Uq z`jWD;STC3Dq9^Ag?3ZFak~FWBtQNgy!Hv4f1v@OuXbBgUyc~oV_sTE1o?Mrqasz)a zbJ^bt!m1sCX?q_l1%J2Pay`^?9VH7vwdQ)7cvgD$wjQYtzvXc*MEFj$m%$2bzu93V znb7peExMi?b#bE#PR_2RS&7rki6pWcS|!gT+}(~;YEwmaR9Bl!f){+9C-Z65cKx<4 zx#dZRlaS~j%ZY-p#m>5R*$-6YI;urV9K}j<3S^jnG~HV zUVxp}o|$v6Hy(NQ_e;NcQhe!W^DkbeUSSx6J%Wrr3`Ry69qt)GM}5N9GKL3VpWA$P z0?)tZ_JnN*G*L2IL0x{(Rh^L)O}2VIc_R ze69BNBzd!qDQgl6hVN9R&#tBE}-8;-MKl?iab6&2Z267+ikBz9f-bT*&OzyE{RUiN-8aO#!g zuZi`oKmV0OTA1EAr?9&>R%M9e6K!N=V`J~?Z^Zs@1jP%Gz~S2PW#k|WcCCik6Sh?= z6)Ase{>bCUC^2@UWefrJ{^z5AJbSDBh3kK;{NcAhNeT`-e2vF~M|)eVFvXlrWPWj5 z>djYG?10q!HJNwoVG^0WIzFe|VFpsVmI}P04q;{v-<=BLDs}uebe7vC3`#6t*~8L@ zie_*=U&s($ZC(ACaW!=maGmnB3AjjSFYLwZ<pLsczD*J20$_1_z4tEoYQU!mQZDG_ z+i3a#h7Fo%|Bj-H;;5ry4uHM@eO0Py8%;!H1Cv^Pgs*~T3EkX|Y5A6?SLR^ouE2xtE$zQG)2|+-7OUFRyor4piGFivgMM*BPnX`@QF*0DSXtZS#!0C zg66r7euP-K*3I!)Llo9k#P6I>>CX{U&x36xojPhtGr>U#<)u15GD^A7ZJ_R#rTUaw zr&?MCT1O9Rfm7#7y&@aZ6CT4^(^kuVBe*C-Q`FsghhGr0=9cX#nFOVkjNitamh0m? ke4iO_CjkO8 literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.genruntimeconfig.cache b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.genruntimeconfig.cache new file mode 100644 index 00000000..5cfe10de --- /dev/null +++ b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.genruntimeconfig.cache @@ -0,0 +1 @@ +49ce694314afd82411617ead736cc32fc4b9dedf diff --git a/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.pdb b/packages/process_status_dll/tester/obj/Debug/netcoreapp3.1/tester.pdb new file mode 100644 index 0000000000000000000000000000000000000000..306170caf01fd70a0d5cfd1524fd6bc1b320d012 GIT binary patch literal 9596 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 +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.1", FrameworkDisplayName = "")] diff --git a/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/apphost.exe b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/apphost.exe new file mode 100644 index 0000000000000000000000000000000000000000..91b4f9f6cd5eb9af7920cf983fcf09745692b5d2 GIT binary patch literal 174592 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≻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

          ix_kEZm|>N4?>*%xwNCk!Of|Dr?6 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 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("tester")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] +[assembly: System.Reflection.AssemblyProductAttribute("tester")] +[assembly: System.Reflection.AssemblyTitleAttribute("tester")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.AssemblyInfoInputs.cache b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.AssemblyInfoInputs.cache new file mode 100644 index 00000000..3e6f0b41 --- /dev/null +++ b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +28339ae3a62766e0e5429d37ce0e272644d8e2b3 diff --git a/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.assets.cache b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.assets.cache new file mode 100644 index 0000000000000000000000000000000000000000..89c4b595c641ebbd6a3ec6c21eac0db901ff5669 GIT binary patch literal 142 zcmWIWc6a1rU|>kEaM>k)ZN2Bdv$Gm>Uvwp(oYXS&(@oCFA)e=TS2WJL+XYlZ2rvQ_ pC^}okgche37039d78PZdl*H)em8Peb#1teZXD6no7RTT-1pqkuATFncZka)3iT8@E2uX z2ld%5_hq7zF!SEexd^-is`|=nB$6#J9WtqS5^vV(Ud^j|)#ar|F0x#*&6wqxq+)sL ze%=w>|A-9^l0J(!JJpr298#Qx2CVr9H@*%&5ULYXE`AktavNk9Daf* zgkXLKAt>)2RlSUM1jDGE5-0=JKTfq^g8OkogKg?(i7b!yGY8=|k|?E;NgMq(`6Fh) zpt26B$eGf#l4hE7_O($QpU8m6R7`9hKe+R55rzQ^U=)st3YRl*=x^+Bmve32jRD*S zRZJsf5e;$NDuX(1Y_vXA0D5beNy)RU^#MC+r84oEQf&oD<*FSBF>R>B{ z?19xH##bP1!-I+H_P=K4_Vzd{F3c}QNnpTVU#GDVuvA$Jv!+a$oiM3~u^GkyvJu8R zffYvgWfCGJ7ST$CIQH_{<(fUnLEvpE#iEWF?9qtb{W4=QvJL_EW-&NAMiX**l(bQ@ zaqQuHZ~gxL;SYAPc?Sj@+>A2^%9;n|o~#1BSE?(ub>dvY(aWGNd3$#cwk5>$MI!sw z0t{&;TFE={VMnJjbFM8sUQO!F;p;_xWSiz=}ti)fm%KqGn?DXNu9L`ML0 zqMw1twuxPzlw2J0ZZ0WS-8eCvsqy3B-Y~iZ=-G?jxv14B8N>bX4i`Kd5JHNCS&I$%OcJdV{<2PtxPZuxxD4$@Bx7(U+d=1VXgR}p(jVFBK3f4=Y7#7Ax zrBZ2ZREnCejB2_9HC;Ks+i62k)0I(8Px*{B?ONAht)27kPBm}r+!yKHaV`WnbIVv9 z1>Be(V!7Y+g`pT&RA*R+jnZoG(uawJ9}Z2?Y8OY4)81z%99saI+8{U; z`y+bC6KnyAfua*+2RcXGPs{ubc-x!M^Ym$kwSFN$I%{jR?$_V0t*@-I>Ya5HH#QR- z&r$K~dXdfNsQAAnll1&`%zwyYCb?f6_f3|4UOPIP-e-=FkynT$v0edf zN6Js6;2qa_6<(d2pvF=(EAlJw6&n_gl3(Bf8xFG7b&EsjHFz|!SpFxL=sufMZjAR`tdxi-hk-~NJ+fr>EAtS9o|^|`5S`##CC}t^|Y8s z!xs}byxfd$_V(n8-k>S<;gSJ6wa?vhr(8S7hFID*);Nmu=I~crz$`q8B&K87)R7JfDUi8H~ou?Q##k!{8age+;>aS}PkPW(>{wqr8mAXc+DJw4@dLr?e6 z)iZc5yV(P9SSex!K>{x9?vWr6aBx6~>mFdm1!=V>Bsi>AE0AEdKdeOdd)3`D<2WoJ zaYEF%Ue&Aj>ecsNSJf*o{`_g`Afisxt5=CO(Q=v4^#79!5NCe+R)*f(`Tp&jV&VPU z^XrZ>s)1h)tcqbLgeo30Wz3Kh2>E&6X1<^sj|K#((B&&Ty zS=uEAiFz=?73K9iKn&CgR3-+RRD>Hnjh|b(fQoT09d!N)qTTwh)y8b3LaVTQhWisl zV_orJdvl)X2JjmPi1O{@-_$pn(6wd{_|t83%usHG;5WNLAk%)vxWVaS5S=#z71-c3 zwh44tKaJW}CV<`yr0YYGvC?@|wguPQ%LLI>JJ0=RIIbv+Ek#{aGKlsd4gx$XulAja zd2ko-9R!T@p?#@?z1&Xa?wbenCqZ=@T!2ULmG+O`p;9- zQ?3PCuVrM~uT&jZ51y5-wV`{eB~K792XNmGw+q;SD@JeavQXcr(~oBGdEQsnuWgeV88Y0(V=cN5tu4A0M)O z>gERntGeWSvm3UovMc%Zz<*o`=tX<-n4rDp(rkX(59DOEdUqVS@%pei1Ou5p%{?^Z zsH$r!>ZN3BFJAk^Q zDc0xbMzD9Hj^LgiiF0A1an1EkXLB>TPmlfQ;w!hkH2s{@oxi)|H@EVkn;tE!DD3XS zq6~0+!orNK7q)->LgYiiFFsO;T_|`mv=IxdT15n61+!WzQttHRkz>axUM_boUJfpu zSbYA=S2Lr_AHV#8`QlS?dSS@FD2>dOl-IC zPyAvoion;c6UA*A^L?ydBO8`m=(fjg5brd+skZ1}8--R3aIflkO(I4L zzEtqFTzFw%r)-T}YYxW`Z_jC>za`rb{AX{!J9cWL;u`hnDKVbKeV;X?XZs~&yYcKw ze(vx{)IE9TZm^dM24G+0%JiFLHqH`TvKTJ$q z^x1*PLKxIk$Zwx-iRVaG&%@eE+BM{vM$BU*kdM{);Za%+oI2hDWvRZU)#1ddfzq;r z>|ob8gD=RsbPbp3c-B($Ufq9G23e!#Oxpaa7|*U*u9C4++Q`6l&?L|YwqPF{Xa)fa eV*|+-I*E_{Ln%h|KiQkde<%+9=*M@7!2ba31G)PE literal 0 HcmV?d00001 diff --git a/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.genruntimeconfig.cache b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.genruntimeconfig.cache new file mode 100644 index 00000000..5cfe10de --- /dev/null +++ b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.genruntimeconfig.cache @@ -0,0 +1 @@ +49ce694314afd82411617ead736cc32fc4b9dedf diff --git a/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.pdb b/packages/process_status_dll/tester/obj/Release/netcoreapp3.1/tester.pdb new file mode 100644 index 0000000000000000000000000000000000000000..5efcaf9a9fee1c0f46ba8816161e2a0d64bbf3d3 GIT binary patch literal 9548 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 1.0.0" + ] + }, + "packageFolders": { + "C:\\Users\\Merritt\\.nuget\\packages\\": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj", + "projectName": "tester", + "projectPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj", + "packagesPath": "C:\\Users\\Merritt\\.nuget\\packages\\", + "outputPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\Merritt\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netcoreapp3.1" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netcoreapp3.1": { + "targetAlias": "netcoreapp3.1", + "projectReferences": { + "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj": { + "projectPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "netcoreapp3.1": { + "targetAlias": "netcoreapp3.1", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\5.0.202\\RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/packages/process_status_dll/tester/obj/project.nuget.cache b/packages/process_status_dll/tester/obj/project.nuget.cache new file mode 100644 index 00000000..5ab948a5 --- /dev/null +++ b/packages/process_status_dll/tester/obj/project.nuget.cache @@ -0,0 +1,8 @@ +{ + "version": 2, + "dgSpecHash": "tVjwY1t6tAWrMFjFAM6wyVo5NhNgyZdygzxlpqwaMPCwcDGNpgRKHdB8pIOLXN3qvPXalGURU1y/viSpFF88Qw==", + "success": true, + "projectFilePath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj", + "expectedPackageFiles": [], + "logs": [] +} \ No newline at end of file diff --git a/packages/process_status_dll/tester/obj/tester.csproj.nuget.dgspec.json b/packages/process_status_dll/tester/obj/tester.csproj.nuget.dgspec.json new file mode 100644 index 00000000..3b79e9a3 --- /dev/null +++ b/packages/process_status_dll/tester/obj/tester.csproj.nuget.dgspec.json @@ -0,0 +1,76 @@ +{ + "format": 1, + "restore": { + "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj": {} + }, + "projects": { + "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj": { + "restore": { + "projectUniqueName": "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj", + "projectName": "process_status_dll", + "projectPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj" + }, + "frameworks": { + "net472": {} + } + }, + "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj", + "projectName": "tester", + "projectPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\tester.csproj", + "packagesPath": "C:\\Users\\Merritt\\.nuget\\packages\\", + "outputPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\tester\\obj\\", + "projectStyle": "PackageReference", + "configFilePaths": [ + "C:\\Users\\Merritt\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "netcoreapp3.1" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netcoreapp3.1": { + "targetAlias": "netcoreapp3.1", + "projectReferences": { + "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj": { + "projectPath": "C:\\Users\\Merritt\\Dev\\process_status_dll\\process_status_dll\\process_status_dll.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + } + }, + "frameworks": { + "netcoreapp3.1": { + "targetAlias": "netcoreapp3.1", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\5.0.202\\RuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.props b/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.props new file mode 100644 index 00000000..07bfff9b --- /dev/null +++ b/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.props @@ -0,0 +1,18 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + $(UserProfile)\.nuget\packages\ + C:\Users\Merritt\.nuget\packages\ + PackageReference + 5.9.1 + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + \ No newline at end of file diff --git a/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.targets b/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.targets new file mode 100644 index 00000000..53cfaa19 --- /dev/null +++ b/packages/process_status_dll/tester/obj/tester.csproj.nuget.g.targets @@ -0,0 +1,6 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + \ No newline at end of file diff --git a/packages/process_status_dll/tester/tester.csproj b/packages/process_status_dll/tester/tester.csproj new file mode 100644 index 00000000..60f53374 --- /dev/null +++ b/packages/process_status_dll/tester/tester.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + From de3fc56bb86d60f0860adc7f2ffd7a060fa7fabb Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:20:17 -0400 Subject: [PATCH 45/83] Add NtQuerySystemInformation experiment --- packages/ntquerysysteminformation/.gitignore | 8 + .../ntquerysysteminformation/CHANGELOG.md | 3 + packages/ntquerysysteminformation/README.md | 1 + .../analysis_options.yaml | 16 + .../example/GetNativeSystemInfo.dart | 66 + .../example/NtQuerySystemInformation.dart | 72 + .../example/ntdll/_winternl.dart | 1386 +++++ .../example/ntdll/_winternl.h | 3 + .../example/ntdll/winternl.dart | 18 + .../example/ntdll/winternl.yaml | 21 + .../example/ntstatus/_ntstatus.h | 3 + .../example/ntstatus/ntstatus.dart | 5532 +++++++++++++++++ .../example/ntstatus/ntstatus.yaml | 11 + .../lib/dynamic_load.dart | 14 + .../ntquerysysteminformation/pubspec.lock | 152 + .../ntquerysysteminformation/pubspec.yaml | 15 + 16 files changed, 7321 insertions(+) create mode 100644 packages/ntquerysysteminformation/.gitignore create mode 100644 packages/ntquerysysteminformation/CHANGELOG.md create mode 100644 packages/ntquerysysteminformation/README.md create mode 100644 packages/ntquerysysteminformation/analysis_options.yaml create mode 100644 packages/ntquerysysteminformation/example/GetNativeSystemInfo.dart create mode 100644 packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart create mode 100644 packages/ntquerysysteminformation/example/ntdll/_winternl.dart create mode 100644 packages/ntquerysysteminformation/example/ntdll/_winternl.h create mode 100644 packages/ntquerysysteminformation/example/ntdll/winternl.dart create mode 100644 packages/ntquerysysteminformation/example/ntdll/winternl.yaml create mode 100644 packages/ntquerysysteminformation/example/ntstatus/_ntstatus.h create mode 100644 packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart create mode 100644 packages/ntquerysysteminformation/example/ntstatus/ntstatus.yaml create mode 100644 packages/ntquerysysteminformation/lib/dynamic_load.dart create mode 100644 packages/ntquerysysteminformation/pubspec.lock create mode 100644 packages/ntquerysysteminformation/pubspec.yaml diff --git a/packages/ntquerysysteminformation/.gitignore b/packages/ntquerysysteminformation/.gitignore new file mode 100644 index 00000000..606b117e --- /dev/null +++ b/packages/ntquerysysteminformation/.gitignore @@ -0,0 +1,8 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build output. +build/ + +.vscode \ No newline at end of file diff --git a/packages/ntquerysysteminformation/CHANGELOG.md b/packages/ntquerysysteminformation/CHANGELOG.md new file mode 100644 index 00000000..effe43c8 --- /dev/null +++ b/packages/ntquerysysteminformation/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/packages/ntquerysysteminformation/README.md b/packages/ntquerysysteminformation/README.md new file mode 100644 index 00000000..a3075394 --- /dev/null +++ b/packages/ntquerysysteminformation/README.md @@ -0,0 +1 @@ +A simple command-line application. diff --git a/packages/ntquerysysteminformation/analysis_options.yaml b/packages/ntquerysysteminformation/analysis_options.yaml new file mode 100644 index 00000000..18b40b8d --- /dev/null +++ b/packages/ntquerysysteminformation/analysis_options.yaml @@ -0,0 +1,16 @@ +# Defines a default set of lint rules enforced for projects at Google. For +# details and rationale, see +# https://github.com/dart-lang/pedantic#enabled-lints. + +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. + +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/packages/ntquerysysteminformation/example/GetNativeSystemInfo.dart b/packages/ntquerysysteminformation/example/GetNativeSystemInfo.dart new file mode 100644 index 00000000..642021dc --- /dev/null +++ b/packages/ntquerysysteminformation/example/GetNativeSystemInfo.dart @@ -0,0 +1,66 @@ +import 'dart:ffi'; + +import 'package:dynamic_load/dynamic_load.dart'; +import 'package:ffi/ffi.dart'; +import 'package:win32/win32.dart'; + +final bool kIsX64 = sizeOf() == 8; + +// Inspired by https://github.com/timsneath/win32/blob/main/example/dynamic_load.dart +void main() { + using((Arena arena) { + final systemInfo = arena(); + final nativeSystemInfo = arena(); + + GetSystemInfo(systemInfo); + getNativeSystemInfo(nativeSystemInfo); + + if (kIsX64) { + assert(systemInfo.ref.wProcessorArchitecture == + nativeSystemInfo.ref.wProcessorArchitecture); + } else { + // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo + assert(systemInfo.ref.wProcessorArchitecture != + nativeSystemInfo.ref.wProcessorArchitecture); + } + + final archName = getArchitectureName(systemInfo.ref.wProcessorArchitecture); + final nativeArchName = + getArchitectureName(nativeSystemInfo.ref.wProcessorArchitecture); + print('archName $archName, nativeArchName $nativeArchName'); + }); +} + +typedef getNativeSystemInfoNative = Void Function( + Pointer lpSystemInfo); +typedef getNativeSystemInfoDart = void Function( + Pointer lpSystemInfo); + +void getNativeSystemInfo(Pointer lpSystemInfo) { + final pGetNativeSystemInfo = + getFuncAddress('kernel32.dll', 'GetNativeSystemInfo'); + + final funcGetNativeSystemInfo = + Pointer>.fromAddress( + pGetNativeSystemInfo) + .asFunction(); + + funcGetNativeSystemInfo(lpSystemInfo); +} + +String getArchitectureName(int wProcessorArchitecture) { + switch (wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + return 'PROCESSOR_ARCHITECTURE_INTEL'; + case PROCESSOR_ARCHITECTURE_ARM: + return 'PROCESSOR_ARCHITECTURE_ARM'; + case PROCESSOR_ARCHITECTURE_IA64: + return 'PROCESSOR_ARCHITECTURE_IA64'; + case PROCESSOR_ARCHITECTURE_AMD64: + return 'PROCESSOR_ARCHITECTURE_AMD64'; + case PROCESSOR_ARCHITECTURE_ARM64: + return 'PROCESSOR_ARCHITECTURE_ARM64'; + default: + throw Exception('Unknown architecture'); + } +} diff --git a/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart b/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart new file mode 100644 index 00000000..93f3582e --- /dev/null +++ b/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart @@ -0,0 +1,72 @@ +// ignore_for_file: omit_local_variable_types + +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import 'ntdll/winternl.dart'; +import 'ntstatus/ntstatus.dart'; + +/// +/// https://github.com/Sunbreak/dynamic_load.trial/tree/develop +/// + +void main() { + using((Arena arena) { + final pNeedSize = arena(); + var status = funcNtQuerySystemInformation( + SYSTEM_INFORMATION_CLASS.SystemProcessInformation, + nullptr, + 0, + pNeedSize); + if (status != STATUS_INFO_LENGTH_MISMATCH) throw Exception('Unknown'); + + final pBuffer = arena(pNeedSize.value); + status = funcNtQuerySystemInformation( + SYSTEM_INFORMATION_CLASS.SystemProcessInformation, + pBuffer.cast(), + pNeedSize.value, + nullptr); + if (status < 0) + throw Exception('Query SystemProcessInformation error: $status'); + + var address = pBuffer.address; + var nextEntryOffset = 0; + do { + address += nextEntryOffset; + final procRef = + Pointer.fromAddress(address).cast().ref; + // print('UniqueProcessId: ${procRef.UniqueProcessId.address}'); + final namePtr = procRef.ImageName.Buffer.cast(); + String name = ''; + if (namePtr != nullptr) { + final name = namePtr.toDartString(); + // print('Name: $name'); + } + // print('NumberOfThreads: ${procRef.NumberOfThreads}\n'); + if (procRef.UniqueProcessId.address == 18228) { + print('~~~~~~~~~~~~~~~~~~~~'); + print('This should be the Notepad process, with PID 18228.'); + print('Name: $name'); + print('UniqueProcessId: ${procRef.UniqueProcessId.address}'); + print('NumberOfThreads: ${procRef.NumberOfThreads}\n'); + for (var i = 0; i < (procRef.NumberOfThreads - 1); i++) { + /// TODO: If we could figure out how to get the [SYSTEM_THREAD_INFORMATION] + /// from the array following the [SYSTEM_PROCESS_INFORMATION], we'd + /// have everything necessary to do everything natively from dart. + /// Frustrating without proper docs, but maybe look into it more later. + /// Also, who knows if this would work on Windows 11? + + // final threadInfoAddress = + // procRef.NextEntryOffset + sizeOf(); + // final threadInfo = Pointer.fromAddress(threadInfoAddress) + // .cast() + // .ref; + // print(threadInfo); + } + print('~~~~~~~~~~~~~~~~~~~~'); + } + nextEntryOffset = procRef.NextEntryOffset; + } while (nextEntryOffset != 0); + }); +} diff --git a/packages/ntquerysysteminformation/example/ntdll/_winternl.dart b/packages/ntquerysysteminformation/example/ntdll/_winternl.dart new file mode 100644 index 00000000..dd2d86e3 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntdll/_winternl.dart @@ -0,0 +1,1386 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +import 'dart:ffi' as ffi; + +/// Bindings to `winternl.h`. +class winternl { + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + winternl(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup; + + /// The symbols are looked up with [lookup]. + winternl.fromLookup( + ffi.Pointer Function(String symbolName) + lookup) + : _lookup = lookup; + + int NtClose( + HANDLE Handle, + ) { + return _NtClose( + Handle, + ); + } + + late final _NtClosePtr = + _lookup>('NtClose'); + late final _NtClose = _NtClosePtr.asFunction(); + + int NtCreateFile( + PHANDLE FileHandle, + int DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + PLARGE_INTEGER AllocationSize, + int FileAttributes, + int ShareAccess, + int CreateDisposition, + int CreateOptions, + PVOID EaBuffer, + int EaLength, + ) { + return _NtCreateFile( + FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + AllocationSize, + FileAttributes, + ShareAccess, + CreateDisposition, + CreateOptions, + EaBuffer, + EaLength, + ); + } + + late final _NtCreateFilePtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + PHANDLE, + ACCESS_MASK, + POBJECT_ATTRIBUTES, + PIO_STATUS_BLOCK, + PLARGE_INTEGER, + ULONG, + ULONG, + ULONG, + ULONG, + PVOID, + ULONG)>>('NtCreateFile'); + late final _NtCreateFile = _NtCreateFilePtr.asFunction< + int Function(PHANDLE, int, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, + PLARGE_INTEGER, int, int, int, int, PVOID, int)>(); + + int NtOpenFile( + PHANDLE FileHandle, + int DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + int ShareAccess, + int OpenOptions, + ) { + return _NtOpenFile( + FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + ShareAccess, + OpenOptions, + ); + } + + late final _NtOpenFilePtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, + PIO_STATUS_BLOCK, ULONG, ULONG)>>('NtOpenFile'); + late final _NtOpenFile = _NtOpenFilePtr.asFunction< + int Function( + PHANDLE, int, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, int, int)>(); + + int NtRenameKey( + HANDLE KeyHandle, + PUNICODE_STRING NewName, + ) { + return _NtRenameKey( + KeyHandle, + NewName, + ); + } + + late final _NtRenameKeyPtr = + _lookup>( + 'NtRenameKey'); + late final _NtRenameKey = + _NtRenameKeyPtr.asFunction(); + + int NtNotifyChangeMultipleKeys( + HANDLE MasterKeyHandle, + int Count, + ffi.Pointer SubordinateObjects, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + int CompletionFilter, + int WatchTree, + PVOID Buffer, + int BufferSize, + int Asynchronous, + ) { + return _NtNotifyChangeMultipleKeys( + MasterKeyHandle, + Count, + SubordinateObjects, + Event, + ApcRoutine, + ApcContext, + IoStatusBlock, + CompletionFilter, + WatchTree, + Buffer, + BufferSize, + Asynchronous, + ); + } + + late final _NtNotifyChangeMultipleKeysPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + HANDLE, + ULONG, + ffi.Pointer, + HANDLE, + PIO_APC_ROUTINE, + PVOID, + PIO_STATUS_BLOCK, + ULONG, + BOOLEAN, + PVOID, + ULONG, + BOOLEAN)>>('NtNotifyChangeMultipleKeys'); + late final _NtNotifyChangeMultipleKeys = + _NtNotifyChangeMultipleKeysPtr.asFunction< + int Function( + HANDLE, + int, + ffi.Pointer, + HANDLE, + PIO_APC_ROUTINE, + PVOID, + PIO_STATUS_BLOCK, + int, + int, + PVOID, + int, + int)>(); + + int NtQueryMultipleValueKey( + HANDLE KeyHandle, + PKEY_VALUE_ENTRY ValueEntries, + int EntryCount, + PVOID ValueBuffer, + PULONG BufferLength, + PULONG RequiredBufferLength, + ) { + return _NtQueryMultipleValueKey( + KeyHandle, + ValueEntries, + EntryCount, + ValueBuffer, + BufferLength, + RequiredBufferLength, + ); + } + + late final _NtQueryMultipleValueKeyPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(HANDLE, PKEY_VALUE_ENTRY, ULONG, PVOID, PULONG, + PULONG)>>('NtQueryMultipleValueKey'); + late final _NtQueryMultipleValueKey = _NtQueryMultipleValueKeyPtr.asFunction< + int Function(HANDLE, PKEY_VALUE_ENTRY, int, PVOID, PULONG, PULONG)>(); + + int NtSetInformationKey( + HANDLE KeyHandle, + int KeySetInformationClass, + PVOID KeySetInformation, + int KeySetInformationLength, + ) { + return _NtSetInformationKey( + KeyHandle, + KeySetInformationClass, + KeySetInformation, + KeySetInformationLength, + ); + } + + late final _NtSetInformationKeyPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + HANDLE, ffi.Int32, PVOID, ULONG)>>('NtSetInformationKey'); + late final _NtSetInformationKey = _NtSetInformationKeyPtr.asFunction< + int Function(HANDLE, int, PVOID, int)>(); + + int NtDeviceIoControlFile( + HANDLE FileHandle, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + int IoControlCode, + PVOID InputBuffer, + int InputBufferLength, + PVOID OutputBuffer, + int OutputBufferLength, + ) { + return _NtDeviceIoControlFile( + FileHandle, + Event, + ApcRoutine, + ApcContext, + IoStatusBlock, + IoControlCode, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength, + ); + } + + late final _NtDeviceIoControlFilePtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + HANDLE, + HANDLE, + PIO_APC_ROUTINE, + PVOID, + PIO_STATUS_BLOCK, + ULONG, + PVOID, + ULONG, + PVOID, + ULONG)>>('NtDeviceIoControlFile'); + late final _NtDeviceIoControlFile = _NtDeviceIoControlFilePtr.asFunction< + int Function(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, + int, PVOID, int, PVOID, int)>(); + + int NtWaitForSingleObject( + HANDLE Handle, + int Alertable, + PLARGE_INTEGER Timeout, + ) { + return _NtWaitForSingleObject( + Handle, + Alertable, + Timeout, + ); + } + + late final _NtWaitForSingleObjectPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + HANDLE, BOOLEAN, PLARGE_INTEGER)>>('NtWaitForSingleObject'); + late final _NtWaitForSingleObject = _NtWaitForSingleObjectPtr.asFunction< + int Function(HANDLE, int, PLARGE_INTEGER)>(); + + int RtlIsNameLegalDOS8Dot3( + PUNICODE_STRING Name, + POEM_STRING OemName, + PBOOLEAN NameContainsSpaces, + ) { + return _RtlIsNameLegalDOS8Dot3( + Name, + OemName, + NameContainsSpaces, + ); + } + + late final _RtlIsNameLegalDOS8Dot3Ptr = _lookup< + ffi.NativeFunction< + BOOLEAN Function(PUNICODE_STRING, POEM_STRING, + PBOOLEAN)>>('RtlIsNameLegalDOS8Dot3'); + late final _RtlIsNameLegalDOS8Dot3 = _RtlIsNameLegalDOS8Dot3Ptr.asFunction< + int Function(PUNICODE_STRING, POEM_STRING, PBOOLEAN)>(); + + int RtlNtStatusToDosError( + int Status, + ) { + return _RtlNtStatusToDosError( + Status, + ); + } + + late final _RtlNtStatusToDosErrorPtr = + _lookup>( + 'RtlNtStatusToDosError'); + late final _RtlNtStatusToDosError = + _RtlNtStatusToDosErrorPtr.asFunction(); + + int NtQueryInformationProcess( + HANDLE ProcessHandle, + int ProcessInformationClass, + PVOID ProcessInformation, + int ProcessInformationLength, + PULONG ReturnLength, + ) { + return _NtQueryInformationProcess( + ProcessHandle, + ProcessInformationClass, + ProcessInformation, + ProcessInformationLength, + ReturnLength, + ); + } + + late final _NtQueryInformationProcessPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(HANDLE, ffi.Int32, PVOID, ULONG, + PULONG)>>('NtQueryInformationProcess'); + late final _NtQueryInformationProcess = _NtQueryInformationProcessPtr + .asFunction(); + + int NtQueryInformationThread( + HANDLE ThreadHandle, + int ThreadInformationClass, + PVOID ThreadInformation, + int ThreadInformationLength, + PULONG ReturnLength, + ) { + return _NtQueryInformationThread( + ThreadHandle, + ThreadInformationClass, + ThreadInformation, + ThreadInformationLength, + ReturnLength, + ); + } + + late final _NtQueryInformationThreadPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(HANDLE, ffi.Int32, PVOID, ULONG, + PULONG)>>('NtQueryInformationThread'); + late final _NtQueryInformationThread = _NtQueryInformationThreadPtr + .asFunction(); + + int NtQueryObject( + HANDLE Handle, + int ObjectInformationClass, + PVOID ObjectInformation, + int ObjectInformationLength, + PULONG ReturnLength, + ) { + return _NtQueryObject( + Handle, + ObjectInformationClass, + ObjectInformation, + ObjectInformationLength, + ReturnLength, + ); + } + + late final _NtQueryObjectPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + HANDLE, ffi.Int32, PVOID, ULONG, PULONG)>>('NtQueryObject'); + late final _NtQueryObject = _NtQueryObjectPtr.asFunction< + int Function(HANDLE, int, PVOID, int, PULONG)>(); + + int NtQuerySystemInformation( + int SystemInformationClass, + PVOID SystemInformation, + int SystemInformationLength, + PULONG ReturnLength, + ) { + return _NtQuerySystemInformation( + SystemInformationClass, + SystemInformation, + SystemInformationLength, + ReturnLength, + ); + } + + late final _NtQuerySystemInformationPtr = + _lookup>( + 'NtQuerySystemInformation'); + late final _NtQuerySystemInformation = + _NtQuerySystemInformationPtr.asFunction(); + + int NtQuerySystemTime( + PLARGE_INTEGER SystemTime, + ) { + return _NtQuerySystemTime( + SystemTime, + ); + } + + late final _NtQuerySystemTimePtr = + _lookup>( + 'NtQuerySystemTime'); + late final _NtQuerySystemTime = + _NtQuerySystemTimePtr.asFunction(); + + int RtlLocalTimeToSystemTime( + PLARGE_INTEGER LocalTime, + PLARGE_INTEGER SystemTime, + ) { + return _RtlLocalTimeToSystemTime( + LocalTime, + SystemTime, + ); + } + + late final _RtlLocalTimeToSystemTimePtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + PLARGE_INTEGER, PLARGE_INTEGER)>>('RtlLocalTimeToSystemTime'); + late final _RtlLocalTimeToSystemTime = _RtlLocalTimeToSystemTimePtr + .asFunction(); + + int RtlTimeToSecondsSince1970( + PLARGE_INTEGER Time, + PULONG ElapsedSeconds, + ) { + return _RtlTimeToSecondsSince1970( + Time, + ElapsedSeconds, + ); + } + + late final _RtlTimeToSecondsSince1970Ptr = + _lookup>( + 'RtlTimeToSecondsSince1970'); + late final _RtlTimeToSecondsSince1970 = _RtlTimeToSecondsSince1970Ptr + .asFunction(); + + void RtlFreeAnsiString( + PANSI_STRING AnsiString, + ) { + return _RtlFreeAnsiString( + AnsiString, + ); + } + + late final _RtlFreeAnsiStringPtr = + _lookup>( + 'RtlFreeAnsiString'); + late final _RtlFreeAnsiString = + _RtlFreeAnsiStringPtr.asFunction(); + + void RtlFreeUnicodeString( + PUNICODE_STRING UnicodeString, + ) { + return _RtlFreeUnicodeString( + UnicodeString, + ); + } + + late final _RtlFreeUnicodeStringPtr = + _lookup>( + 'RtlFreeUnicodeString'); + late final _RtlFreeUnicodeString = + _RtlFreeUnicodeStringPtr.asFunction(); + + void RtlFreeOemString( + POEM_STRING OemString, + ) { + return _RtlFreeOemString( + OemString, + ); + } + + late final _RtlFreeOemStringPtr = + _lookup>( + 'RtlFreeOemString'); + late final _RtlFreeOemString = + _RtlFreeOemStringPtr.asFunction(); + + void RtlInitString( + PSTRING DestinationString, + PCSZ SourceString, + ) { + return _RtlInitString( + DestinationString, + SourceString, + ); + } + + late final _RtlInitStringPtr = + _lookup>( + 'RtlInitString'); + late final _RtlInitString = + _RtlInitStringPtr.asFunction(); + + int RtlInitStringEx( + PSTRING DestinationString, + PCSZ SourceString, + ) { + return _RtlInitStringEx( + DestinationString, + SourceString, + ); + } + + late final _RtlInitStringExPtr = + _lookup>( + 'RtlInitStringEx'); + late final _RtlInitStringEx = + _RtlInitStringExPtr.asFunction(); + + void RtlInitAnsiString( + PANSI_STRING DestinationString, + PCSZ SourceString, + ) { + return _RtlInitAnsiString( + DestinationString, + SourceString, + ); + } + + late final _RtlInitAnsiStringPtr = + _lookup>( + 'RtlInitAnsiString'); + late final _RtlInitAnsiString = + _RtlInitAnsiStringPtr.asFunction(); + + int RtlInitAnsiStringEx( + PANSI_STRING DestinationString, + PCSZ SourceString, + ) { + return _RtlInitAnsiStringEx( + DestinationString, + SourceString, + ); + } + + late final _RtlInitAnsiStringExPtr = + _lookup>( + 'RtlInitAnsiStringEx'); + late final _RtlInitAnsiStringEx = + _RtlInitAnsiStringExPtr.asFunction(); + + void RtlInitUnicodeString( + PUNICODE_STRING DestinationString, + PCWSTR SourceString, + ) { + return _RtlInitUnicodeString( + DestinationString, + SourceString, + ); + } + + late final _RtlInitUnicodeStringPtr = + _lookup>( + 'RtlInitUnicodeString'); + late final _RtlInitUnicodeString = _RtlInitUnicodeStringPtr.asFunction< + void Function(PUNICODE_STRING, PCWSTR)>(); + + int RtlAnsiStringToUnicodeString( + PUNICODE_STRING DestinationString, + PCANSI_STRING SourceString, + int AllocateDestinationString, + ) { + return _RtlAnsiStringToUnicodeString( + DestinationString, + SourceString, + AllocateDestinationString, + ); + } + + late final _RtlAnsiStringToUnicodeStringPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(PUNICODE_STRING, PCANSI_STRING, + BOOLEAN)>>('RtlAnsiStringToUnicodeString'); + late final _RtlAnsiStringToUnicodeString = _RtlAnsiStringToUnicodeStringPtr + .asFunction(); + + int RtlUnicodeStringToAnsiString( + PANSI_STRING DestinationString, + PCUNICODE_STRING SourceString, + int AllocateDestinationString, + ) { + return _RtlUnicodeStringToAnsiString( + DestinationString, + SourceString, + AllocateDestinationString, + ); + } + + late final _RtlUnicodeStringToAnsiStringPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(PANSI_STRING, PCUNICODE_STRING, + BOOLEAN)>>('RtlUnicodeStringToAnsiString'); + late final _RtlUnicodeStringToAnsiString = _RtlUnicodeStringToAnsiStringPtr + .asFunction(); + + int RtlUnicodeStringToOemString( + POEM_STRING DestinationString, + PCUNICODE_STRING SourceString, + int AllocateDestinationString, + ) { + return _RtlUnicodeStringToOemString( + DestinationString, + SourceString, + AllocateDestinationString, + ); + } + + late final _RtlUnicodeStringToOemStringPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function(POEM_STRING, PCUNICODE_STRING, + BOOLEAN)>>('RtlUnicodeStringToOemString'); + late final _RtlUnicodeStringToOemString = _RtlUnicodeStringToOemStringPtr + .asFunction(); + + int RtlUnicodeToMultiByteSize( + PULONG BytesInMultiByteString, + PWCH UnicodeString, + int BytesInUnicodeString, + ) { + return _RtlUnicodeToMultiByteSize( + BytesInMultiByteString, + UnicodeString, + BytesInUnicodeString, + ); + } + + late final _RtlUnicodeToMultiByteSizePtr = + _lookup>( + 'RtlUnicodeToMultiByteSize'); + late final _RtlUnicodeToMultiByteSize = _RtlUnicodeToMultiByteSizePtr + .asFunction(); + + int RtlCharToInteger( + PCSZ String, + int Base, + PULONG Value, + ) { + return _RtlCharToInteger( + String, + Base, + Value, + ); + } + + late final _RtlCharToIntegerPtr = + _lookup>( + 'RtlCharToInteger'); + late final _RtlCharToInteger = + _RtlCharToIntegerPtr.asFunction(); + + int RtlConvertSidToUnicodeString( + PUNICODE_STRING UnicodeString, + PSID Sid, + int AllocateDestinationString, + ) { + return _RtlConvertSidToUnicodeString( + UnicodeString, + Sid, + AllocateDestinationString, + ); + } + + late final _RtlConvertSidToUnicodeStringPtr = _lookup< + ffi.NativeFunction< + NTSTATUS Function( + PUNICODE_STRING, PSID, BOOLEAN)>>('RtlConvertSidToUnicodeString'); + late final _RtlConvertSidToUnicodeString = _RtlConvertSidToUnicodeStringPtr + .asFunction(); + + int RtlUniform( + PULONG Seed, + ) { + return _RtlUniform( + Seed, + ); + } + + late final _RtlUniformPtr = + _lookup>('RtlUniform'); + late final _RtlUniform = _RtlUniformPtr.asFunction(); +} + +class _STRING extends ffi.Struct { + @USHORT() + external int Length; + + @USHORT() + external int MaximumLength; + + external PCHAR Buffer; +} + +typedef USHORT = ffi.Uint16; +typedef PCHAR = ffi.Pointer; +typedef CHAR = ffi.Int8; + +class _UNICODE_STRING extends ffi.Struct { + @USHORT() + external int Length; + + @USHORT() + external int MaximumLength; + + external PWSTR Buffer; +} + +typedef PWSTR = ffi.Pointer; +typedef WCHAR = wchar_t; +typedef wchar_t = ffi.Uint16; + +class _CLIENT_ID extends ffi.Struct { + external HANDLE UniqueProcess; + + external HANDLE UniqueThread; +} + +typedef HANDLE = ffi.Pointer; + +class _PEB_LDR_DATA extends ffi.Struct { + @ffi.Array.multi([8]) + external ffi.Array Reserved1; + + @ffi.Array.multi([3]) + external ffi.Array Reserved2; + + external LIST_ENTRY InMemoryOrderModuleList; +} + +typedef BYTE = ffi.Uint8; +typedef PVOID = ffi.Pointer; +typedef LIST_ENTRY = _LIST_ENTRY; + +class _LIST_ENTRY extends ffi.Struct { + external ffi.Pointer<_LIST_ENTRY> Flink; + + external ffi.Pointer<_LIST_ENTRY> Blink; +} + +class _LDR_DATA_TABLE_ENTRY extends ffi.Struct { + @ffi.Array.multi([2]) + external ffi.Array Reserved1; + + external LIST_ENTRY InMemoryOrderLinks; + + @ffi.Array.multi([2]) + external ffi.Array Reserved2; + + external PVOID DllBase; + + @ffi.Array.multi([2]) + external ffi.Array Reserved3; + + external UNICODE_STRING FullDllName; + + @ffi.Array.multi([8]) + external ffi.Array Reserved4; + + @ffi.Array.multi([3]) + external ffi.Array Reserved5; + + @ULONG() + external int TimeDateStamp; +} + +typedef UNICODE_STRING = _UNICODE_STRING; +typedef ULONG = DWORD; +typedef DWORD = ffi.Uint32; + +class _RTL_USER_PROCESS_PARAMETERS extends ffi.Struct { + @ffi.Array.multi([16]) + external ffi.Array Reserved1; + + @ffi.Array.multi([10]) + external ffi.Array Reserved2; + + external UNICODE_STRING ImagePathName; + + external UNICODE_STRING CommandLine; +} + +class _PEB extends ffi.Struct { + @ffi.Array.multi([2]) + external ffi.Array Reserved1; + + @BYTE() + external int BeingDebugged; + + @ffi.Array.multi([1]) + external ffi.Array Reserved2; + + @ffi.Array.multi([2]) + external ffi.Array Reserved3; + + external PPEB_LDR_DATA Ldr; + + external PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + + @ffi.Array.multi([3]) + external ffi.Array Reserved4; + + external PVOID AtlThunkSListPtr; + + external PVOID Reserved5; + + @ULONG() + external int Reserved6; + + external PVOID Reserved7; + + @ULONG() + external int Reserved8; + + @ULONG() + external int AtlThunkSListPtr32; + + @ffi.Array.multi([45]) + external ffi.Array Reserved9; + + @ffi.Array.multi([96]) + external ffi.Array Reserved10; + + external PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; + + @ffi.Array.multi([128]) + external ffi.Array Reserved11; + + @ffi.Array.multi([1]) + external ffi.Array Reserved12; + + @ULONG() + external int SessionId; +} + +typedef PPEB_LDR_DATA = ffi.Pointer<_PEB_LDR_DATA>; +typedef PRTL_USER_PROCESS_PARAMETERS + = ffi.Pointer<_RTL_USER_PROCESS_PARAMETERS>; +typedef PPS_POST_PROCESS_INIT_ROUTINE + = ffi.Pointer>; + +class _TEB extends ffi.Struct { + @ffi.Array.multi([12]) + external ffi.Array Reserved1; + + external PPEB ProcessEnvironmentBlock; + + @ffi.Array.multi([399]) + external ffi.Array Reserved2; + + @ffi.Array.multi([1952]) + external ffi.Array Reserved3; + + @ffi.Array.multi([64]) + external ffi.Array TlsSlots; + + @ffi.Array.multi([8]) + external ffi.Array Reserved4; + + @ffi.Array.multi([26]) + external ffi.Array Reserved5; + + external PVOID ReservedForOle; + + @ffi.Array.multi([4]) + external ffi.Array Reserved6; + + external PVOID TlsExpansionSlots; +} + +typedef PPEB = ffi.Pointer<_PEB>; + +class _OBJECT_ATTRIBUTES extends ffi.Struct { + @ULONG() + external int Length; + + external HANDLE RootDirectory; + + external PUNICODE_STRING ObjectName; + + @ULONG() + external int Attributes; + + external PVOID SecurityDescriptor; + + external PVOID SecurityQualityOfService; +} + +typedef PUNICODE_STRING = ffi.Pointer; + +class _IO_STATUS_BLOCK extends ffi.Struct { + @ULONG_PTR() + external int Information; +} + +typedef ULONG_PTR = ffi.Uint64; + +class _PROCESS_BASIC_INFORMATION extends ffi.Struct { + external PVOID Reserved1; + + external PPEB PebBaseAddress; + + @ffi.Array.multi([2]) + external ffi.Array Reserved2; + + @ULONG_PTR() + external int UniqueProcessId; + + external PVOID Reserved3; +} + +class SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION extends ffi.Struct { + external LARGE_INTEGER IdleTime; + + external LARGE_INTEGER KernelTime; + + external LARGE_INTEGER UserTime; + + @ffi.Array.multi([2]) + external ffi.Array Reserved1; + + @ULONG() + external int Reserved2; +} + +typedef LARGE_INTEGER = _LARGE_INTEGER; + +class _LARGE_INTEGER extends ffi.Union { + external UnnamedStruct1 u; + + @LONGLONG() + external int QuadPart; +} + +class UnnamedStruct1 extends ffi.Struct { + @DWORD() + external int LowPart; + + @LONG() + external int HighPart; +} + +typedef LONG = ffi.Int32; +typedef LONGLONG = ffi.Int64; + +class SYSTEM_PROCESS_INFORMATION extends ffi.Struct { + @ULONG() + external int NextEntryOffset; + + @ULONG() + external int NumberOfThreads; + + @ffi.Array.multi([48]) + external ffi.Array Reserved1; + + external UNICODE_STRING ImageName; + + @KPRIORITY() + external int BasePriority; + + external HANDLE UniqueProcessId; + + external PVOID Reserved2; + + @ULONG() + external int HandleCount; + + @ULONG() + external int SessionId; + + external PVOID Reserved3; + + @SIZE_T() + external int PeakVirtualSize; + + @SIZE_T() + external int VirtualSize; + + @ULONG() + external int Reserved4; + + @SIZE_T() + external int PeakWorkingSetSize; + + @SIZE_T() + external int WorkingSetSize; + + external PVOID Reserved5; + + @SIZE_T() + external int QuotaPagedPoolUsage; + + external PVOID Reserved6; + + @SIZE_T() + external int QuotaNonPagedPoolUsage; + + @SIZE_T() + external int PagefileUsage; + + @SIZE_T() + external int PeakPagefileUsage; + + @SIZE_T() + external int PrivatePageCount; + + @ffi.Array.multi([6]) + external ffi.Array Reserved7; +} + +typedef KPRIORITY = LONG; +typedef SIZE_T = ULONG_PTR; + +class SYSTEM_THREAD_INFORMATION extends ffi.Struct { + @ffi.Array.multi([3]) + external ffi.Array Reserved1; + + @ULONG() + external int Reserved2; + + external PVOID StartAddress; + + external CLIENT_ID ClientId; + + @KPRIORITY() + external int Priority; + + @LONG() + external int BasePriority; + + @ULONG() + external int Reserved3; + + @ULONG() + external int ThreadState; + + @ULONG() + external int WaitReason; +} + +typedef CLIENT_ID = _CLIENT_ID; + +class SYSTEM_REGISTRY_QUOTA_INFORMATION extends ffi.Struct { + @ULONG() + external int RegistryQuotaAllowed; + + @ULONG() + external int RegistryQuotaUsed; + + external PVOID Reserved1; +} + +class SYSTEM_BASIC_INFORMATION extends ffi.Struct { + @ffi.Array.multi([24]) + external ffi.Array Reserved1; + + @ffi.Array.multi([4]) + external ffi.Array Reserved2; + + @CCHAR() + external int NumberOfProcessors; +} + +typedef CCHAR = ffi.Int8; + +class SYSTEM_TIMEOFDAY_INFORMATION extends ffi.Struct { + @ffi.Array.multi([48]) + external ffi.Array Reserved1; +} + +class SYSTEM_PERFORMANCE_INFORMATION extends ffi.Struct { + @ffi.Array.multi([312]) + external ffi.Array Reserved1; +} + +class SYSTEM_EXCEPTION_INFORMATION extends ffi.Struct { + @ffi.Array.multi([16]) + external ffi.Array Reserved1; +} + +class SYSTEM_LOOKASIDE_INFORMATION extends ffi.Struct { + @ffi.Array.multi([32]) + external ffi.Array Reserved1; +} + +class SYSTEM_INTERRUPT_INFORMATION extends ffi.Struct { + @ffi.Array.multi([24]) + external ffi.Array Reserved1; +} + +class SYSTEM_POLICY_INFORMATION extends ffi.Struct { + @ffi.Array.multi([2]) + external ffi.Array Reserved1; + + @ffi.Array.multi([3]) + external ffi.Array Reserved2; +} + +abstract class _FILE_INFORMATION_CLASS { + static const int FileDirectoryInformation = 1; +} + +abstract class _PROCESSINFOCLASS { + static const int ProcessBasicInformation = 0; + static const int ProcessDebugPort = 7; + static const int ProcessWow64Information = 26; + static const int ProcessImageFileName = 27; + static const int ProcessBreakOnTermination = 29; +} + +abstract class _THREADINFOCLASS { + static const int ThreadIsIoPending = 16; +} + +class SYSTEM_CODEINTEGRITY_INFORMATION extends ffi.Struct { + @ULONG() + external int Length; + + @ULONG() + external int CodeIntegrityOptions; +} + +abstract class SYSTEM_INFORMATION_CLASS { + static const int SystemBasicInformation = 0; + static const int SystemPerformanceInformation = 2; + static const int SystemTimeOfDayInformation = 3; + static const int SystemProcessInformation = 5; + static const int SystemProcessorPerformanceInformation = 8; + static const int SystemInterruptInformation = 23; + static const int SystemExceptionInformation = 33; + static const int SystemRegistryQuotaInformation = 37; + static const int SystemLookasideInformation = 45; + static const int SystemCodeIntegrityInformation = 103; + static const int SystemPolicyInformation = 134; +} + +abstract class _OBJECT_INFORMATION_CLASS { + static const int ObjectBasicInformation = 0; + static const int ObjectTypeInformation = 2; +} + +class _PUBLIC_OBJECT_BASIC_INFORMATION extends ffi.Struct { + @ULONG() + external int Attributes; + + @ACCESS_MASK() + external int GrantedAccess; + + @ULONG() + external int HandleCount; + + @ULONG() + external int PointerCount; + + @ffi.Array.multi([10]) + external ffi.Array Reserved; +} + +typedef ACCESS_MASK = DWORD; + +class __PUBLIC_OBJECT_TYPE_INFORMATION extends ffi.Struct { + external UNICODE_STRING TypeName; + + @ffi.Array.multi([22]) + external ffi.Array Reserved; +} + +typedef NTSTATUS = LONG; +typedef PHANDLE = ffi.Pointer; +typedef POBJECT_ATTRIBUTES = ffi.Pointer; +typedef OBJECT_ATTRIBUTES = _OBJECT_ATTRIBUTES; +typedef PIO_STATUS_BLOCK = ffi.Pointer<_IO_STATUS_BLOCK>; +typedef PLARGE_INTEGER = ffi.Pointer; +typedef PIO_APC_ROUTINE = ffi.Pointer< + ffi.NativeFunction>; +typedef BOOLEAN = boolean; +typedef boolean = ffi.Uint8; + +class _KEY_VALUE_ENTRY extends ffi.Struct { + external PUNICODE_STRING ValueName; + + @ULONG() + external int DataLength; + + @ULONG() + external int DataOffset; + + @ULONG() + external int Type; +} + +typedef PKEY_VALUE_ENTRY = ffi.Pointer<_KEY_VALUE_ENTRY>; +typedef PULONG = ffi.Pointer; + +abstract class _KEY_SET_INFORMATION_CLASS { + static const int KeyWriteTimeInformation = 0; + static const int KeyWow64FlagsInformation = 1; + static const int KeyControlFlagsInformation = 2; + static const int KeySetVirtualizationInformation = 3; + static const int KeySetDebugInformation = 4; + static const int KeySetHandleTagsInformation = 5; + static const int MaxKeySetInfoClass = 6; +} + +typedef POEM_STRING = PSTRING; +typedef PSTRING = ffi.Pointer; +typedef STRING = _STRING; +typedef PBOOLEAN = ffi.Pointer; +typedef NativeNtQuerySystemInformation = NTSTATUS Function( + ffi.Int32 SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength); +typedef DartNtQuerySystemInformation = int Function(int SystemInformationClass, + PVOID SystemInformation, int SystemInformationLength, PULONG ReturnLength); +typedef PANSI_STRING = PSTRING; +typedef PCSZ = ffi.Pointer; +typedef PCWSTR = ffi.Pointer; +typedef PCANSI_STRING = PSTRING; +typedef PCUNICODE_STRING = ffi.Pointer; +typedef PWCH = ffi.Pointer; +typedef PSID = PVOID; + +abstract class _WINSTATIONINFOCLASS { + static const int WinStationInformation = 8; +} + +class _WINSTATIONINFORMATIONW extends ffi.Struct { + @ffi.Array.multi([70]) + external ffi.Array Reserved2; + + @ULONG() + external int LogonId; + + @ffi.Array.multi([1140]) + external ffi.Array Reserved3; +} + +const int CODEINTEGRITY_OPTION_ENABLED = 1; + +const int CODEINTEGRITY_OPTION_TESTSIGN = 2; + +const int CODEINTEGRITY_OPTION_UMCI_ENABLED = 4; + +const int CODEINTEGRITY_OPTION_UMCI_AUDITMODE_ENABLED = 8; + +const int CODEINTEGRITY_OPTION_UMCI_EXCLUSIONPATHS_ENABLED = 16; + +const int CODEINTEGRITY_OPTION_TEST_BUILD = 32; + +const int CODEINTEGRITY_OPTION_PREPRODUCTION_BUILD = 64; + +const int CODEINTEGRITY_OPTION_DEBUGMODE_ENABLED = 128; + +const int CODEINTEGRITY_OPTION_FLIGHT_BUILD = 256; + +const int CODEINTEGRITY_OPTION_FLIGHTING_ENABLED = 512; + +const int CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED = 1024; + +const int CODEINTEGRITY_OPTION_HVCI_KMCI_AUDITMODE_ENABLED = 2048; + +const int CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED = 4096; + +const int CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED = 8192; + +const int LOGONID_CURRENT = 4294967295; + +const int OBJ_INHERIT = 2; + +const int OBJ_PERMANENT = 16; + +const int OBJ_EXCLUSIVE = 32; + +const int OBJ_CASE_INSENSITIVE = 64; + +const int OBJ_OPENIF = 128; + +const int OBJ_OPENLINK = 256; + +const int OBJ_KERNEL_HANDLE = 512; + +const int OBJ_FORCE_ACCESS_CHECK = 1024; + +const int OBJ_IGNORE_IMPERSONATED_DEVICEMAP = 2048; + +const int OBJ_DONT_REPARSE = 4096; + +const int OBJ_VALID_ATTRIBUTES = 8178; + +const int FILE_SUPERSEDE = 0; + +const int FILE_OPEN = 1; + +const int FILE_CREATE = 2; + +const int FILE_OPEN_IF = 3; + +const int FILE_OVERWRITE = 4; + +const int FILE_OVERWRITE_IF = 5; + +const int FILE_MAXIMUM_DISPOSITION = 5; + +const int FILE_DIRECTORY_FILE = 1; + +const int FILE_WRITE_THROUGH = 2; + +const int FILE_SEQUENTIAL_ONLY = 4; + +const int FILE_NO_INTERMEDIATE_BUFFERING = 8; + +const int FILE_SYNCHRONOUS_IO_ALERT = 16; + +const int FILE_SYNCHRONOUS_IO_NONALERT = 32; + +const int FILE_NON_DIRECTORY_FILE = 64; + +const int FILE_CREATE_TREE_CONNECTION = 128; + +const int FILE_COMPLETE_IF_OPLOCKED = 256; + +const int FILE_NO_EA_KNOWLEDGE = 512; + +const int FILE_OPEN_REMOTE_INSTANCE = 1024; + +const int FILE_RANDOM_ACCESS = 2048; + +const int FILE_DELETE_ON_CLOSE = 4096; + +const int FILE_OPEN_BY_FILE_ID = 8192; + +const int FILE_OPEN_FOR_BACKUP_INTENT = 16384; + +const int FILE_NO_COMPRESSION = 32768; + +const int FILE_OPEN_REQUIRING_OPLOCK = 65536; + +const int FILE_RESERVE_OPFILTER = 1048576; + +const int FILE_OPEN_REPARSE_POINT = 2097152; + +const int FILE_OPEN_NO_RECALL = 4194304; + +const int FILE_OPEN_FOR_FREE_SPACE_QUERY = 8388608; + +const int FILE_VALID_OPTION_FLAGS = 16777215; + +const int FILE_VALID_PIPE_OPTION_FLAGS = 50; + +const int FILE_VALID_MAILSLOT_OPTION_FLAGS = 50; + +const int FILE_VALID_SET_FLAGS = 54; + +const int FILE_SUPERSEDED = 0; + +const int FILE_OPENED = 1; + +const int FILE_CREATED = 2; + +const int FILE_OVERWRITTEN = 3; + +const int FILE_EXISTS = 4; + +const int FILE_DOES_NOT_EXIST = 5; diff --git a/packages/ntquerysysteminformation/example/ntdll/_winternl.h b/packages/ntquerysysteminformation/example/ntdll/_winternl.h new file mode 100644 index 00000000..12864b21 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntdll/_winternl.h @@ -0,0 +1,3 @@ +// Dummy header to include the real one +#include +#include \ No newline at end of file diff --git a/packages/ntquerysysteminformation/example/ntdll/winternl.dart b/packages/ntquerysysteminformation/example/ntdll/winternl.dart new file mode 100644 index 00000000..9db815c0 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntdll/winternl.dart @@ -0,0 +1,18 @@ +import 'dart:ffi' as ffi; + +import 'package:dynamic_load/dynamic_load.dart'; +import 'package:ffi/ffi.dart'; + +import '_winternl.dart'; + +export '_winternl.dart'; + +final funcNtQuerySystemInformation = using((Arena arena) { + final pNtQuerySystemInformation = + getFuncAddress('ntdll.dll', 'NtQuerySystemInformation'); + + return ffi.Pointer< + ffi.NativeFunction>.fromAddress( + pNtQuerySystemInformation) + .asFunction(); +}); diff --git a/packages/ntquerysysteminformation/example/ntdll/winternl.yaml b/packages/ntquerysysteminformation/example/ntdll/winternl.yaml new file mode 100644 index 00000000..cc238f31 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntdll/winternl.yaml @@ -0,0 +1,21 @@ +name: winternl +description: Bindings to `winternl.h`. +output: 'example/ntdll/_winternl.dart' +headers: + entry-points: + - 'example/ntdll/_winternl.h' + include-directives: # include only these header files and necessary structs from other header files + - '**winternl.h' +functions: + expose-typedefs: + include: + - 'NtQuerySystemInformation' +structs: + rename: + '_SYSTEM_(.*)': 'SYSTEM_$1' # FIXME: https://github.com/dart-lang/ffigen/issues/233 +enums: + rename: + '_SYSTEM_(.*)': 'SYSTEM_$1' # FIXME: https://github.com/dart-lang/ffigen/issues/233 +size-map: + long: 4 + unsigned long: 4 \ No newline at end of file diff --git a/packages/ntquerysysteminformation/example/ntstatus/_ntstatus.h b/packages/ntquerysysteminformation/example/ntstatus/_ntstatus.h new file mode 100644 index 00000000..ef739413 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntstatus/_ntstatus.h @@ -0,0 +1,3 @@ +// Dummy header to include the real one +#include +#include \ No newline at end of file diff --git a/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart new file mode 100644 index 00000000..b833efd1 --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart @@ -0,0 +1,5532 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +import 'dart:ffi' as ffi; + +const int STATUS_WAIT_0 = 0; + +const int FACILITY_DEBUGGER = 1; + +const int FACILITY_RPC_RUNTIME = 2; + +const int FACILITY_RPC_STUBS = 3; + +const int FACILITY_IO_ERROR_CODE = 4; + +const int FACILITY_CODCLASS_ERROR_CODE = 6; + +const int FACILITY_NTWIN32 = 7; + +const int FACILITY_NTCERT = 8; + +const int FACILITY_NTSSPI = 9; + +const int FACILITY_TERMINAL_SERVER = 10; + +const int FACILTIY_MUI_ERROR_CODE = 11; + +const int FACILITY_USB_ERROR_CODE = 16; + +const int FACILITY_HID_ERROR_CODE = 17; + +const int FACILITY_FIREWIRE_ERROR_CODE = 18; + +const int FACILITY_CLUSTER_ERROR_CODE = 19; + +const int FACILITY_ACPI_ERROR_CODE = 20; + +const int FACILITY_SXS_ERROR_CODE = 21; + +const int FACILITY_TRANSACTION = 25; + +const int FACILITY_COMMONLOG = 26; + +const int FACILITY_VIDEO = 27; + +const int FACILITY_FILTER_MANAGER = 28; + +const int FACILITY_MONITOR = 29; + +const int FACILITY_GRAPHICS_KERNEL = 30; + +const int FACILITY_DRIVER_FRAMEWORK = 32; + +const int FACILITY_FVE_ERROR_CODE = 33; + +const int FACILITY_FWP_ERROR_CODE = 34; + +const int FACILITY_NDIS_ERROR_CODE = 35; + +const int FACILITY_TPM = 41; + +const int FACILITY_RTPM = 42; + +const int FACILITY_HYPERVISOR = 53; + +const int FACILITY_IPSEC = 54; + +const int FACILITY_VIRTUALIZATION = 55; + +const int FACILITY_VOLMGR = 56; + +const int FACILITY_BCD_ERROR_CODE = 57; + +const int FACILITY_WIN32K_NTUSER = 62; + +const int FACILITY_WIN32K_NTGDI = 63; + +const int FACILITY_RESUME_KEY_FILTER = 64; + +const int FACILITY_RDBSS = 65; + +const int FACILITY_BTH_ATT = 66; + +const int FACILITY_SECUREBOOT = 67; + +const int FACILITY_AUDIO_KERNEL = 68; + +const int FACILITY_VSM = 69; + +const int FACILITY_VOLSNAP = 80; + +const int FACILITY_SDBUS = 81; + +const int FACILITY_SHARED_VHDX = 92; + +const int FACILITY_SMB = 93; + +const int FACILITY_XVS = 94; + +const int FACILITY_INTERIX = 153; + +const int FACILITY_SPACES = 231; + +const int FACILITY_SECURITY_CORE = 232; + +const int FACILITY_SYSTEM_INTEGRITY = 233; + +const int FACILITY_LICENSING = 234; + +const int FACILITY_PLATFORM_MANIFEST = 235; + +const int FACILITY_APP_EXEC = 236; + +const int FACILITY_MAXIMUM_VALUE = 237; + +const int STATUS_SEVERITY_SUCCESS = 0; + +const int STATUS_SEVERITY_INFORMATIONAL = 1; + +const int STATUS_SEVERITY_WARNING = 2; + +const int STATUS_SEVERITY_ERROR = 3; + +const int STATUS_SUCCESS = 0; + +const int STATUS_WAIT_1 = 1; + +const int STATUS_WAIT_2 = 2; + +const int STATUS_WAIT_3 = 3; + +const int STATUS_WAIT_63 = 63; + +const int STATUS_ABANDONED = 128; + +const int STATUS_ABANDONED_WAIT_0 = 128; + +const int STATUS_ABANDONED_WAIT_63 = 191; + +const int STATUS_USER_APC = 192; + +const int STATUS_ALREADY_COMPLETE = 255; + +const int STATUS_KERNEL_APC = 256; + +const int STATUS_ALERTED = 257; + +const int STATUS_TIMEOUT = 258; + +const int STATUS_PENDING = 259; + +const int STATUS_REPARSE = 260; + +const int STATUS_MORE_ENTRIES = 261; + +const int STATUS_NOT_ALL_ASSIGNED = 262; + +const int STATUS_SOME_NOT_MAPPED = 263; + +const int STATUS_OPLOCK_BREAK_IN_PROGRESS = 264; + +const int STATUS_VOLUME_MOUNTED = 265; + +const int STATUS_RXACT_COMMITTED = 266; + +const int STATUS_NOTIFY_CLEANUP = 267; + +const int STATUS_NOTIFY_ENUM_DIR = 268; + +const int STATUS_NO_QUOTAS_FOR_ACCOUNT = 269; + +const int STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED = 270; + +const int STATUS_PAGE_FAULT_TRANSITION = 272; + +const int STATUS_PAGE_FAULT_DEMAND_ZERO = 273; + +const int STATUS_PAGE_FAULT_COPY_ON_WRITE = 274; + +const int STATUS_PAGE_FAULT_GUARD_PAGE = 275; + +const int STATUS_PAGE_FAULT_PAGING_FILE = 276; + +const int STATUS_CACHE_PAGE_LOCKED = 277; + +const int STATUS_CRASH_DUMP = 278; + +const int STATUS_BUFFER_ALL_ZEROS = 279; + +const int STATUS_REPARSE_OBJECT = 280; + +const int STATUS_RESOURCE_REQUIREMENTS_CHANGED = 281; + +const int STATUS_TRANSLATION_COMPLETE = 288; + +const int STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY = 289; + +const int STATUS_NOTHING_TO_TERMINATE = 290; + +const int STATUS_PROCESS_NOT_IN_JOB = 291; + +const int STATUS_PROCESS_IN_JOB = 292; + +const int STATUS_VOLSNAP_HIBERNATE_READY = 293; + +const int STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 294; + +const int STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED = 295; + +const int STATUS_INTERRUPT_STILL_CONNECTED = 296; + +const int STATUS_PROCESS_CLONED = 297; + +const int STATUS_FILE_LOCKED_WITH_ONLY_READERS = 298; + +const int STATUS_FILE_LOCKED_WITH_WRITERS = 299; + +const int STATUS_VALID_IMAGE_HASH = 300; + +const int STATUS_VALID_CATALOG_HASH = 301; + +const int STATUS_VALID_STRONG_CODE_HASH = 302; + +const int STATUS_GHOSTED = 303; + +const int STATUS_DATA_OVERWRITTEN = 304; + +const int STATUS_RESOURCEMANAGER_READ_ONLY = 514; + +const int STATUS_RING_PREVIOUSLY_EMPTY = 528; + +const int STATUS_RING_PREVIOUSLY_FULL = 529; + +const int STATUS_RING_PREVIOUSLY_ABOVE_QUOTA = 530; + +const int STATUS_RING_NEWLY_EMPTY = 531; + +const int STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT = 532; + +const int STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE = 533; + +const int STATUS_OPLOCK_HANDLE_CLOSED = 534; + +const int STATUS_WAIT_FOR_OPLOCK = 871; + +const int STATUS_REPARSE_GLOBAL = 872; + +const int DBG_EXCEPTION_HANDLED = 65537; + +const int DBG_CONTINUE = 65538; + +const int STATUS_FLT_IO_COMPLETE = 1835009; + +const int STATUS_OBJECT_NAME_EXISTS = 1073741824; + +const int STATUS_THREAD_WAS_SUSPENDED = 1073741825; + +const int STATUS_WORKING_SET_LIMIT_RANGE = 1073741826; + +const int STATUS_IMAGE_NOT_AT_BASE = 1073741827; + +const int STATUS_RXACT_STATE_CREATED = 1073741828; + +const int STATUS_SEGMENT_NOTIFICATION = 1073741829; + +const int STATUS_LOCAL_USER_SESSION_KEY = 1073741830; + +const int STATUS_BAD_CURRENT_DIRECTORY = 1073741831; + +const int STATUS_SERIAL_MORE_WRITES = 1073741832; + +const int STATUS_REGISTRY_RECOVERED = 1073741833; + +const int STATUS_FT_READ_RECOVERY_FROM_BACKUP = 1073741834; + +const int STATUS_FT_WRITE_RECOVERY = 1073741835; + +const int STATUS_SERIAL_COUNTER_TIMEOUT = 1073741836; + +const int STATUS_NULL_LM_PASSWORD = 1073741837; + +const int STATUS_IMAGE_MACHINE_TYPE_MISMATCH = 1073741838; + +const int STATUS_RECEIVE_PARTIAL = 1073741839; + +const int STATUS_RECEIVE_EXPEDITED = 1073741840; + +const int STATUS_RECEIVE_PARTIAL_EXPEDITED = 1073741841; + +const int STATUS_EVENT_DONE = 1073741842; + +const int STATUS_EVENT_PENDING = 1073741843; + +const int STATUS_CHECKING_FILE_SYSTEM = 1073741844; + +const int STATUS_FATAL_APP_EXIT = 1073741845; + +const int STATUS_PREDEFINED_HANDLE = 1073741846; + +const int STATUS_WAS_UNLOCKED = 1073741847; + +const int STATUS_SERVICE_NOTIFICATION = 1073741848; + +const int STATUS_WAS_LOCKED = 1073741849; + +const int STATUS_LOG_HARD_ERROR = 1073741850; + +const int STATUS_ALREADY_WIN32 = 1073741851; + +const int STATUS_WX86_UNSIMULATE = 1073741852; + +const int STATUS_WX86_CONTINUE = 1073741853; + +const int STATUS_WX86_SINGLE_STEP = 1073741854; + +const int STATUS_WX86_BREAKPOINT = 1073741855; + +const int STATUS_WX86_EXCEPTION_CONTINUE = 1073741856; + +const int STATUS_WX86_EXCEPTION_LASTCHANCE = 1073741857; + +const int STATUS_WX86_EXCEPTION_CHAIN = 1073741858; + +const int STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 1073741859; + +const int STATUS_NO_YIELD_PERFORMED = 1073741860; + +const int STATUS_TIMER_RESUME_IGNORED = 1073741861; + +const int STATUS_ARBITRATION_UNHANDLED = 1073741862; + +const int STATUS_CARDBUS_NOT_SUPPORTED = 1073741863; + +const int STATUS_WX86_CREATEWX86TIB = 1073741864; + +const int STATUS_MP_PROCESSOR_MISMATCH = 1073741865; + +const int STATUS_HIBERNATED = 1073741866; + +const int STATUS_RESUME_HIBERNATION = 1073741867; + +const int STATUS_FIRMWARE_UPDATED = 1073741868; + +const int STATUS_DRIVERS_LEAKING_LOCKED_PAGES = 1073741869; + +const int STATUS_MESSAGE_RETRIEVED = 1073741870; + +const int STATUS_SYSTEM_POWERSTATE_TRANSITION = 1073741871; + +const int STATUS_ALPC_CHECK_COMPLETION_LIST = 1073741872; + +const int STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 1073741873; + +const int STATUS_ACCESS_AUDIT_BY_POLICY = 1073741874; + +const int STATUS_ABANDON_HIBERFILE = 1073741875; + +const int STATUS_BIZRULES_NOT_ENABLED = 1073741876; + +const int STATUS_FT_READ_FROM_COPY = 1073741877; + +const int STATUS_IMAGE_AT_DIFFERENT_BASE = 1073741878; + +const int STATUS_PATCH_DEFERRED = 1073741879; + +const int DBG_REPLY_LATER = 1073807361; + +const int DBG_UNABLE_TO_PROVIDE_HANDLE = 1073807362; + +const int DBG_TERMINATE_THREAD = 1073807363; + +const int DBG_TERMINATE_PROCESS = 1073807364; + +const int DBG_CONTROL_C = 1073807365; + +const int DBG_PRINTEXCEPTION_C = 1073807366; + +const int DBG_RIPEXCEPTION = 1073807367; + +const int DBG_CONTROL_BREAK = 1073807368; + +const int DBG_COMMAND_EXCEPTION = 1073807369; + +const int DBG_PRINTEXCEPTION_WIDE_C = 1073807370; + +const int STATUS_HEURISTIC_DAMAGE_POSSIBLE = 1075380225; + +const int STATUS_GUARD_PAGE_VIOLATION = -2147483647; + +const int STATUS_DATATYPE_MISALIGNMENT = -2147483646; + +const int STATUS_BREAKPOINT = -2147483645; + +const int STATUS_SINGLE_STEP = -2147483644; + +const int STATUS_BUFFER_OVERFLOW = -2147483643; + +const int STATUS_NO_MORE_FILES = -2147483642; + +const int STATUS_WAKE_SYSTEM_DEBUGGER = -2147483641; + +const int STATUS_HANDLES_CLOSED = -2147483638; + +const int STATUS_NO_INHERITANCE = -2147483637; + +const int STATUS_GUID_SUBSTITUTION_MADE = -2147483636; + +const int STATUS_PARTIAL_COPY = -2147483635; + +const int STATUS_DEVICE_PAPER_EMPTY = -2147483634; + +const int STATUS_DEVICE_POWERED_OFF = -2147483633; + +const int STATUS_DEVICE_OFF_LINE = -2147483632; + +const int STATUS_DEVICE_BUSY = -2147483631; + +const int STATUS_NO_MORE_EAS = -2147483630; + +const int STATUS_INVALID_EA_NAME = -2147483629; + +const int STATUS_EA_LIST_INCONSISTENT = -2147483628; + +const int STATUS_INVALID_EA_FLAG = -2147483627; + +const int STATUS_VERIFY_REQUIRED = -2147483626; + +const int STATUS_EXTRANEOUS_INFORMATION = -2147483625; + +const int STATUS_RXACT_COMMIT_NECESSARY = -2147483624; + +const int STATUS_NO_MORE_ENTRIES = -2147483622; + +const int STATUS_FILEMARK_DETECTED = -2147483621; + +const int STATUS_MEDIA_CHANGED = -2147483620; + +const int STATUS_BUS_RESET = -2147483619; + +const int STATUS_END_OF_MEDIA = -2147483618; + +const int STATUS_BEGINNING_OF_MEDIA = -2147483617; + +const int STATUS_MEDIA_CHECK = -2147483616; + +const int STATUS_SETMARK_DETECTED = -2147483615; + +const int STATUS_NO_DATA_DETECTED = -2147483614; + +const int STATUS_REDIRECTOR_HAS_OPEN_HANDLES = -2147483613; + +const int STATUS_SERVER_HAS_OPEN_HANDLES = -2147483612; + +const int STATUS_ALREADY_DISCONNECTED = -2147483611; + +const int STATUS_LONGJUMP = -2147483610; + +const int STATUS_CLEANER_CARTRIDGE_INSTALLED = -2147483609; + +const int STATUS_PLUGPLAY_QUERY_VETOED = -2147483608; + +const int STATUS_UNWIND_CONSOLIDATE = -2147483607; + +const int STATUS_REGISTRY_HIVE_RECOVERED = -2147483606; + +const int STATUS_DLL_MIGHT_BE_INSECURE = -2147483605; + +const int STATUS_DLL_MIGHT_BE_INCOMPATIBLE = -2147483604; + +const int STATUS_STOPPED_ON_SYMLINK = -2147483603; + +const int STATUS_CANNOT_GRANT_REQUESTED_OPLOCK = -2147483602; + +const int STATUS_NO_ACE_CONDITION = -2147483601; + +const int STATUS_DEVICE_SUPPORT_IN_PROGRESS = -2147483600; + +const int STATUS_DEVICE_POWER_CYCLE_REQUIRED = -2147483599; + +const int STATUS_NO_WORK_DONE = -2147483598; + +const int DBG_EXCEPTION_NOT_HANDLED = -2147418111; + +const int STATUS_CLUSTER_NODE_ALREADY_UP = -2146238463; + +const int STATUS_CLUSTER_NODE_ALREADY_DOWN = -2146238462; + +const int STATUS_CLUSTER_NETWORK_ALREADY_ONLINE = -2146238461; + +const int STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE = -2146238460; + +const int STATUS_CLUSTER_NODE_ALREADY_MEMBER = -2146238459; + +const int STATUS_FLT_BUFFER_TOO_SMALL = -2145648639; + +const int STATUS_FVE_PARTIAL_METADATA = -2145320959; + +const int STATUS_FVE_TRANSIENT_STATE = -2145320958; + +const int STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH = -2147430656; + +const int STATUS_UNSUCCESSFUL = -1073741823; + +const int STATUS_NOT_IMPLEMENTED = -1073741822; + +const int STATUS_INVALID_INFO_CLASS = -1073741821; + +const int STATUS_INFO_LENGTH_MISMATCH = -1073741820; + +const int STATUS_ACCESS_VIOLATION = -1073741819; + +const int STATUS_IN_PAGE_ERROR = -1073741818; + +const int STATUS_PAGEFILE_QUOTA = -1073741817; + +const int STATUS_INVALID_HANDLE = -1073741816; + +const int STATUS_BAD_INITIAL_STACK = -1073741815; + +const int STATUS_BAD_INITIAL_PC = -1073741814; + +const int STATUS_INVALID_CID = -1073741813; + +const int STATUS_TIMER_NOT_CANCELED = -1073741812; + +const int STATUS_INVALID_PARAMETER = -1073741811; + +const int STATUS_NO_SUCH_DEVICE = -1073741810; + +const int STATUS_NO_SUCH_FILE = -1073741809; + +const int STATUS_INVALID_DEVICE_REQUEST = -1073741808; + +const int STATUS_END_OF_FILE = -1073741807; + +const int STATUS_WRONG_VOLUME = -1073741806; + +const int STATUS_NO_MEDIA_IN_DEVICE = -1073741805; + +const int STATUS_UNRECOGNIZED_MEDIA = -1073741804; + +const int STATUS_NONEXISTENT_SECTOR = -1073741803; + +const int STATUS_MORE_PROCESSING_REQUIRED = -1073741802; + +const int STATUS_NO_MEMORY = -1073741801; + +const int STATUS_CONFLICTING_ADDRESSES = -1073741800; + +const int STATUS_NOT_MAPPED_VIEW = -1073741799; + +const int STATUS_UNABLE_TO_FREE_VM = -1073741798; + +const int STATUS_UNABLE_TO_DELETE_SECTION = -1073741797; + +const int STATUS_INVALID_SYSTEM_SERVICE = -1073741796; + +const int STATUS_ILLEGAL_INSTRUCTION = -1073741795; + +const int STATUS_INVALID_LOCK_SEQUENCE = -1073741794; + +const int STATUS_INVALID_VIEW_SIZE = -1073741793; + +const int STATUS_INVALID_FILE_FOR_SECTION = -1073741792; + +const int STATUS_ALREADY_COMMITTED = -1073741791; + +const int STATUS_ACCESS_DENIED = -1073741790; + +const int STATUS_BUFFER_TOO_SMALL = -1073741789; + +const int STATUS_OBJECT_TYPE_MISMATCH = -1073741788; + +const int STATUS_NONCONTINUABLE_EXCEPTION = -1073741787; + +const int STATUS_INVALID_DISPOSITION = -1073741786; + +const int STATUS_UNWIND = -1073741785; + +const int STATUS_BAD_STACK = -1073741784; + +const int STATUS_INVALID_UNWIND_TARGET = -1073741783; + +const int STATUS_NOT_LOCKED = -1073741782; + +const int STATUS_PARITY_ERROR = -1073741781; + +const int STATUS_UNABLE_TO_DECOMMIT_VM = -1073741780; + +const int STATUS_NOT_COMMITTED = -1073741779; + +const int STATUS_INVALID_PORT_ATTRIBUTES = -1073741778; + +const int STATUS_PORT_MESSAGE_TOO_LONG = -1073741777; + +const int STATUS_INVALID_PARAMETER_MIX = -1073741776; + +const int STATUS_INVALID_QUOTA_LOWER = -1073741775; + +const int STATUS_DISK_CORRUPT_ERROR = -1073741774; + +const int STATUS_OBJECT_NAME_INVALID = -1073741773; + +const int STATUS_OBJECT_NAME_NOT_FOUND = -1073741772; + +const int STATUS_OBJECT_NAME_COLLISION = -1073741771; + +const int STATUS_PORT_DO_NOT_DISTURB = -1073741770; + +const int STATUS_PORT_DISCONNECTED = -1073741769; + +const int STATUS_DEVICE_ALREADY_ATTACHED = -1073741768; + +const int STATUS_OBJECT_PATH_INVALID = -1073741767; + +const int STATUS_OBJECT_PATH_NOT_FOUND = -1073741766; + +const int STATUS_OBJECT_PATH_SYNTAX_BAD = -1073741765; + +const int STATUS_DATA_OVERRUN = -1073741764; + +const int STATUS_DATA_LATE_ERROR = -1073741763; + +const int STATUS_DATA_ERROR = -1073741762; + +const int STATUS_CRC_ERROR = -1073741761; + +const int STATUS_SECTION_TOO_BIG = -1073741760; + +const int STATUS_PORT_CONNECTION_REFUSED = -1073741759; + +const int STATUS_INVALID_PORT_HANDLE = -1073741758; + +const int STATUS_SHARING_VIOLATION = -1073741757; + +const int STATUS_QUOTA_EXCEEDED = -1073741756; + +const int STATUS_INVALID_PAGE_PROTECTION = -1073741755; + +const int STATUS_MUTANT_NOT_OWNED = -1073741754; + +const int STATUS_SEMAPHORE_LIMIT_EXCEEDED = -1073741753; + +const int STATUS_PORT_ALREADY_SET = -1073741752; + +const int STATUS_SECTION_NOT_IMAGE = -1073741751; + +const int STATUS_SUSPEND_COUNT_EXCEEDED = -1073741750; + +const int STATUS_THREAD_IS_TERMINATING = -1073741749; + +const int STATUS_BAD_WORKING_SET_LIMIT = -1073741748; + +const int STATUS_INCOMPATIBLE_FILE_MAP = -1073741747; + +const int STATUS_SECTION_PROTECTION = -1073741746; + +const int STATUS_EAS_NOT_SUPPORTED = -1073741745; + +const int STATUS_EA_TOO_LARGE = -1073741744; + +const int STATUS_NONEXISTENT_EA_ENTRY = -1073741743; + +const int STATUS_NO_EAS_ON_FILE = -1073741742; + +const int STATUS_EA_CORRUPT_ERROR = -1073741741; + +const int STATUS_FILE_LOCK_CONFLICT = -1073741740; + +const int STATUS_LOCK_NOT_GRANTED = -1073741739; + +const int STATUS_DELETE_PENDING = -1073741738; + +const int STATUS_CTL_FILE_NOT_SUPPORTED = -1073741737; + +const int STATUS_UNKNOWN_REVISION = -1073741736; + +const int STATUS_REVISION_MISMATCH = -1073741735; + +const int STATUS_INVALID_OWNER = -1073741734; + +const int STATUS_INVALID_PRIMARY_GROUP = -1073741733; + +const int STATUS_NO_IMPERSONATION_TOKEN = -1073741732; + +const int STATUS_CANT_DISABLE_MANDATORY = -1073741731; + +const int STATUS_NO_LOGON_SERVERS = -1073741730; + +const int STATUS_NO_SUCH_LOGON_SESSION = -1073741729; + +const int STATUS_NO_SUCH_PRIVILEGE = -1073741728; + +const int STATUS_PRIVILEGE_NOT_HELD = -1073741727; + +const int STATUS_INVALID_ACCOUNT_NAME = -1073741726; + +const int STATUS_USER_EXISTS = -1073741725; + +const int STATUS_NO_SUCH_USER = -1073741724; + +const int STATUS_GROUP_EXISTS = -1073741723; + +const int STATUS_NO_SUCH_GROUP = -1073741722; + +const int STATUS_MEMBER_IN_GROUP = -1073741721; + +const int STATUS_MEMBER_NOT_IN_GROUP = -1073741720; + +const int STATUS_LAST_ADMIN = -1073741719; + +const int STATUS_WRONG_PASSWORD = -1073741718; + +const int STATUS_ILL_FORMED_PASSWORD = -1073741717; + +const int STATUS_PASSWORD_RESTRICTION = -1073741716; + +const int STATUS_LOGON_FAILURE = -1073741715; + +const int STATUS_ACCOUNT_RESTRICTION = -1073741714; + +const int STATUS_INVALID_LOGON_HOURS = -1073741713; + +const int STATUS_INVALID_WORKSTATION = -1073741712; + +const int STATUS_PASSWORD_EXPIRED = -1073741711; + +const int STATUS_ACCOUNT_DISABLED = -1073741710; + +const int STATUS_NONE_MAPPED = -1073741709; + +const int STATUS_TOO_MANY_LUIDS_REQUESTED = -1073741708; + +const int STATUS_LUIDS_EXHAUSTED = -1073741707; + +const int STATUS_INVALID_SUB_AUTHORITY = -1073741706; + +const int STATUS_INVALID_ACL = -1073741705; + +const int STATUS_INVALID_SID = -1073741704; + +const int STATUS_INVALID_SECURITY_DESCR = -1073741703; + +const int STATUS_PROCEDURE_NOT_FOUND = -1073741702; + +const int STATUS_INVALID_IMAGE_FORMAT = -1073741701; + +const int STATUS_NO_TOKEN = -1073741700; + +const int STATUS_BAD_INHERITANCE_ACL = -1073741699; + +const int STATUS_RANGE_NOT_LOCKED = -1073741698; + +const int STATUS_DISK_FULL = -1073741697; + +const int STATUS_SERVER_DISABLED = -1073741696; + +const int STATUS_SERVER_NOT_DISABLED = -1073741695; + +const int STATUS_TOO_MANY_GUIDS_REQUESTED = -1073741694; + +const int STATUS_GUIDS_EXHAUSTED = -1073741693; + +const int STATUS_INVALID_ID_AUTHORITY = -1073741692; + +const int STATUS_AGENTS_EXHAUSTED = -1073741691; + +const int STATUS_INVALID_VOLUME_LABEL = -1073741690; + +const int STATUS_SECTION_NOT_EXTENDED = -1073741689; + +const int STATUS_NOT_MAPPED_DATA = -1073741688; + +const int STATUS_RESOURCE_DATA_NOT_FOUND = -1073741687; + +const int STATUS_RESOURCE_TYPE_NOT_FOUND = -1073741686; + +const int STATUS_RESOURCE_NAME_NOT_FOUND = -1073741685; + +const int STATUS_ARRAY_BOUNDS_EXCEEDED = -1073741684; + +const int STATUS_FLOAT_DENORMAL_OPERAND = -1073741683; + +const int STATUS_FLOAT_DIVIDE_BY_ZERO = -1073741682; + +const int STATUS_FLOAT_INEXACT_RESULT = -1073741681; + +const int STATUS_FLOAT_INVALID_OPERATION = -1073741680; + +const int STATUS_FLOAT_OVERFLOW = -1073741679; + +const int STATUS_FLOAT_STACK_CHECK = -1073741678; + +const int STATUS_FLOAT_UNDERFLOW = -1073741677; + +const int STATUS_INTEGER_DIVIDE_BY_ZERO = -1073741676; + +const int STATUS_INTEGER_OVERFLOW = -1073741675; + +const int STATUS_PRIVILEGED_INSTRUCTION = -1073741674; + +const int STATUS_TOO_MANY_PAGING_FILES = -1073741673; + +const int STATUS_FILE_INVALID = -1073741672; + +const int STATUS_ALLOTTED_SPACE_EXCEEDED = -1073741671; + +const int STATUS_INSUFFICIENT_RESOURCES = -1073741670; + +const int STATUS_DFS_EXIT_PATH_FOUND = -1073741669; + +const int STATUS_DEVICE_DATA_ERROR = -1073741668; + +const int STATUS_DEVICE_NOT_CONNECTED = -1073741667; + +const int STATUS_DEVICE_POWER_FAILURE = -1073741666; + +const int STATUS_FREE_VM_NOT_AT_BASE = -1073741665; + +const int STATUS_MEMORY_NOT_ALLOCATED = -1073741664; + +const int STATUS_WORKING_SET_QUOTA = -1073741663; + +const int STATUS_MEDIA_WRITE_PROTECTED = -1073741662; + +const int STATUS_DEVICE_NOT_READY = -1073741661; + +const int STATUS_INVALID_GROUP_ATTRIBUTES = -1073741660; + +const int STATUS_BAD_IMPERSONATION_LEVEL = -1073741659; + +const int STATUS_CANT_OPEN_ANONYMOUS = -1073741658; + +const int STATUS_BAD_VALIDATION_CLASS = -1073741657; + +const int STATUS_BAD_TOKEN_TYPE = -1073741656; + +const int STATUS_BAD_MASTER_BOOT_RECORD = -1073741655; + +const int STATUS_INSTRUCTION_MISALIGNMENT = -1073741654; + +const int STATUS_INSTANCE_NOT_AVAILABLE = -1073741653; + +const int STATUS_PIPE_NOT_AVAILABLE = -1073741652; + +const int STATUS_INVALID_PIPE_STATE = -1073741651; + +const int STATUS_PIPE_BUSY = -1073741650; + +const int STATUS_ILLEGAL_FUNCTION = -1073741649; + +const int STATUS_PIPE_DISCONNECTED = -1073741648; + +const int STATUS_PIPE_CLOSING = -1073741647; + +const int STATUS_PIPE_CONNECTED = -1073741646; + +const int STATUS_PIPE_LISTENING = -1073741645; + +const int STATUS_INVALID_READ_MODE = -1073741644; + +const int STATUS_IO_TIMEOUT = -1073741643; + +const int STATUS_FILE_FORCED_CLOSED = -1073741642; + +const int STATUS_PROFILING_NOT_STARTED = -1073741641; + +const int STATUS_PROFILING_NOT_STOPPED = -1073741640; + +const int STATUS_COULD_NOT_INTERPRET = -1073741639; + +const int STATUS_FILE_IS_A_DIRECTORY = -1073741638; + +const int STATUS_NOT_SUPPORTED = -1073741637; + +const int STATUS_REMOTE_NOT_LISTENING = -1073741636; + +const int STATUS_DUPLICATE_NAME = -1073741635; + +const int STATUS_BAD_NETWORK_PATH = -1073741634; + +const int STATUS_NETWORK_BUSY = -1073741633; + +const int STATUS_DEVICE_DOES_NOT_EXIST = -1073741632; + +const int STATUS_TOO_MANY_COMMANDS = -1073741631; + +const int STATUS_ADAPTER_HARDWARE_ERROR = -1073741630; + +const int STATUS_INVALID_NETWORK_RESPONSE = -1073741629; + +const int STATUS_UNEXPECTED_NETWORK_ERROR = -1073741628; + +const int STATUS_BAD_REMOTE_ADAPTER = -1073741627; + +const int STATUS_PRINT_QUEUE_FULL = -1073741626; + +const int STATUS_NO_SPOOL_SPACE = -1073741625; + +const int STATUS_PRINT_CANCELLED = -1073741624; + +const int STATUS_NETWORK_NAME_DELETED = -1073741623; + +const int STATUS_NETWORK_ACCESS_DENIED = -1073741622; + +const int STATUS_BAD_DEVICE_TYPE = -1073741621; + +const int STATUS_BAD_NETWORK_NAME = -1073741620; + +const int STATUS_TOO_MANY_NAMES = -1073741619; + +const int STATUS_TOO_MANY_SESSIONS = -1073741618; + +const int STATUS_SHARING_PAUSED = -1073741617; + +const int STATUS_REQUEST_NOT_ACCEPTED = -1073741616; + +const int STATUS_REDIRECTOR_PAUSED = -1073741615; + +const int STATUS_NET_WRITE_FAULT = -1073741614; + +const int STATUS_PROFILING_AT_LIMIT = -1073741613; + +const int STATUS_NOT_SAME_DEVICE = -1073741612; + +const int STATUS_FILE_RENAMED = -1073741611; + +const int STATUS_VIRTUAL_CIRCUIT_CLOSED = -1073741610; + +const int STATUS_NO_SECURITY_ON_OBJECT = -1073741609; + +const int STATUS_CANT_WAIT = -1073741608; + +const int STATUS_PIPE_EMPTY = -1073741607; + +const int STATUS_CANT_ACCESS_DOMAIN_INFO = -1073741606; + +const int STATUS_CANT_TERMINATE_SELF = -1073741605; + +const int STATUS_INVALID_SERVER_STATE = -1073741604; + +const int STATUS_INVALID_DOMAIN_STATE = -1073741603; + +const int STATUS_INVALID_DOMAIN_ROLE = -1073741602; + +const int STATUS_NO_SUCH_DOMAIN = -1073741601; + +const int STATUS_DOMAIN_EXISTS = -1073741600; + +const int STATUS_DOMAIN_LIMIT_EXCEEDED = -1073741599; + +const int STATUS_OPLOCK_NOT_GRANTED = -1073741598; + +const int STATUS_INVALID_OPLOCK_PROTOCOL = -1073741597; + +const int STATUS_INTERNAL_DB_CORRUPTION = -1073741596; + +const int STATUS_INTERNAL_ERROR = -1073741595; + +const int STATUS_GENERIC_NOT_MAPPED = -1073741594; + +const int STATUS_BAD_DESCRIPTOR_FORMAT = -1073741593; + +const int STATUS_INVALID_USER_BUFFER = -1073741592; + +const int STATUS_UNEXPECTED_IO_ERROR = -1073741591; + +const int STATUS_UNEXPECTED_MM_CREATE_ERR = -1073741590; + +const int STATUS_UNEXPECTED_MM_MAP_ERROR = -1073741589; + +const int STATUS_UNEXPECTED_MM_EXTEND_ERR = -1073741588; + +const int STATUS_NOT_LOGON_PROCESS = -1073741587; + +const int STATUS_LOGON_SESSION_EXISTS = -1073741586; + +const int STATUS_INVALID_PARAMETER_1 = -1073741585; + +const int STATUS_INVALID_PARAMETER_2 = -1073741584; + +const int STATUS_INVALID_PARAMETER_3 = -1073741583; + +const int STATUS_INVALID_PARAMETER_4 = -1073741582; + +const int STATUS_INVALID_PARAMETER_5 = -1073741581; + +const int STATUS_INVALID_PARAMETER_6 = -1073741580; + +const int STATUS_INVALID_PARAMETER_7 = -1073741579; + +const int STATUS_INVALID_PARAMETER_8 = -1073741578; + +const int STATUS_INVALID_PARAMETER_9 = -1073741577; + +const int STATUS_INVALID_PARAMETER_10 = -1073741576; + +const int STATUS_INVALID_PARAMETER_11 = -1073741575; + +const int STATUS_INVALID_PARAMETER_12 = -1073741574; + +const int STATUS_REDIRECTOR_NOT_STARTED = -1073741573; + +const int STATUS_REDIRECTOR_STARTED = -1073741572; + +const int STATUS_STACK_OVERFLOW = -1073741571; + +const int STATUS_NO_SUCH_PACKAGE = -1073741570; + +const int STATUS_BAD_FUNCTION_TABLE = -1073741569; + +const int STATUS_VARIABLE_NOT_FOUND = -1073741568; + +const int STATUS_DIRECTORY_NOT_EMPTY = -1073741567; + +const int STATUS_FILE_CORRUPT_ERROR = -1073741566; + +const int STATUS_NOT_A_DIRECTORY = -1073741565; + +const int STATUS_BAD_LOGON_SESSION_STATE = -1073741564; + +const int STATUS_LOGON_SESSION_COLLISION = -1073741563; + +const int STATUS_NAME_TOO_LONG = -1073741562; + +const int STATUS_FILES_OPEN = -1073741561; + +const int STATUS_CONNECTION_IN_USE = -1073741560; + +const int STATUS_MESSAGE_NOT_FOUND = -1073741559; + +const int STATUS_PROCESS_IS_TERMINATING = -1073741558; + +const int STATUS_INVALID_LOGON_TYPE = -1073741557; + +const int STATUS_NO_GUID_TRANSLATION = -1073741556; + +const int STATUS_CANNOT_IMPERSONATE = -1073741555; + +const int STATUS_IMAGE_ALREADY_LOADED = -1073741554; + +const int STATUS_ABIOS_NOT_PRESENT = -1073741553; + +const int STATUS_ABIOS_LID_NOT_EXIST = -1073741552; + +const int STATUS_ABIOS_LID_ALREADY_OWNED = -1073741551; + +const int STATUS_ABIOS_NOT_LID_OWNER = -1073741550; + +const int STATUS_ABIOS_INVALID_COMMAND = -1073741549; + +const int STATUS_ABIOS_INVALID_LID = -1073741548; + +const int STATUS_ABIOS_SELECTOR_NOT_AVAILABLE = -1073741547; + +const int STATUS_ABIOS_INVALID_SELECTOR = -1073741546; + +const int STATUS_NO_LDT = -1073741545; + +const int STATUS_INVALID_LDT_SIZE = -1073741544; + +const int STATUS_INVALID_LDT_OFFSET = -1073741543; + +const int STATUS_INVALID_LDT_DESCRIPTOR = -1073741542; + +const int STATUS_INVALID_IMAGE_NE_FORMAT = -1073741541; + +const int STATUS_RXACT_INVALID_STATE = -1073741540; + +const int STATUS_RXACT_COMMIT_FAILURE = -1073741539; + +const int STATUS_MAPPED_FILE_SIZE_ZERO = -1073741538; + +const int STATUS_TOO_MANY_OPENED_FILES = -1073741537; + +const int STATUS_CANCELLED = -1073741536; + +const int STATUS_CANNOT_DELETE = -1073741535; + +const int STATUS_INVALID_COMPUTER_NAME = -1073741534; + +const int STATUS_FILE_DELETED = -1073741533; + +const int STATUS_SPECIAL_ACCOUNT = -1073741532; + +const int STATUS_SPECIAL_GROUP = -1073741531; + +const int STATUS_SPECIAL_USER = -1073741530; + +const int STATUS_MEMBERS_PRIMARY_GROUP = -1073741529; + +const int STATUS_FILE_CLOSED = -1073741528; + +const int STATUS_TOO_MANY_THREADS = -1073741527; + +const int STATUS_THREAD_NOT_IN_PROCESS = -1073741526; + +const int STATUS_TOKEN_ALREADY_IN_USE = -1073741525; + +const int STATUS_PAGEFILE_QUOTA_EXCEEDED = -1073741524; + +const int STATUS_COMMITMENT_LIMIT = -1073741523; + +const int STATUS_INVALID_IMAGE_LE_FORMAT = -1073741522; + +const int STATUS_INVALID_IMAGE_NOT_MZ = -1073741521; + +const int STATUS_INVALID_IMAGE_PROTECT = -1073741520; + +const int STATUS_INVALID_IMAGE_WIN_16 = -1073741519; + +const int STATUS_LOGON_SERVER_CONFLICT = -1073741518; + +const int STATUS_TIME_DIFFERENCE_AT_DC = -1073741517; + +const int STATUS_SYNCHRONIZATION_REQUIRED = -1073741516; + +const int STATUS_DLL_NOT_FOUND = -1073741515; + +const int STATUS_OPEN_FAILED = -1073741514; + +const int STATUS_IO_PRIVILEGE_FAILED = -1073741513; + +const int STATUS_ORDINAL_NOT_FOUND = -1073741512; + +const int STATUS_ENTRYPOINT_NOT_FOUND = -1073741511; + +const int STATUS_CONTROL_C_EXIT = -1073741510; + +const int STATUS_LOCAL_DISCONNECT = -1073741509; + +const int STATUS_REMOTE_DISCONNECT = -1073741508; + +const int STATUS_REMOTE_RESOURCES = -1073741507; + +const int STATUS_LINK_FAILED = -1073741506; + +const int STATUS_LINK_TIMEOUT = -1073741505; + +const int STATUS_INVALID_CONNECTION = -1073741504; + +const int STATUS_INVALID_ADDRESS = -1073741503; + +const int STATUS_DLL_INIT_FAILED = -1073741502; + +const int STATUS_MISSING_SYSTEMFILE = -1073741501; + +const int STATUS_UNHANDLED_EXCEPTION = -1073741500; + +const int STATUS_APP_INIT_FAILURE = -1073741499; + +const int STATUS_PAGEFILE_CREATE_FAILED = -1073741498; + +const int STATUS_NO_PAGEFILE = -1073741497; + +const int STATUS_INVALID_LEVEL = -1073741496; + +const int STATUS_WRONG_PASSWORD_CORE = -1073741495; + +const int STATUS_ILLEGAL_FLOAT_CONTEXT = -1073741494; + +const int STATUS_PIPE_BROKEN = -1073741493; + +const int STATUS_REGISTRY_CORRUPT = -1073741492; + +const int STATUS_REGISTRY_IO_FAILED = -1073741491; + +const int STATUS_NO_EVENT_PAIR = -1073741490; + +const int STATUS_UNRECOGNIZED_VOLUME = -1073741489; + +const int STATUS_SERIAL_NO_DEVICE_INITED = -1073741488; + +const int STATUS_NO_SUCH_ALIAS = -1073741487; + +const int STATUS_MEMBER_NOT_IN_ALIAS = -1073741486; + +const int STATUS_MEMBER_IN_ALIAS = -1073741485; + +const int STATUS_ALIAS_EXISTS = -1073741484; + +const int STATUS_LOGON_NOT_GRANTED = -1073741483; + +const int STATUS_TOO_MANY_SECRETS = -1073741482; + +const int STATUS_SECRET_TOO_LONG = -1073741481; + +const int STATUS_INTERNAL_DB_ERROR = -1073741480; + +const int STATUS_FULLSCREEN_MODE = -1073741479; + +const int STATUS_TOO_MANY_CONTEXT_IDS = -1073741478; + +const int STATUS_LOGON_TYPE_NOT_GRANTED = -1073741477; + +const int STATUS_NOT_REGISTRY_FILE = -1073741476; + +const int STATUS_NT_CROSS_ENCRYPTION_REQUIRED = -1073741475; + +const int STATUS_DOMAIN_CTRLR_CONFIG_ERROR = -1073741474; + +const int STATUS_FT_MISSING_MEMBER = -1073741473; + +const int STATUS_ILL_FORMED_SERVICE_ENTRY = -1073741472; + +const int STATUS_ILLEGAL_CHARACTER = -1073741471; + +const int STATUS_UNMAPPABLE_CHARACTER = -1073741470; + +const int STATUS_UNDEFINED_CHARACTER = -1073741469; + +const int STATUS_FLOPPY_VOLUME = -1073741468; + +const int STATUS_FLOPPY_ID_MARK_NOT_FOUND = -1073741467; + +const int STATUS_FLOPPY_WRONG_CYLINDER = -1073741466; + +const int STATUS_FLOPPY_UNKNOWN_ERROR = -1073741465; + +const int STATUS_FLOPPY_BAD_REGISTERS = -1073741464; + +const int STATUS_DISK_RECALIBRATE_FAILED = -1073741463; + +const int STATUS_DISK_OPERATION_FAILED = -1073741462; + +const int STATUS_DISK_RESET_FAILED = -1073741461; + +const int STATUS_SHARED_IRQ_BUSY = -1073741460; + +const int STATUS_FT_ORPHANING = -1073741459; + +const int STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT = -1073741458; + +const int STATUS_PARTITION_FAILURE = -1073741454; + +const int STATUS_INVALID_BLOCK_LENGTH = -1073741453; + +const int STATUS_DEVICE_NOT_PARTITIONED = -1073741452; + +const int STATUS_UNABLE_TO_LOCK_MEDIA = -1073741451; + +const int STATUS_UNABLE_TO_UNLOAD_MEDIA = -1073741450; + +const int STATUS_EOM_OVERFLOW = -1073741449; + +const int STATUS_NO_MEDIA = -1073741448; + +const int STATUS_NO_SUCH_MEMBER = -1073741446; + +const int STATUS_INVALID_MEMBER = -1073741445; + +const int STATUS_KEY_DELETED = -1073741444; + +const int STATUS_NO_LOG_SPACE = -1073741443; + +const int STATUS_TOO_MANY_SIDS = -1073741442; + +const int STATUS_LM_CROSS_ENCRYPTION_REQUIRED = -1073741441; + +const int STATUS_KEY_HAS_CHILDREN = -1073741440; + +const int STATUS_CHILD_MUST_BE_VOLATILE = -1073741439; + +const int STATUS_DEVICE_CONFIGURATION_ERROR = -1073741438; + +const int STATUS_DRIVER_INTERNAL_ERROR = -1073741437; + +const int STATUS_INVALID_DEVICE_STATE = -1073741436; + +const int STATUS_IO_DEVICE_ERROR = -1073741435; + +const int STATUS_DEVICE_PROTOCOL_ERROR = -1073741434; + +const int STATUS_BACKUP_CONTROLLER = -1073741433; + +const int STATUS_LOG_FILE_FULL = -1073741432; + +const int STATUS_TOO_LATE = -1073741431; + +const int STATUS_NO_TRUST_LSA_SECRET = -1073741430; + +const int STATUS_NO_TRUST_SAM_ACCOUNT = -1073741429; + +const int STATUS_TRUSTED_DOMAIN_FAILURE = -1073741428; + +const int STATUS_TRUSTED_RELATIONSHIP_FAILURE = -1073741427; + +const int STATUS_EVENTLOG_FILE_CORRUPT = -1073741426; + +const int STATUS_EVENTLOG_CANT_START = -1073741425; + +const int STATUS_TRUST_FAILURE = -1073741424; + +const int STATUS_MUTANT_LIMIT_EXCEEDED = -1073741423; + +const int STATUS_NETLOGON_NOT_STARTED = -1073741422; + +const int STATUS_ACCOUNT_EXPIRED = -1073741421; + +const int STATUS_POSSIBLE_DEADLOCK = -1073741420; + +const int STATUS_NETWORK_CREDENTIAL_CONFLICT = -1073741419; + +const int STATUS_REMOTE_SESSION_LIMIT = -1073741418; + +const int STATUS_EVENTLOG_FILE_CHANGED = -1073741417; + +const int STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = -1073741416; + +const int STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT = -1073741415; + +const int STATUS_NOLOGON_SERVER_TRUST_ACCOUNT = -1073741414; + +const int STATUS_DOMAIN_TRUST_INCONSISTENT = -1073741413; + +const int STATUS_FS_DRIVER_REQUIRED = -1073741412; + +const int STATUS_IMAGE_ALREADY_LOADED_AS_DLL = -1073741411; + +const int STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = + -1073741410; + +const int STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME = -1073741409; + +const int STATUS_SECURITY_STREAM_IS_INCONSISTENT = -1073741408; + +const int STATUS_INVALID_LOCK_RANGE = -1073741407; + +const int STATUS_INVALID_ACE_CONDITION = -1073741406; + +const int STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT = -1073741405; + +const int STATUS_NOTIFICATION_GUID_ALREADY_DEFINED = -1073741404; + +const int STATUS_INVALID_EXCEPTION_HANDLER = -1073741403; + +const int STATUS_DUPLICATE_PRIVILEGES = -1073741402; + +const int STATUS_NOT_ALLOWED_ON_SYSTEM_FILE = -1073741401; + +const int STATUS_REPAIR_NEEDED = -1073741400; + +const int STATUS_QUOTA_NOT_ENABLED = -1073741399; + +const int STATUS_NO_APPLICATION_PACKAGE = -1073741398; + +const int STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS = -1073741397; + +const int STATUS_NOT_SAME_OBJECT = -1073741396; + +const int STATUS_FATAL_MEMORY_EXHAUSTION = -1073741395; + +const int STATUS_ERROR_PROCESS_NOT_IN_JOB = -1073741394; + +const int STATUS_CPU_SET_INVALID = -1073741393; + +const int STATUS_IO_DEVICE_INVALID_DATA = -1073741392; + +const int STATUS_IO_UNALIGNED_WRITE = -1073741391; + +const int STATUS_NETWORK_OPEN_RESTRICTION = -1073741311; + +const int STATUS_NO_USER_SESSION_KEY = -1073741310; + +const int STATUS_USER_SESSION_DELETED = -1073741309; + +const int STATUS_RESOURCE_LANG_NOT_FOUND = -1073741308; + +const int STATUS_INSUFF_SERVER_RESOURCES = -1073741307; + +const int STATUS_INVALID_BUFFER_SIZE = -1073741306; + +const int STATUS_INVALID_ADDRESS_COMPONENT = -1073741305; + +const int STATUS_INVALID_ADDRESS_WILDCARD = -1073741304; + +const int STATUS_TOO_MANY_ADDRESSES = -1073741303; + +const int STATUS_ADDRESS_ALREADY_EXISTS = -1073741302; + +const int STATUS_ADDRESS_CLOSED = -1073741301; + +const int STATUS_CONNECTION_DISCONNECTED = -1073741300; + +const int STATUS_CONNECTION_RESET = -1073741299; + +const int STATUS_TOO_MANY_NODES = -1073741298; + +const int STATUS_TRANSACTION_ABORTED = -1073741297; + +const int STATUS_TRANSACTION_TIMED_OUT = -1073741296; + +const int STATUS_TRANSACTION_NO_RELEASE = -1073741295; + +const int STATUS_TRANSACTION_NO_MATCH = -1073741294; + +const int STATUS_TRANSACTION_RESPONDED = -1073741293; + +const int STATUS_TRANSACTION_INVALID_ID = -1073741292; + +const int STATUS_TRANSACTION_INVALID_TYPE = -1073741291; + +const int STATUS_NOT_SERVER_SESSION = -1073741290; + +const int STATUS_NOT_CLIENT_SESSION = -1073741289; + +const int STATUS_CANNOT_LOAD_REGISTRY_FILE = -1073741288; + +const int STATUS_DEBUG_ATTACH_FAILED = -1073741287; + +const int STATUS_SYSTEM_PROCESS_TERMINATED = -1073741286; + +const int STATUS_DATA_NOT_ACCEPTED = -1073741285; + +const int STATUS_NO_BROWSER_SERVERS_FOUND = -1073741284; + +const int STATUS_VDM_HARD_ERROR = -1073741283; + +const int STATUS_DRIVER_CANCEL_TIMEOUT = -1073741282; + +const int STATUS_REPLY_MESSAGE_MISMATCH = -1073741281; + +const int STATUS_MAPPED_ALIGNMENT = -1073741280; + +const int STATUS_IMAGE_CHECKSUM_MISMATCH = -1073741279; + +const int STATUS_LOST_WRITEBEHIND_DATA = -1073741278; + +const int STATUS_CLIENT_SERVER_PARAMETERS_INVALID = -1073741277; + +const int STATUS_PASSWORD_MUST_CHANGE = -1073741276; + +const int STATUS_NOT_FOUND = -1073741275; + +const int STATUS_NOT_TINY_STREAM = -1073741274; + +const int STATUS_RECOVERY_FAILURE = -1073741273; + +const int STATUS_STACK_OVERFLOW_READ = -1073741272; + +const int STATUS_FAIL_CHECK = -1073741271; + +const int STATUS_DUPLICATE_OBJECTID = -1073741270; + +const int STATUS_OBJECTID_EXISTS = -1073741269; + +const int STATUS_CONVERT_TO_LARGE = -1073741268; + +const int STATUS_RETRY = -1073741267; + +const int STATUS_FOUND_OUT_OF_SCOPE = -1073741266; + +const int STATUS_ALLOCATE_BUCKET = -1073741265; + +const int STATUS_PROPSET_NOT_FOUND = -1073741264; + +const int STATUS_MARSHALL_OVERFLOW = -1073741263; + +const int STATUS_INVALID_VARIANT = -1073741262; + +const int STATUS_DOMAIN_CONTROLLER_NOT_FOUND = -1073741261; + +const int STATUS_ACCOUNT_LOCKED_OUT = -1073741260; + +const int STATUS_HANDLE_NOT_CLOSABLE = -1073741259; + +const int STATUS_CONNECTION_REFUSED = -1073741258; + +const int STATUS_GRACEFUL_DISCONNECT = -1073741257; + +const int STATUS_ADDRESS_ALREADY_ASSOCIATED = -1073741256; + +const int STATUS_ADDRESS_NOT_ASSOCIATED = -1073741255; + +const int STATUS_CONNECTION_INVALID = -1073741254; + +const int STATUS_CONNECTION_ACTIVE = -1073741253; + +const int STATUS_NETWORK_UNREACHABLE = -1073741252; + +const int STATUS_HOST_UNREACHABLE = -1073741251; + +const int STATUS_PROTOCOL_UNREACHABLE = -1073741250; + +const int STATUS_PORT_UNREACHABLE = -1073741249; + +const int STATUS_REQUEST_ABORTED = -1073741248; + +const int STATUS_CONNECTION_ABORTED = -1073741247; + +const int STATUS_BAD_COMPRESSION_BUFFER = -1073741246; + +const int STATUS_USER_MAPPED_FILE = -1073741245; + +const int STATUS_AUDIT_FAILED = -1073741244; + +const int STATUS_TIMER_RESOLUTION_NOT_SET = -1073741243; + +const int STATUS_CONNECTION_COUNT_LIMIT = -1073741242; + +const int STATUS_LOGIN_TIME_RESTRICTION = -1073741241; + +const int STATUS_LOGIN_WKSTA_RESTRICTION = -1073741240; + +const int STATUS_IMAGE_MP_UP_MISMATCH = -1073741239; + +const int STATUS_INSUFFICIENT_LOGON_INFO = -1073741232; + +const int STATUS_BAD_DLL_ENTRYPOINT = -1073741231; + +const int STATUS_BAD_SERVICE_ENTRYPOINT = -1073741230; + +const int STATUS_LPC_REPLY_LOST = -1073741229; + +const int STATUS_IP_ADDRESS_CONFLICT1 = -1073741228; + +const int STATUS_IP_ADDRESS_CONFLICT2 = -1073741227; + +const int STATUS_REGISTRY_QUOTA_LIMIT = -1073741226; + +const int STATUS_PATH_NOT_COVERED = -1073741225; + +const int STATUS_NO_CALLBACK_ACTIVE = -1073741224; + +const int STATUS_LICENSE_QUOTA_EXCEEDED = -1073741223; + +const int STATUS_PWD_TOO_SHORT = -1073741222; + +const int STATUS_PWD_TOO_RECENT = -1073741221; + +const int STATUS_PWD_HISTORY_CONFLICT = -1073741220; + +const int STATUS_PLUGPLAY_NO_DEVICE = -1073741218; + +const int STATUS_UNSUPPORTED_COMPRESSION = -1073741217; + +const int STATUS_INVALID_HW_PROFILE = -1073741216; + +const int STATUS_INVALID_PLUGPLAY_DEVICE_PATH = -1073741215; + +const int STATUS_DRIVER_ORDINAL_NOT_FOUND = -1073741214; + +const int STATUS_DRIVER_ENTRYPOINT_NOT_FOUND = -1073741213; + +const int STATUS_RESOURCE_NOT_OWNED = -1073741212; + +const int STATUS_TOO_MANY_LINKS = -1073741211; + +const int STATUS_QUOTA_LIST_INCONSISTENT = -1073741210; + +const int STATUS_FILE_IS_OFFLINE = -1073741209; + +const int STATUS_EVALUATION_EXPIRATION = -1073741208; + +const int STATUS_ILLEGAL_DLL_RELOCATION = -1073741207; + +const int STATUS_LICENSE_VIOLATION = -1073741206; + +const int STATUS_DLL_INIT_FAILED_LOGOFF = -1073741205; + +const int STATUS_DRIVER_UNABLE_TO_LOAD = -1073741204; + +const int STATUS_DFS_UNAVAILABLE = -1073741203; + +const int STATUS_VOLUME_DISMOUNTED = -1073741202; + +const int STATUS_WX86_INTERNAL_ERROR = -1073741201; + +const int STATUS_WX86_FLOAT_STACK_CHECK = -1073741200; + +const int STATUS_VALIDATE_CONTINUE = -1073741199; + +const int STATUS_NO_MATCH = -1073741198; + +const int STATUS_NO_MORE_MATCHES = -1073741197; + +const int STATUS_NOT_A_REPARSE_POINT = -1073741195; + +const int STATUS_IO_REPARSE_TAG_INVALID = -1073741194; + +const int STATUS_IO_REPARSE_TAG_MISMATCH = -1073741193; + +const int STATUS_IO_REPARSE_DATA_INVALID = -1073741192; + +const int STATUS_IO_REPARSE_TAG_NOT_HANDLED = -1073741191; + +const int STATUS_PWD_TOO_LONG = -1073741190; + +const int STATUS_STOWED_EXCEPTION = -1073741189; + +const int STATUS_CONTEXT_STOWED_EXCEPTION = -1073741188; + +const int STATUS_REPARSE_POINT_NOT_RESOLVED = -1073741184; + +const int STATUS_DIRECTORY_IS_A_REPARSE_POINT = -1073741183; + +const int STATUS_RANGE_LIST_CONFLICT = -1073741182; + +const int STATUS_SOURCE_ELEMENT_EMPTY = -1073741181; + +const int STATUS_DESTINATION_ELEMENT_FULL = -1073741180; + +const int STATUS_ILLEGAL_ELEMENT_ADDRESS = -1073741179; + +const int STATUS_MAGAZINE_NOT_PRESENT = -1073741178; + +const int STATUS_REINITIALIZATION_NEEDED = -1073741177; + +const int STATUS_DEVICE_REQUIRES_CLEANING = -2147483000; + +const int STATUS_DEVICE_DOOR_OPEN = -2147482999; + +const int STATUS_ENCRYPTION_FAILED = -1073741174; + +const int STATUS_DECRYPTION_FAILED = -1073741173; + +const int STATUS_RANGE_NOT_FOUND = -1073741172; + +const int STATUS_NO_RECOVERY_POLICY = -1073741171; + +const int STATUS_NO_EFS = -1073741170; + +const int STATUS_WRONG_EFS = -1073741169; + +const int STATUS_NO_USER_KEYS = -1073741168; + +const int STATUS_FILE_NOT_ENCRYPTED = -1073741167; + +const int STATUS_NOT_EXPORT_FORMAT = -1073741166; + +const int STATUS_FILE_ENCRYPTED = -1073741165; + +const int STATUS_WAKE_SYSTEM = 1073742484; + +const int STATUS_WMI_GUID_NOT_FOUND = -1073741163; + +const int STATUS_WMI_INSTANCE_NOT_FOUND = -1073741162; + +const int STATUS_WMI_ITEMID_NOT_FOUND = -1073741161; + +const int STATUS_WMI_TRY_AGAIN = -1073741160; + +const int STATUS_SHARED_POLICY = -1073741159; + +const int STATUS_POLICY_OBJECT_NOT_FOUND = -1073741158; + +const int STATUS_POLICY_ONLY_IN_DS = -1073741157; + +const int STATUS_VOLUME_NOT_UPGRADED = -1073741156; + +const int STATUS_REMOTE_STORAGE_NOT_ACTIVE = -1073741155; + +const int STATUS_REMOTE_STORAGE_MEDIA_ERROR = -1073741154; + +const int STATUS_NO_TRACKING_SERVICE = -1073741153; + +const int STATUS_SERVER_SID_MISMATCH = -1073741152; + +const int STATUS_DS_NO_ATTRIBUTE_OR_VALUE = -1073741151; + +const int STATUS_DS_INVALID_ATTRIBUTE_SYNTAX = -1073741150; + +const int STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED = -1073741149; + +const int STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS = -1073741148; + +const int STATUS_DS_BUSY = -1073741147; + +const int STATUS_DS_UNAVAILABLE = -1073741146; + +const int STATUS_DS_NO_RIDS_ALLOCATED = -1073741145; + +const int STATUS_DS_NO_MORE_RIDS = -1073741144; + +const int STATUS_DS_INCORRECT_ROLE_OWNER = -1073741143; + +const int STATUS_DS_RIDMGR_INIT_ERROR = -1073741142; + +const int STATUS_DS_OBJ_CLASS_VIOLATION = -1073741141; + +const int STATUS_DS_CANT_ON_NON_LEAF = -1073741140; + +const int STATUS_DS_CANT_ON_RDN = -1073741139; + +const int STATUS_DS_CANT_MOD_OBJ_CLASS = -1073741138; + +const int STATUS_DS_CROSS_DOM_MOVE_FAILED = -1073741137; + +const int STATUS_DS_GC_NOT_AVAILABLE = -1073741136; + +const int STATUS_DIRECTORY_SERVICE_REQUIRED = -1073741135; + +const int STATUS_REPARSE_ATTRIBUTE_CONFLICT = -1073741134; + +const int STATUS_CANT_ENABLE_DENY_ONLY = -1073741133; + +const int STATUS_FLOAT_MULTIPLE_FAULTS = -1073741132; + +const int STATUS_FLOAT_MULTIPLE_TRAPS = -1073741131; + +const int STATUS_DEVICE_REMOVED = -1073741130; + +const int STATUS_JOURNAL_DELETE_IN_PROGRESS = -1073741129; + +const int STATUS_JOURNAL_NOT_ACTIVE = -1073741128; + +const int STATUS_NOINTERFACE = -1073741127; + +const int STATUS_DS_RIDMGR_DISABLED = -1073741126; + +const int STATUS_DS_ADMIN_LIMIT_EXCEEDED = -1073741119; + +const int STATUS_DRIVER_FAILED_SLEEP = -1073741118; + +const int STATUS_MUTUAL_AUTHENTICATION_FAILED = -1073741117; + +const int STATUS_CORRUPT_SYSTEM_FILE = -1073741116; + +const int STATUS_DATATYPE_MISALIGNMENT_ERROR = -1073741115; + +const int STATUS_WMI_READ_ONLY = -1073741114; + +const int STATUS_WMI_SET_FAILURE = -1073741113; + +const int STATUS_COMMITMENT_MINIMUM = -1073741112; + +const int STATUS_REG_NAT_CONSUMPTION = -1073741111; + +const int STATUS_TRANSPORT_FULL = -1073741110; + +const int STATUS_DS_SAM_INIT_FAILURE = -1073741109; + +const int STATUS_ONLY_IF_CONNECTED = -1073741108; + +const int STATUS_DS_SENSITIVE_GROUP_VIOLATION = -1073741107; + +const int STATUS_PNP_RESTART_ENUMERATION = -1073741106; + +const int STATUS_JOURNAL_ENTRY_DELETED = -1073741105; + +const int STATUS_DS_CANT_MOD_PRIMARYGROUPID = -1073741104; + +const int STATUS_SYSTEM_IMAGE_BAD_SIGNATURE = -1073741103; + +const int STATUS_PNP_REBOOT_REQUIRED = -1073741102; + +const int STATUS_POWER_STATE_INVALID = -1073741101; + +const int STATUS_DS_INVALID_GROUP_TYPE = -1073741100; + +const int STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = -1073741099; + +const int STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = -1073741098; + +const int STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = -1073741097; + +const int STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = -1073741096; + +const int STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = -1073741095; + +const int STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = -1073741094; + +const int STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = -1073741093; + +const int STATUS_DS_HAVE_PRIMARY_MEMBERS = -1073741092; + +const int STATUS_WMI_NOT_SUPPORTED = -1073741091; + +const int STATUS_INSUFFICIENT_POWER = -1073741090; + +const int STATUS_SAM_NEED_BOOTKEY_PASSWORD = -1073741089; + +const int STATUS_SAM_NEED_BOOTKEY_FLOPPY = -1073741088; + +const int STATUS_DS_CANT_START = -1073741087; + +const int STATUS_DS_INIT_FAILURE = -1073741086; + +const int STATUS_SAM_INIT_FAILURE = -1073741085; + +const int STATUS_DS_GC_REQUIRED = -1073741084; + +const int STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = -1073741083; + +const int STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS = -1073741082; + +const int STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = -1073741081; + +const int STATUS_MULTIPLE_FAULT_VIOLATION = -1073741080; + +const int STATUS_CURRENT_DOMAIN_NOT_ALLOWED = -1073741079; + +const int STATUS_CANNOT_MAKE = -1073741078; + +const int STATUS_SYSTEM_SHUTDOWN = -1073741077; + +const int STATUS_DS_INIT_FAILURE_CONSOLE = -1073741076; + +const int STATUS_DS_SAM_INIT_FAILURE_CONSOLE = -1073741075; + +const int STATUS_UNFINISHED_CONTEXT_DELETED = -1073741074; + +const int STATUS_NO_TGT_REPLY = -1073741073; + +const int STATUS_OBJECTID_NOT_FOUND = -1073741072; + +const int STATUS_NO_IP_ADDRESSES = -1073741071; + +const int STATUS_WRONG_CREDENTIAL_HANDLE = -1073741070; + +const int STATUS_CRYPTO_SYSTEM_INVALID = -1073741069; + +const int STATUS_MAX_REFERRALS_EXCEEDED = -1073741068; + +const int STATUS_MUST_BE_KDC = -1073741067; + +const int STATUS_STRONG_CRYPTO_NOT_SUPPORTED = -1073741066; + +const int STATUS_TOO_MANY_PRINCIPALS = -1073741065; + +const int STATUS_NO_PA_DATA = -1073741064; + +const int STATUS_PKINIT_NAME_MISMATCH = -1073741063; + +const int STATUS_SMARTCARD_LOGON_REQUIRED = -1073741062; + +const int STATUS_KDC_INVALID_REQUEST = -1073741061; + +const int STATUS_KDC_UNABLE_TO_REFER = -1073741060; + +const int STATUS_KDC_UNKNOWN_ETYPE = -1073741059; + +const int STATUS_SHUTDOWN_IN_PROGRESS = -1073741058; + +const int STATUS_SERVER_SHUTDOWN_IN_PROGRESS = -1073741057; + +const int STATUS_NOT_SUPPORTED_ON_SBS = -1073741056; + +const int STATUS_WMI_GUID_DISCONNECTED = -1073741055; + +const int STATUS_WMI_ALREADY_DISABLED = -1073741054; + +const int STATUS_WMI_ALREADY_ENABLED = -1073741053; + +const int STATUS_MFT_TOO_FRAGMENTED = -1073741052; + +const int STATUS_COPY_PROTECTION_FAILURE = -1073741051; + +const int STATUS_CSS_AUTHENTICATION_FAILURE = -1073741050; + +const int STATUS_CSS_KEY_NOT_PRESENT = -1073741049; + +const int STATUS_CSS_KEY_NOT_ESTABLISHED = -1073741048; + +const int STATUS_CSS_SCRAMBLED_SECTOR = -1073741047; + +const int STATUS_CSS_REGION_MISMATCH = -1073741046; + +const int STATUS_CSS_RESETS_EXHAUSTED = -1073741045; + +const int STATUS_PASSWORD_CHANGE_REQUIRED = -1073741044; + +const int STATUS_LOST_MODE_LOGON_RESTRICTION = -1073741043; + +const int STATUS_PKINIT_FAILURE = -1073741024; + +const int STATUS_SMARTCARD_SUBSYSTEM_FAILURE = -1073741023; + +const int STATUS_NO_KERB_KEY = -1073741022; + +const int STATUS_HOST_DOWN = -1073740976; + +const int STATUS_UNSUPPORTED_PREAUTH = -1073740975; + +const int STATUS_EFS_ALG_BLOB_TOO_BIG = -1073740974; + +const int STATUS_PORT_NOT_SET = -1073740973; + +const int STATUS_DEBUGGER_INACTIVE = -1073740972; + +const int STATUS_DS_VERSION_CHECK_FAILURE = -1073740971; + +const int STATUS_AUDITING_DISABLED = -1073740970; + +const int STATUS_PRENT4_MACHINE_ACCOUNT = -1073740969; + +const int STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = -1073740968; + +const int STATUS_INVALID_IMAGE_WIN_32 = -1073740967; + +const int STATUS_INVALID_IMAGE_WIN_64 = -1073740966; + +const int STATUS_BAD_BINDINGS = -1073740965; + +const int STATUS_NETWORK_SESSION_EXPIRED = -1073740964; + +const int STATUS_APPHELP_BLOCK = -1073740963; + +const int STATUS_ALL_SIDS_FILTERED = -1073740962; + +const int STATUS_NOT_SAFE_MODE_DRIVER = -1073740961; + +const int STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT = -1073740959; + +const int STATUS_ACCESS_DISABLED_BY_POLICY_PATH = -1073740958; + +const int STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER = -1073740957; + +const int STATUS_ACCESS_DISABLED_BY_POLICY_OTHER = -1073740956; + +const int STATUS_FAILED_DRIVER_ENTRY = -1073740955; + +const int STATUS_DEVICE_ENUMERATION_ERROR = -1073740954; + +const int STATUS_MOUNT_POINT_NOT_RESOLVED = -1073740952; + +const int STATUS_INVALID_DEVICE_OBJECT_PARAMETER = -1073740951; + +const int STATUS_MCA_OCCURED = -1073740950; + +const int STATUS_DRIVER_BLOCKED_CRITICAL = -1073740949; + +const int STATUS_DRIVER_BLOCKED = -1073740948; + +const int STATUS_DRIVER_DATABASE_ERROR = -1073740947; + +const int STATUS_SYSTEM_HIVE_TOO_LARGE = -1073740946; + +const int STATUS_INVALID_IMPORT_OF_NON_DLL = -1073740945; + +const int STATUS_DS_SHUTTING_DOWN = 1073742704; + +const int STATUS_NO_SECRETS = -1073740943; + +const int STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = -1073740942; + +const int STATUS_FAILED_STACK_SWITCH = -1073740941; + +const int STATUS_HEAP_CORRUPTION = -1073740940; + +const int STATUS_SMARTCARD_WRONG_PIN = -1073740928; + +const int STATUS_SMARTCARD_CARD_BLOCKED = -1073740927; + +const int STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED = -1073740926; + +const int STATUS_SMARTCARD_NO_CARD = -1073740925; + +const int STATUS_SMARTCARD_NO_KEY_CONTAINER = -1073740924; + +const int STATUS_SMARTCARD_NO_CERTIFICATE = -1073740923; + +const int STATUS_SMARTCARD_NO_KEYSET = -1073740922; + +const int STATUS_SMARTCARD_IO_ERROR = -1073740921; + +const int STATUS_DOWNGRADE_DETECTED = -1073740920; + +const int STATUS_SMARTCARD_CERT_REVOKED = -1073740919; + +const int STATUS_ISSUING_CA_UNTRUSTED = -1073740918; + +const int STATUS_REVOCATION_OFFLINE_C = -1073740917; + +const int STATUS_PKINIT_CLIENT_FAILURE = -1073740916; + +const int STATUS_SMARTCARD_CERT_EXPIRED = -1073740915; + +const int STATUS_DRIVER_FAILED_PRIOR_UNLOAD = -1073740914; + +const int STATUS_SMARTCARD_SILENT_CONTEXT = -1073740913; + +const int STATUS_PER_USER_TRUST_QUOTA_EXCEEDED = -1073740799; + +const int STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED = -1073740798; + +const int STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED = -1073740797; + +const int STATUS_DS_NAME_NOT_UNIQUE = -1073740796; + +const int STATUS_DS_DUPLICATE_ID_FOUND = -1073740795; + +const int STATUS_DS_GROUP_CONVERSION_ERROR = -1073740794; + +const int STATUS_VOLSNAP_PREPARE_HIBERNATE = -1073740793; + +const int STATUS_USER2USER_REQUIRED = -1073740792; + +const int STATUS_STACK_BUFFER_OVERRUN = -1073740791; + +const int STATUS_NO_S4U_PROT_SUPPORT = -1073740790; + +const int STATUS_CROSSREALM_DELEGATION_FAILURE = -1073740789; + +const int STATUS_REVOCATION_OFFLINE_KDC = -1073740788; + +const int STATUS_ISSUING_CA_UNTRUSTED_KDC = -1073740787; + +const int STATUS_KDC_CERT_EXPIRED = -1073740786; + +const int STATUS_KDC_CERT_REVOKED = -1073740785; + +const int STATUS_PARAMETER_QUOTA_EXCEEDED = -1073740784; + +const int STATUS_HIBERNATION_FAILURE = -1073740783; + +const int STATUS_DELAY_LOAD_FAILED = -1073740782; + +const int STATUS_AUTHENTICATION_FIREWALL_FAILED = -1073740781; + +const int STATUS_VDM_DISALLOWED = -1073740780; + +const int STATUS_HUNG_DISPLAY_DRIVER_THREAD = -1073740779; + +const int STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = + -1073740778; + +const int STATUS_INVALID_CRUNTIME_PARAMETER = -1073740777; + +const int STATUS_NTLM_BLOCKED = -1073740776; + +const int STATUS_DS_SRC_SID_EXISTS_IN_FOREST = -1073740775; + +const int STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST = -1073740774; + +const int STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST = -1073740773; + +const int STATUS_INVALID_USER_PRINCIPAL_NAME = -1073740772; + +const int STATUS_FATAL_USER_CALLBACK_EXCEPTION = -1073740771; + +const int STATUS_ASSERTION_FAILURE = -1073740768; + +const int STATUS_VERIFIER_STOP = -1073740767; + +const int STATUS_CALLBACK_POP_STACK = -1073740765; + +const int STATUS_INCOMPATIBLE_DRIVER_BLOCKED = -1073740764; + +const int STATUS_HIVE_UNLOADED = -1073740763; + +const int STATUS_COMPRESSION_DISABLED = -1073740762; + +const int STATUS_FILE_SYSTEM_LIMITATION = -1073740761; + +const int STATUS_INVALID_IMAGE_HASH = -1073740760; + +const int STATUS_NOT_CAPABLE = -1073740759; + +const int STATUS_REQUEST_OUT_OF_SEQUENCE = -1073740758; + +const int STATUS_IMPLEMENTATION_LIMIT = -1073740757; + +const int STATUS_ELEVATION_REQUIRED = -1073740756; + +const int STATUS_NO_SECURITY_CONTEXT = -1073740755; + +const int STATUS_PKU2U_CERT_FAILURE = -1073740753; + +const int STATUS_BEYOND_VDL = -1073740750; + +const int STATUS_ENCOUNTERED_WRITE_IN_PROGRESS = -1073740749; + +const int STATUS_PTE_CHANGED = -1073740748; + +const int STATUS_PURGE_FAILED = -1073740747; + +const int STATUS_CRED_REQUIRES_CONFIRMATION = -1073740736; + +const int STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE = -1073740735; + +const int STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER = -1073740734; + +const int STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = -1073740733; + +const int STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE = -1073740732; + +const int STATUS_CS_ENCRYPTION_FILE_NOT_CSE = -1073740731; + +const int STATUS_INVALID_LABEL = -1073740730; + +const int STATUS_DRIVER_PROCESS_TERMINATED = -1073740720; + +const int STATUS_AMBIGUOUS_SYSTEM_DEVICE = -1073740719; + +const int STATUS_SYSTEM_DEVICE_NOT_FOUND = -1073740718; + +const int STATUS_RESTART_BOOT_APPLICATION = -1073740717; + +const int STATUS_INSUFFICIENT_NVRAM_RESOURCES = -1073740716; + +const int STATUS_INVALID_SESSION = -1073740715; + +const int STATUS_THREAD_ALREADY_IN_SESSION = -1073740714; + +const int STATUS_THREAD_NOT_IN_SESSION = -1073740713; + +const int STATUS_INVALID_WEIGHT = -1073740712; + +const int STATUS_REQUEST_PAUSED = -1073740711; + +const int STATUS_NO_RANGES_PROCESSED = -1073740704; + +const int STATUS_DISK_RESOURCES_EXHAUSTED = -1073740703; + +const int STATUS_NEEDS_REMEDIATION = -1073740702; + +const int STATUS_DEVICE_FEATURE_NOT_SUPPORTED = -1073740701; + +const int STATUS_DEVICE_UNREACHABLE = -1073740700; + +const int STATUS_INVALID_TOKEN = -1073740699; + +const int STATUS_SERVER_UNAVAILABLE = -1073740698; + +const int STATUS_FILE_NOT_AVAILABLE = -1073740697; + +const int STATUS_DEVICE_INSUFFICIENT_RESOURCES = -1073740696; + +const int STATUS_PACKAGE_UPDATING = -1073740695; + +const int STATUS_NOT_READ_FROM_COPY = -1073740694; + +const int STATUS_FT_WRITE_FAILURE = -1073740693; + +const int STATUS_FT_DI_SCAN_REQUIRED = -1073740692; + +const int STATUS_OBJECT_NOT_EXTERNALLY_BACKED = -1073740691; + +const int STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN = -1073740690; + +const int STATUS_COMPRESSION_NOT_BENEFICIAL = -1073740689; + +const int STATUS_DATA_CHECKSUM_ERROR = -1073740688; + +const int STATUS_INTERMIXED_KERNEL_EA_OPERATION = -1073740687; + +const int STATUS_TRIM_READ_ZERO_NOT_SUPPORTED = -1073740686; + +const int STATUS_TOO_MANY_SEGMENT_DESCRIPTORS = -1073740685; + +const int STATUS_INVALID_OFFSET_ALIGNMENT = -1073740684; + +const int STATUS_INVALID_FIELD_IN_PARAMETER_LIST = -1073740683; + +const int STATUS_OPERATION_IN_PROGRESS = -1073740682; + +const int STATUS_INVALID_INITIATOR_TARGET_PATH = -1073740681; + +const int STATUS_SCRUB_DATA_DISABLED = -1073740680; + +const int STATUS_NOT_REDUNDANT_STORAGE = -1073740679; + +const int STATUS_RESIDENT_FILE_NOT_SUPPORTED = -1073740678; + +const int STATUS_COMPRESSED_FILE_NOT_SUPPORTED = -1073740677; + +const int STATUS_DIRECTORY_NOT_SUPPORTED = -1073740676; + +const int STATUS_IO_OPERATION_TIMEOUT = -1073740675; + +const int STATUS_SYSTEM_NEEDS_REMEDIATION = -1073740674; + +const int STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN = -1073740673; + +const int STATUS_SHARE_UNAVAILABLE = -1073740672; + +const int STATUS_APISET_NOT_HOSTED = -1073740671; + +const int STATUS_APISET_NOT_PRESENT = -1073740670; + +const int STATUS_DEVICE_HARDWARE_ERROR = -1073740669; + +const int STATUS_FIRMWARE_SLOT_INVALID = -1073740668; + +const int STATUS_FIRMWARE_IMAGE_INVALID = -1073740667; + +const int STATUS_STORAGE_TOPOLOGY_ID_MISMATCH = -1073740666; + +const int STATUS_WIM_NOT_BOOTABLE = -1073740665; + +const int STATUS_BLOCKED_BY_PARENTAL_CONTROLS = -1073740664; + +const int STATUS_NEEDS_REGISTRATION = -1073740663; + +const int STATUS_QUOTA_ACTIVITY = -1073740662; + +const int STATUS_CALLBACK_INVOKE_INLINE = -1073740661; + +const int STATUS_BLOCK_TOO_MANY_REFERENCES = -1073740660; + +const int STATUS_MARKED_TO_DISALLOW_WRITES = -1073740659; + +const int STATUS_NETWORK_ACCESS_DENIED_EDP = -1073740658; + +const int STATUS_ENCLAVE_FAILURE = -1073740657; + +const int STATUS_PNP_NO_COMPAT_DRIVERS = -1073740656; + +const int STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND = -1073740655; + +const int STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND = -1073740654; + +const int STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE = -1073740653; + +const int STATUS_PNP_FUNCTION_DRIVER_REQUIRED = -1073740652; + +const int STATUS_PNP_DEVICE_CONFIGURATION_PENDING = -1073740651; + +const int STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL = -1073740650; + +const int STATUS_PACKAGE_NOT_AVAILABLE = -1073740649; + +const int STATUS_DEVICE_IN_MAINTENANCE = -1073740647; + +const int STATUS_NOT_SUPPORTED_ON_DAX = -1073740646; + +const int STATUS_FREE_SPACE_TOO_FRAGMENTED = -1073740645; + +const int STATUS_DAX_MAPPING_EXISTS = -1073740644; + +const int STATUS_CHILD_PROCESS_BLOCKED = -1073740643; + +const int STATUS_STORAGE_LOST_DATA_PERSISTENCE = -1073740642; + +const int STATUS_VRF_CFG_ENABLED = -1073740641; + +const int STATUS_PARTITION_TERMINATING = -1073740640; + +const int STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED = -1073740639; + +const int STATUS_ENCLAVE_VIOLATION = -1073740638; + +const int STATUS_FILE_PROTECTED_UNDER_DPL = -1073740637; + +const int STATUS_VOLUME_NOT_CLUSTER_ALIGNED = -1073740636; + +const int STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND = -1073740635; + +const int STATUS_APPX_FILE_NOT_ENCRYPTED = -1073740634; + +const int STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED = -1073740633; + +const int STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET = -1073740632; + +const int STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE = -1073740631; + +const int STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER = -1073740630; + +const int STATUS_FT_READ_FAILURE = -1073740629; + +const int STATUS_PATCH_CONFLICT = -1073740628; + +const int STATUS_STORAGE_RESERVE_ID_INVALID = -1073740627; + +const int STATUS_STORAGE_RESERVE_DOES_NOT_EXIST = -1073740626; + +const int STATUS_STORAGE_RESERVE_ALREADY_EXISTS = -1073740625; + +const int STATUS_STORAGE_RESERVE_NOT_EMPTY = -1073740624; + +const int STATUS_NOT_A_DAX_VOLUME = -1073740623; + +const int STATUS_NOT_DAX_MAPPABLE = -1073740622; + +const int STATUS_CASE_DIFFERING_NAMES_IN_DIR = -1073740621; + +const int STATUS_FILE_NOT_SUPPORTED = -1073740620; + +const int STATUS_NOT_SUPPORTED_WITH_BTT = -1073740619; + +const int STATUS_ENCRYPTION_DISABLED = -1073740618; + +const int STATUS_ENCRYPTING_METADATA_DISALLOWED = -1073740617; + +const int STATUS_CANT_CLEAR_ENCRYPTION_FLAG = -1073740616; + +const int STATUS_INVALID_TASK_NAME = -1073740544; + +const int STATUS_INVALID_TASK_INDEX = -1073740543; + +const int STATUS_THREAD_ALREADY_IN_TASK = -1073740542; + +const int STATUS_CALLBACK_BYPASS = -1073740541; + +const int STATUS_UNDEFINED_SCOPE = -1073740540; + +const int STATUS_INVALID_CAP = -1073740539; + +const int STATUS_NOT_GUI_PROCESS = -1073740538; + +const int STATUS_DEVICE_HUNG = -1073740537; + +const int STATUS_CONTAINER_ASSIGNED = -1073740536; + +const int STATUS_JOB_NO_CONTAINER = -1073740535; + +const int STATUS_DEVICE_UNRESPONSIVE = -1073740534; + +const int STATUS_REPARSE_POINT_ENCOUNTERED = -1073740533; + +const int STATUS_ATTRIBUTE_NOT_PRESENT = -1073740532; + +const int STATUS_NOT_A_TIERED_VOLUME = -1073740531; + +const int STATUS_ALREADY_HAS_STREAM_ID = -1073740530; + +const int STATUS_JOB_NOT_EMPTY = -1073740529; + +const int STATUS_ALREADY_INITIALIZED = -1073740528; + +const int STATUS_ENCLAVE_NOT_TERMINATED = -1073740527; + +const int STATUS_ENCLAVE_IS_TERMINATING = -1073740526; + +const int STATUS_SMB1_NOT_AVAILABLE = -1073740525; + +const int STATUS_SMR_GARBAGE_COLLECTION_REQUIRED = -1073740524; + +const int STATUS_INTERRUPTED = -1073740523; + +const int STATUS_THREAD_NOT_RUNNING = -1073740522; + +const int STATUS_FAIL_FAST_EXCEPTION = -1073740286; + +const int STATUS_IMAGE_CERT_REVOKED = -1073740285; + +const int STATUS_DYNAMIC_CODE_BLOCKED = -1073740284; + +const int STATUS_IMAGE_CERT_EXPIRED = -1073740283; + +const int STATUS_STRICT_CFG_VIOLATION = -1073740282; + +const int STATUS_SET_CONTEXT_DENIED = -1073740278; + +const int STATUS_CROSS_PARTITION_VIOLATION = -1073740277; + +const int STATUS_PORT_CLOSED = -1073740032; + +const int STATUS_MESSAGE_LOST = -1073740031; + +const int STATUS_INVALID_MESSAGE = -1073740030; + +const int STATUS_REQUEST_CANCELED = -1073740029; + +const int STATUS_RECURSIVE_DISPATCH = -1073740028; + +const int STATUS_LPC_RECEIVE_BUFFER_EXPECTED = -1073740027; + +const int STATUS_LPC_INVALID_CONNECTION_USAGE = -1073740026; + +const int STATUS_LPC_REQUESTS_NOT_ALLOWED = -1073740025; + +const int STATUS_RESOURCE_IN_USE = -1073740024; + +const int STATUS_HARDWARE_MEMORY_ERROR = -1073740023; + +const int STATUS_THREADPOOL_HANDLE_EXCEPTION = -1073740022; + +const int STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED = -1073740021; + +const int STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED = + -1073740020; + +const int STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED = -1073740019; + +const int STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED = -1073740018; + +const int STATUS_THREADPOOL_RELEASED_DURING_OPERATION = -1073740017; + +const int STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING = -1073740016; + +const int STATUS_APC_RETURNED_WHILE_IMPERSONATING = -1073740015; + +const int STATUS_PROCESS_IS_PROTECTED = -1073740014; + +const int STATUS_MCA_EXCEPTION = -1073740013; + +const int STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE = -1073740012; + +const int STATUS_SYMLINK_CLASS_DISABLED = -1073740011; + +const int STATUS_INVALID_IDN_NORMALIZATION = -1073740010; + +const int STATUS_NO_UNICODE_TRANSLATION = -1073740009; + +const int STATUS_ALREADY_REGISTERED = -1073740008; + +const int STATUS_CONTEXT_MISMATCH = -1073740007; + +const int STATUS_PORT_ALREADY_HAS_COMPLETION_LIST = -1073740006; + +const int STATUS_CALLBACK_RETURNED_THREAD_PRIORITY = -1073740005; + +const int STATUS_INVALID_THREAD = -1073740004; + +const int STATUS_CALLBACK_RETURNED_TRANSACTION = -1073740003; + +const int STATUS_CALLBACK_RETURNED_LDR_LOCK = -1073740002; + +const int STATUS_CALLBACK_RETURNED_LANG = -1073740001; + +const int STATUS_CALLBACK_RETURNED_PRI_BACK = -1073740000; + +const int STATUS_CALLBACK_RETURNED_THREAD_AFFINITY = -1073739999; + +const int STATUS_LPC_HANDLE_COUNT_EXCEEDED = -1073739998; + +const int STATUS_EXECUTABLE_MEMORY_WRITE = -1073739997; + +const int STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE = -1073739996; + +const int STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE = -1073739995; + +const int STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE = -1073739994; + +const int STATUS_DISK_REPAIR_DISABLED = -1073739776; + +const int STATUS_DS_DOMAIN_RENAME_IN_PROGRESS = -1073739775; + +const int STATUS_DISK_QUOTA_EXCEEDED = -1073739774; + +const int STATUS_DATA_LOST_REPAIR = -2147481597; + +const int STATUS_CONTENT_BLOCKED = -1073739772; + +const int STATUS_BAD_CLUSTERS = -1073739771; + +const int STATUS_VOLUME_DIRTY = -1073739770; + +const int STATUS_DISK_REPAIR_REDIRECTED = 1073743879; + +const int STATUS_DISK_REPAIR_UNSUCCESSFUL = -1073739768; + +const int STATUS_CORRUPT_LOG_OVERFULL = -1073739767; + +const int STATUS_CORRUPT_LOG_CORRUPTED = -1073739766; + +const int STATUS_CORRUPT_LOG_UNAVAILABLE = -1073739765; + +const int STATUS_CORRUPT_LOG_DELETED_FULL = -1073739764; + +const int STATUS_CORRUPT_LOG_CLEARED = -1073739763; + +const int STATUS_ORPHAN_NAME_EXHAUSTED = -1073739762; + +const int STATUS_PROACTIVE_SCAN_IN_PROGRESS = -1073739761; + +const int STATUS_ENCRYPTED_IO_NOT_POSSIBLE = -1073739760; + +const int STATUS_CORRUPT_LOG_UPLEVEL_RECORDS = -1073739759; + +const int STATUS_FILE_CHECKED_OUT = -1073739519; + +const int STATUS_CHECKOUT_REQUIRED = -1073739518; + +const int STATUS_BAD_FILE_TYPE = -1073739517; + +const int STATUS_FILE_TOO_LARGE = -1073739516; + +const int STATUS_FORMS_AUTH_REQUIRED = -1073739515; + +const int STATUS_VIRUS_INFECTED = -1073739514; + +const int STATUS_VIRUS_DELETED = -1073739513; + +const int STATUS_BAD_MCFG_TABLE = -1073739512; + +const int STATUS_CANNOT_BREAK_OPLOCK = -1073739511; + +const int STATUS_BAD_KEY = -1073739510; + +const int STATUS_BAD_DATA = -1073739509; + +const int STATUS_NO_KEY = -1073739508; + +const int STATUS_FILE_HANDLE_REVOKED = -1073739504; + +const int STATUS_WOW_ASSERTION = -1073702760; + +const int STATUS_INVALID_SIGNATURE = -1073700864; + +const int STATUS_HMAC_NOT_SUPPORTED = -1073700863; + +const int STATUS_AUTH_TAG_MISMATCH = -1073700862; + +const int STATUS_INVALID_STATE_TRANSITION = -1073700861; + +const int STATUS_INVALID_KERNEL_INFO_VERSION = -1073700860; + +const int STATUS_INVALID_PEP_INFO_VERSION = -1073700859; + +const int STATUS_HANDLE_REVOKED = -1073700858; + +const int STATUS_EOF_ON_GHOSTED_RANGE = -1073700857; + +const int STATUS_IPSEC_QUEUE_OVERFLOW = -1073700848; + +const int STATUS_ND_QUEUE_OVERFLOW = -1073700847; + +const int STATUS_HOPLIMIT_EXCEEDED = -1073700846; + +const int STATUS_PROTOCOL_NOT_SUPPORTED = -1073700845; + +const int STATUS_FASTPATH_REJECTED = -1073700844; + +const int STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = -1073700736; + +const int STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = -1073700735; + +const int STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = -1073700734; + +const int STATUS_XML_PARSE_ERROR = -1073700733; + +const int STATUS_XMLDSIG_ERROR = -1073700732; + +const int STATUS_WRONG_COMPARTMENT = -1073700731; + +const int STATUS_AUTHIP_FAILURE = -1073700730; + +const int STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = -1073700729; + +const int STATUS_DS_OID_NOT_FOUND = -1073700728; + +const int STATUS_INCORRECT_ACCOUNT_TYPE = -1073700727; + +const int STATUS_HASH_NOT_SUPPORTED = -1073700608; + +const int STATUS_HASH_NOT_PRESENT = -1073700607; + +const int STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED = -1073700575; + +const int STATUS_GPIO_CLIENT_INFORMATION_INVALID = -1073700574; + +const int STATUS_GPIO_VERSION_NOT_SUPPORTED = -1073700573; + +const int STATUS_GPIO_INVALID_REGISTRATION_PACKET = -1073700572; + +const int STATUS_GPIO_OPERATION_DENIED = -1073700571; + +const int STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE = -1073700570; + +const int STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED = -2147442393; + +const int STATUS_CANNOT_SWITCH_RUNLEVEL = -1073700543; + +const int STATUS_INVALID_RUNLEVEL_SETTING = -1073700542; + +const int STATUS_RUNLEVEL_SWITCH_TIMEOUT = -1073700541; + +const int STATUS_SERVICES_FAILED_AUTOSTART = 1073783108; + +const int STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT = -1073700539; + +const int STATUS_RUNLEVEL_SWITCH_IN_PROGRESS = -1073700538; + +const int STATUS_NOT_APPCONTAINER = -1073700352; + +const int STATUS_NOT_SUPPORTED_IN_APPCONTAINER = -1073700351; + +const int STATUS_INVALID_PACKAGE_SID_LENGTH = -1073700350; + +const int STATUS_LPAC_ACCESS_DENIED = -1073700349; + +const int STATUS_ADMINLESS_ACCESS_DENIED = -1073700348; + +const int STATUS_APP_DATA_NOT_FOUND = -1073700223; + +const int STATUS_APP_DATA_EXPIRED = -1073700222; + +const int STATUS_APP_DATA_CORRUPT = -1073700221; + +const int STATUS_APP_DATA_LIMIT_EXCEEDED = -1073700220; + +const int STATUS_APP_DATA_REBOOT_REQUIRED = -1073700219; + +const int STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED = -1073700191; + +const int STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED = -1073700190; + +const int STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED = -1073700189; + +const int STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED = -1073700188; + +const int STATUS_WOF_WIM_HEADER_CORRUPT = -1073700187; + +const int STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT = -1073700186; + +const int STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT = -1073700185; + +const int STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE = -1073689087; + +const int STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT = -1073689086; + +const int STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY = -1073689085; + +const int STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN = -1073689084; + +const int STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION = -1073689083; + +const int STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT = -1073688832; + +const int STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING = -1073688831; + +const int STATUS_CLOUD_FILE_METADATA_CORRUPT = -1073688830; + +const int STATUS_CLOUD_FILE_METADATA_TOO_LARGE = -1073688829; + +const int STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE = -2147430652; + +const int STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS = -2147430651; + +const int STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED = -1073688826; + +const int STATUS_NOT_A_CLOUD_FILE = -1073688825; + +const int STATUS_CLOUD_FILE_NOT_IN_SYNC = -1073688824; + +const int STATUS_CLOUD_FILE_ALREADY_CONNECTED = -1073688823; + +const int STATUS_CLOUD_FILE_NOT_SUPPORTED = -1073688822; + +const int STATUS_CLOUD_FILE_INVALID_REQUEST = -1073688821; + +const int STATUS_CLOUD_FILE_READ_ONLY_VOLUME = -1073688820; + +const int STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY = -1073688819; + +const int STATUS_CLOUD_FILE_VALIDATION_FAILED = -1073688818; + +const int STATUS_CLOUD_FILE_AUTHENTICATION_FAILED = -1073688817; + +const int STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES = -1073688816; + +const int STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE = -1073688815; + +const int STATUS_CLOUD_FILE_UNSUCCESSFUL = -1073688814; + +const int STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT = -1073688813; + +const int STATUS_CLOUD_FILE_IN_USE = -1073688812; + +const int STATUS_CLOUD_FILE_PINNED = -1073688811; + +const int STATUS_CLOUD_FILE_REQUEST_ABORTED = -1073688810; + +const int STATUS_CLOUD_FILE_PROPERTY_CORRUPT = -1073688809; + +const int STATUS_CLOUD_FILE_ACCESS_DENIED = -1073688808; + +const int STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS = -1073688807; + +const int STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT = -1073688806; + +const int STATUS_CLOUD_FILE_REQUEST_CANCELED = -1073688805; + +const int STATUS_CLOUD_FILE_PROVIDER_TERMINATED = -1073688803; + +const int STATUS_NOT_A_CLOUD_SYNC_ROOT = -1073688802; + +const int STATUS_CLOUD_FILE_REQUEST_TIMEOUT = -1073688801; + +const int DBG_NO_STATE_CHANGE = -1073676287; + +const int DBG_APP_NOT_IDLE = -1073676286; + +const int RPC_NT_INVALID_STRING_BINDING = -1073610751; + +const int RPC_NT_WRONG_KIND_OF_BINDING = -1073610750; + +const int RPC_NT_INVALID_BINDING = -1073610749; + +const int RPC_NT_PROTSEQ_NOT_SUPPORTED = -1073610748; + +const int RPC_NT_INVALID_RPC_PROTSEQ = -1073610747; + +const int RPC_NT_INVALID_STRING_UUID = -1073610746; + +const int RPC_NT_INVALID_ENDPOINT_FORMAT = -1073610745; + +const int RPC_NT_INVALID_NET_ADDR = -1073610744; + +const int RPC_NT_NO_ENDPOINT_FOUND = -1073610743; + +const int RPC_NT_INVALID_TIMEOUT = -1073610742; + +const int RPC_NT_OBJECT_NOT_FOUND = -1073610741; + +const int RPC_NT_ALREADY_REGISTERED = -1073610740; + +const int RPC_NT_TYPE_ALREADY_REGISTERED = -1073610739; + +const int RPC_NT_ALREADY_LISTENING = -1073610738; + +const int RPC_NT_NO_PROTSEQS_REGISTERED = -1073610737; + +const int RPC_NT_NOT_LISTENING = -1073610736; + +const int RPC_NT_UNKNOWN_MGR_TYPE = -1073610735; + +const int RPC_NT_UNKNOWN_IF = -1073610734; + +const int RPC_NT_NO_BINDINGS = -1073610733; + +const int RPC_NT_NO_PROTSEQS = -1073610732; + +const int RPC_NT_CANT_CREATE_ENDPOINT = -1073610731; + +const int RPC_NT_OUT_OF_RESOURCES = -1073610730; + +const int RPC_NT_SERVER_UNAVAILABLE = -1073610729; + +const int RPC_NT_SERVER_TOO_BUSY = -1073610728; + +const int RPC_NT_INVALID_NETWORK_OPTIONS = -1073610727; + +const int RPC_NT_NO_CALL_ACTIVE = -1073610726; + +const int RPC_NT_CALL_FAILED = -1073610725; + +const int RPC_NT_CALL_FAILED_DNE = -1073610724; + +const int RPC_NT_PROTOCOL_ERROR = -1073610723; + +const int RPC_NT_UNSUPPORTED_TRANS_SYN = -1073610721; + +const int RPC_NT_UNSUPPORTED_TYPE = -1073610719; + +const int RPC_NT_INVALID_TAG = -1073610718; + +const int RPC_NT_INVALID_BOUND = -1073610717; + +const int RPC_NT_NO_ENTRY_NAME = -1073610716; + +const int RPC_NT_INVALID_NAME_SYNTAX = -1073610715; + +const int RPC_NT_UNSUPPORTED_NAME_SYNTAX = -1073610714; + +const int RPC_NT_UUID_NO_ADDRESS = -1073610712; + +const int RPC_NT_DUPLICATE_ENDPOINT = -1073610711; + +const int RPC_NT_UNKNOWN_AUTHN_TYPE = -1073610710; + +const int RPC_NT_MAX_CALLS_TOO_SMALL = -1073610709; + +const int RPC_NT_STRING_TOO_LONG = -1073610708; + +const int RPC_NT_PROTSEQ_NOT_FOUND = -1073610707; + +const int RPC_NT_PROCNUM_OUT_OF_RANGE = -1073610706; + +const int RPC_NT_BINDING_HAS_NO_AUTH = -1073610705; + +const int RPC_NT_UNKNOWN_AUTHN_SERVICE = -1073610704; + +const int RPC_NT_UNKNOWN_AUTHN_LEVEL = -1073610703; + +const int RPC_NT_INVALID_AUTH_IDENTITY = -1073610702; + +const int RPC_NT_UNKNOWN_AUTHZ_SERVICE = -1073610701; + +const int EPT_NT_INVALID_ENTRY = -1073610700; + +const int EPT_NT_CANT_PERFORM_OP = -1073610699; + +const int EPT_NT_NOT_REGISTERED = -1073610698; + +const int RPC_NT_NOTHING_TO_EXPORT = -1073610697; + +const int RPC_NT_INCOMPLETE_NAME = -1073610696; + +const int RPC_NT_INVALID_VERS_OPTION = -1073610695; + +const int RPC_NT_NO_MORE_MEMBERS = -1073610694; + +const int RPC_NT_NOT_ALL_OBJS_UNEXPORTED = -1073610693; + +const int RPC_NT_INTERFACE_NOT_FOUND = -1073610692; + +const int RPC_NT_ENTRY_ALREADY_EXISTS = -1073610691; + +const int RPC_NT_ENTRY_NOT_FOUND = -1073610690; + +const int RPC_NT_NAME_SERVICE_UNAVAILABLE = -1073610689; + +const int RPC_NT_INVALID_NAF_ID = -1073610688; + +const int RPC_NT_CANNOT_SUPPORT = -1073610687; + +const int RPC_NT_NO_CONTEXT_AVAILABLE = -1073610686; + +const int RPC_NT_INTERNAL_ERROR = -1073610685; + +const int RPC_NT_ZERO_DIVIDE = -1073610684; + +const int RPC_NT_ADDRESS_ERROR = -1073610683; + +const int RPC_NT_FP_DIV_ZERO = -1073610682; + +const int RPC_NT_FP_UNDERFLOW = -1073610681; + +const int RPC_NT_FP_OVERFLOW = -1073610680; + +const int RPC_NT_NO_MORE_ENTRIES = -1073545215; + +const int RPC_NT_SS_CHAR_TRANS_OPEN_FAIL = -1073545214; + +const int RPC_NT_SS_CHAR_TRANS_SHORT_FILE = -1073545213; + +const int RPC_NT_SS_IN_NULL_CONTEXT = -1073545212; + +const int RPC_NT_SS_CONTEXT_MISMATCH = -1073545211; + +const int RPC_NT_SS_CONTEXT_DAMAGED = -1073545210; + +const int RPC_NT_SS_HANDLES_MISMATCH = -1073545209; + +const int RPC_NT_SS_CANNOT_GET_CALL_HANDLE = -1073545208; + +const int RPC_NT_NULL_REF_POINTER = -1073545207; + +const int RPC_NT_ENUM_VALUE_OUT_OF_RANGE = -1073545206; + +const int RPC_NT_BYTE_COUNT_TOO_SMALL = -1073545205; + +const int RPC_NT_BAD_STUB_DATA = -1073545204; + +const int RPC_NT_CALL_IN_PROGRESS = -1073610679; + +const int RPC_NT_NO_MORE_BINDINGS = -1073610678; + +const int RPC_NT_GROUP_MEMBER_NOT_FOUND = -1073610677; + +const int EPT_NT_CANT_CREATE = -1073610676; + +const int RPC_NT_INVALID_OBJECT = -1073610675; + +const int RPC_NT_NO_INTERFACES = -1073610673; + +const int RPC_NT_CALL_CANCELLED = -1073610672; + +const int RPC_NT_BINDING_INCOMPLETE = -1073610671; + +const int RPC_NT_COMM_FAILURE = -1073610670; + +const int RPC_NT_UNSUPPORTED_AUTHN_LEVEL = -1073610669; + +const int RPC_NT_NO_PRINC_NAME = -1073610668; + +const int RPC_NT_NOT_RPC_ERROR = -1073610667; + +const int RPC_NT_UUID_LOCAL_ONLY = 1073872982; + +const int RPC_NT_SEC_PKG_ERROR = -1073610665; + +const int RPC_NT_NOT_CANCELLED = -1073610664; + +const int RPC_NT_INVALID_ES_ACTION = -1073545127; + +const int RPC_NT_WRONG_ES_VERSION = -1073545126; + +const int RPC_NT_WRONG_STUB_VERSION = -1073545125; + +const int RPC_NT_INVALID_PIPE_OBJECT = -1073545124; + +const int RPC_NT_INVALID_PIPE_OPERATION = -1073545123; + +const int RPC_NT_WRONG_PIPE_VERSION = -1073545122; + +const int RPC_NT_PIPE_CLOSED = -1073545121; + +const int RPC_NT_PIPE_DISCIPLINE_ERROR = -1073545120; + +const int RPC_NT_PIPE_EMPTY = -1073545119; + +const int RPC_NT_INVALID_ASYNC_HANDLE = -1073610654; + +const int RPC_NT_INVALID_ASYNC_CALL = -1073610653; + +const int RPC_NT_PROXY_ACCESS_DENIED = -1073610652; + +const int RPC_NT_COOKIE_AUTH_FAILED = -1073610651; + +const int RPC_NT_SEND_INCOMPLETE = 1073873071; + +const int STATUS_ACPI_INVALID_OPCODE = -1072431103; + +const int STATUS_ACPI_STACK_OVERFLOW = -1072431102; + +const int STATUS_ACPI_ASSERT_FAILED = -1072431101; + +const int STATUS_ACPI_INVALID_INDEX = -1072431100; + +const int STATUS_ACPI_INVALID_ARGUMENT = -1072431099; + +const int STATUS_ACPI_FATAL = -1072431098; + +const int STATUS_ACPI_INVALID_SUPERNAME = -1072431097; + +const int STATUS_ACPI_INVALID_ARGTYPE = -1072431096; + +const int STATUS_ACPI_INVALID_OBJTYPE = -1072431095; + +const int STATUS_ACPI_INVALID_TARGETTYPE = -1072431094; + +const int STATUS_ACPI_INCORRECT_ARGUMENT_COUNT = -1072431093; + +const int STATUS_ACPI_ADDRESS_NOT_MAPPED = -1072431092; + +const int STATUS_ACPI_INVALID_EVENTTYPE = -1072431091; + +const int STATUS_ACPI_HANDLER_COLLISION = -1072431090; + +const int STATUS_ACPI_INVALID_DATA = -1072431089; + +const int STATUS_ACPI_INVALID_REGION = -1072431088; + +const int STATUS_ACPI_INVALID_ACCESS_SIZE = -1072431087; + +const int STATUS_ACPI_ACQUIRE_GLOBAL_LOCK = -1072431086; + +const int STATUS_ACPI_ALREADY_INITIALIZED = -1072431085; + +const int STATUS_ACPI_NOT_INITIALIZED = -1072431084; + +const int STATUS_ACPI_INVALID_MUTEX_LEVEL = -1072431083; + +const int STATUS_ACPI_MUTEX_NOT_OWNED = -1072431082; + +const int STATUS_ACPI_MUTEX_NOT_OWNER = -1072431081; + +const int STATUS_ACPI_RS_ACCESS = -1072431080; + +const int STATUS_ACPI_INVALID_TABLE = -1072431079; + +const int STATUS_ACPI_REG_HANDLER_FAILED = -1072431072; + +const int STATUS_ACPI_POWER_REQUEST_FAILED = -1072431071; + +const int STATUS_CTX_WINSTATION_NAME_INVALID = -1073086463; + +const int STATUS_CTX_INVALID_PD = -1073086462; + +const int STATUS_CTX_PD_NOT_FOUND = -1073086461; + +const int STATUS_CTX_CDM_CONNECT = 1074397188; + +const int STATUS_CTX_CDM_DISCONNECT = 1074397189; + +const int STATUS_CTX_CLOSE_PENDING = -1073086458; + +const int STATUS_CTX_NO_OUTBUF = -1073086457; + +const int STATUS_CTX_MODEM_INF_NOT_FOUND = -1073086456; + +const int STATUS_CTX_INVALID_MODEMNAME = -1073086455; + +const int STATUS_CTX_RESPONSE_ERROR = -1073086454; + +const int STATUS_CTX_MODEM_RESPONSE_TIMEOUT = -1073086453; + +const int STATUS_CTX_MODEM_RESPONSE_NO_CARRIER = -1073086452; + +const int STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE = -1073086451; + +const int STATUS_CTX_MODEM_RESPONSE_BUSY = -1073086450; + +const int STATUS_CTX_MODEM_RESPONSE_VOICE = -1073086449; + +const int STATUS_CTX_TD_ERROR = -1073086448; + +const int STATUS_CTX_LICENSE_CLIENT_INVALID = -1073086446; + +const int STATUS_CTX_LICENSE_NOT_AVAILABLE = -1073086445; + +const int STATUS_CTX_LICENSE_EXPIRED = -1073086444; + +const int STATUS_CTX_WINSTATION_NOT_FOUND = -1073086443; + +const int STATUS_CTX_WINSTATION_NAME_COLLISION = -1073086442; + +const int STATUS_CTX_WINSTATION_BUSY = -1073086441; + +const int STATUS_CTX_BAD_VIDEO_MODE = -1073086440; + +const int STATUS_CTX_GRAPHICS_INVALID = -1073086430; + +const int STATUS_CTX_NOT_CONSOLE = -1073086428; + +const int STATUS_CTX_CLIENT_QUERY_TIMEOUT = -1073086426; + +const int STATUS_CTX_CONSOLE_DISCONNECT = -1073086425; + +const int STATUS_CTX_CONSOLE_CONNECT = -1073086424; + +const int STATUS_CTX_SHADOW_DENIED = -1073086422; + +const int STATUS_CTX_WINSTATION_ACCESS_DENIED = -1073086421; + +const int STATUS_CTX_INVALID_WD = -1073086418; + +const int STATUS_CTX_WD_NOT_FOUND = -1073086417; + +const int STATUS_CTX_SHADOW_INVALID = -1073086416; + +const int STATUS_CTX_SHADOW_DISABLED = -1073086415; + +const int STATUS_RDP_PROTOCOL_ERROR = -1073086414; + +const int STATUS_CTX_CLIENT_LICENSE_NOT_SET = -1073086413; + +const int STATUS_CTX_CLIENT_LICENSE_IN_USE = -1073086412; + +const int STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE = -1073086411; + +const int STATUS_CTX_SHADOW_NOT_RUNNING = -1073086410; + +const int STATUS_CTX_LOGON_DISABLED = -1073086409; + +const int STATUS_CTX_SECURITY_LAYER_ERROR = -1073086408; + +const int STATUS_TS_INCOMPATIBLE_SESSIONS = -1073086407; + +const int STATUS_TS_VIDEO_SUBSYSTEM_ERROR = -1073086406; + +const int STATUS_PNP_BAD_MPS_TABLE = -1073479627; + +const int STATUS_PNP_TRANSLATION_FAILED = -1073479626; + +const int STATUS_PNP_IRQ_TRANSLATION_FAILED = -1073479625; + +const int STATUS_PNP_INVALID_ID = -1073479624; + +const int STATUS_IO_REISSUE_AS_CACHED = -1073479623; + +const int STATUS_MUI_FILE_NOT_FOUND = -1073020927; + +const int STATUS_MUI_INVALID_FILE = -1073020926; + +const int STATUS_MUI_INVALID_RC_CONFIG = -1073020925; + +const int STATUS_MUI_INVALID_LOCALE_NAME = -1073020924; + +const int STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME = -1073020923; + +const int STATUS_MUI_FILE_NOT_LOADED = -1073020922; + +const int STATUS_RESOURCE_ENUM_USER_STOP = -1073020921; + +const int STATUS_FLT_NO_HANDLER_DEFINED = -1071906815; + +const int STATUS_FLT_CONTEXT_ALREADY_DEFINED = -1071906814; + +const int STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST = -1071906813; + +const int STATUS_FLT_DISALLOW_FAST_IO = -1071906812; + +const int STATUS_FLT_DISALLOW_FSFILTER_IO = -1071906812; + +const int STATUS_FLT_INVALID_NAME_REQUEST = -1071906811; + +const int STATUS_FLT_NOT_SAFE_TO_POST_OPERATION = -1071906810; + +const int STATUS_FLT_NOT_INITIALIZED = -1071906809; + +const int STATUS_FLT_FILTER_NOT_READY = -1071906808; + +const int STATUS_FLT_POST_OPERATION_CLEANUP = -1071906807; + +const int STATUS_FLT_INTERNAL_ERROR = -1071906806; + +const int STATUS_FLT_DELETING_OBJECT = -1071906805; + +const int STATUS_FLT_MUST_BE_NONPAGED_POOL = -1071906804; + +const int STATUS_FLT_DUPLICATE_ENTRY = -1071906803; + +const int STATUS_FLT_CBDQ_DISABLED = -1071906802; + +const int STATUS_FLT_DO_NOT_ATTACH = -1071906801; + +const int STATUS_FLT_DO_NOT_DETACH = -1071906800; + +const int STATUS_FLT_INSTANCE_ALTITUDE_COLLISION = -1071906799; + +const int STATUS_FLT_INSTANCE_NAME_COLLISION = -1071906798; + +const int STATUS_FLT_FILTER_NOT_FOUND = -1071906797; + +const int STATUS_FLT_VOLUME_NOT_FOUND = -1071906796; + +const int STATUS_FLT_INSTANCE_NOT_FOUND = -1071906795; + +const int STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND = -1071906794; + +const int STATUS_FLT_INVALID_CONTEXT_REGISTRATION = -1071906793; + +const int STATUS_FLT_NAME_CACHE_MISS = -1071906792; + +const int STATUS_FLT_NO_DEVICE_OBJECT = -1071906791; + +const int STATUS_FLT_VOLUME_ALREADY_MOUNTED = -1071906790; + +const int STATUS_FLT_ALREADY_ENLISTED = -1071906789; + +const int STATUS_FLT_CONTEXT_ALREADY_LINKED = -1071906788; + +const int STATUS_FLT_NO_WAITER_FOR_REPLY = -1071906784; + +const int STATUS_FLT_REGISTRATION_BUSY = -1071906781; + +const int STATUS_SXS_SECTION_NOT_FOUND = -1072365567; + +const int STATUS_SXS_CANT_GEN_ACTCTX = -1072365566; + +const int STATUS_SXS_INVALID_ACTCTXDATA_FORMAT = -1072365565; + +const int STATUS_SXS_ASSEMBLY_NOT_FOUND = -1072365564; + +const int STATUS_SXS_MANIFEST_FORMAT_ERROR = -1072365563; + +const int STATUS_SXS_MANIFEST_PARSE_ERROR = -1072365562; + +const int STATUS_SXS_ACTIVATION_CONTEXT_DISABLED = -1072365561; + +const int STATUS_SXS_KEY_NOT_FOUND = -1072365560; + +const int STATUS_SXS_VERSION_CONFLICT = -1072365559; + +const int STATUS_SXS_WRONG_SECTION_TYPE = -1072365558; + +const int STATUS_SXS_THREAD_QUERIES_DISABLED = -1072365557; + +const int STATUS_SXS_ASSEMBLY_MISSING = -1072365556; + +const int STATUS_SXS_RELEASE_ACTIVATION_CONTEXT = 1075118093; + +const int STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET = -1072365554; + +const int STATUS_SXS_EARLY_DEACTIVATION = -1072365553; + +const int STATUS_SXS_INVALID_DEACTIVATION = -1072365552; + +const int STATUS_SXS_MULTIPLE_DEACTIVATION = -1072365551; + +const int STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = -1072365550; + +const int STATUS_SXS_PROCESS_TERMINATION_REQUESTED = -1072365549; + +const int STATUS_SXS_CORRUPT_ACTIVATION_STACK = -1072365548; + +const int STATUS_SXS_CORRUPTION = -1072365547; + +const int STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = -1072365546; + +const int STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = -1072365545; + +const int STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE = -1072365544; + +const int STATUS_SXS_IDENTITY_PARSE_ERROR = -1072365543; + +const int STATUS_SXS_COMPONENT_STORE_CORRUPT = -1072365542; + +const int STATUS_SXS_FILE_HASH_MISMATCH = -1072365541; + +const int STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = + -1072365540; + +const int STATUS_SXS_IDENTITIES_DIFFERENT = -1072365539; + +const int STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = -1072365538; + +const int STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY = -1072365537; + +const int STATUS_ADVANCED_INSTALLER_FAILED = -1072365536; + +const int STATUS_XML_ENCODING_MISMATCH = -1072365535; + +const int STATUS_SXS_MANIFEST_TOO_BIG = -1072365534; + +const int STATUS_SXS_SETTING_NOT_REGISTERED = -1072365533; + +const int STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE = -1072365532; + +const int STATUS_SMI_PRIMITIVE_INSTALLER_FAILED = -1072365531; + +const int STATUS_GENERIC_COMMAND_FAILED = -1072365530; + +const int STATUS_SXS_FILE_HASH_MISSING = -1072365529; + +const int STATUS_CLUSTER_INVALID_NODE = -1072496639; + +const int STATUS_CLUSTER_NODE_EXISTS = -1072496638; + +const int STATUS_CLUSTER_JOIN_IN_PROGRESS = -1072496637; + +const int STATUS_CLUSTER_NODE_NOT_FOUND = -1072496636; + +const int STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND = -1072496635; + +const int STATUS_CLUSTER_NETWORK_EXISTS = -1072496634; + +const int STATUS_CLUSTER_NETWORK_NOT_FOUND = -1072496633; + +const int STATUS_CLUSTER_NETINTERFACE_EXISTS = -1072496632; + +const int STATUS_CLUSTER_NETINTERFACE_NOT_FOUND = -1072496631; + +const int STATUS_CLUSTER_INVALID_REQUEST = -1072496630; + +const int STATUS_CLUSTER_INVALID_NETWORK_PROVIDER = -1072496629; + +const int STATUS_CLUSTER_NODE_DOWN = -1072496628; + +const int STATUS_CLUSTER_NODE_UNREACHABLE = -1072496627; + +const int STATUS_CLUSTER_NODE_NOT_MEMBER = -1072496626; + +const int STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS = -1072496625; + +const int STATUS_CLUSTER_INVALID_NETWORK = -1072496624; + +const int STATUS_CLUSTER_NO_NET_ADAPTERS = -1072496623; + +const int STATUS_CLUSTER_NODE_UP = -1072496622; + +const int STATUS_CLUSTER_NODE_PAUSED = -1072496621; + +const int STATUS_CLUSTER_NODE_NOT_PAUSED = -1072496620; + +const int STATUS_CLUSTER_NO_SECURITY_CONTEXT = -1072496619; + +const int STATUS_CLUSTER_NETWORK_NOT_INTERNAL = -1072496618; + +const int STATUS_CLUSTER_POISONED = -1072496617; + +const int STATUS_CLUSTER_NON_CSV_PATH = -1072496616; + +const int STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL = -1072496615; + +const int STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS = -1072496608; + +const int STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR = -1072496607; + +const int STATUS_CLUSTER_CSV_REDIRECTED = -1072496606; + +const int STATUS_CLUSTER_CSV_NOT_REDIRECTED = -1072496605; + +const int STATUS_CLUSTER_CSV_VOLUME_DRAINING = -1072496604; + +const int STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS = -1072496603; + +const int STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL = -1072496602; + +const int STATUS_CLUSTER_CSV_NO_SNAPSHOTS = -1072496601; + +const int STATUS_CSV_IO_PAUSE_TIMEOUT = -1072496600; + +const int STATUS_CLUSTER_CSV_INVALID_HANDLE = -1072496599; + +const int STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR = -1072496592; + +const int STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED = -1072496591; + +const int STATUS_TRANSACTIONAL_CONFLICT = -1072103423; + +const int STATUS_INVALID_TRANSACTION = -1072103422; + +const int STATUS_TRANSACTION_NOT_ACTIVE = -1072103421; + +const int STATUS_TM_INITIALIZATION_FAILED = -1072103420; + +const int STATUS_RM_NOT_ACTIVE = -1072103419; + +const int STATUS_RM_METADATA_CORRUPT = -1072103418; + +const int STATUS_TRANSACTION_NOT_JOINED = -1072103417; + +const int STATUS_DIRECTORY_NOT_RM = -1072103416; + +const int STATUS_COULD_NOT_RESIZE_LOG = -2145845239; + +const int STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE = -1072103414; + +const int STATUS_LOG_RESIZE_INVALID_SIZE = -1072103413; + +const int STATUS_REMOTE_FILE_VERSION_MISMATCH = -1072103412; + +const int STATUS_CRM_PROTOCOL_ALREADY_EXISTS = -1072103409; + +const int STATUS_TRANSACTION_PROPAGATION_FAILED = -1072103408; + +const int STATUS_CRM_PROTOCOL_NOT_FOUND = -1072103407; + +const int STATUS_TRANSACTION_SUPERIOR_EXISTS = -1072103406; + +const int STATUS_TRANSACTION_REQUEST_NOT_VALID = -1072103405; + +const int STATUS_TRANSACTION_NOT_REQUESTED = -1072103404; + +const int STATUS_TRANSACTION_ALREADY_ABORTED = -1072103403; + +const int STATUS_TRANSACTION_ALREADY_COMMITTED = -1072103402; + +const int STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER = -1072103401; + +const int STATUS_CURRENT_TRANSACTION_NOT_VALID = -1072103400; + +const int STATUS_LOG_GROWTH_FAILED = -1072103399; + +const int STATUS_OBJECT_NO_LONGER_EXISTS = -1072103391; + +const int STATUS_STREAM_MINIVERSION_NOT_FOUND = -1072103390; + +const int STATUS_STREAM_MINIVERSION_NOT_VALID = -1072103389; + +const int STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = + -1072103388; + +const int STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = -1072103387; + +const int STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS = -1072103386; + +const int STATUS_HANDLE_NO_LONGER_VALID = -1072103384; + +const int STATUS_NO_TXF_METADATA = -2145845207; + +const int STATUS_LOG_CORRUPTION_DETECTED = -1072103376; + +const int STATUS_CANT_RECOVER_WITH_HANDLE_OPEN = -2145845199; + +const int STATUS_RM_DISCONNECTED = -1072103374; + +const int STATUS_ENLISTMENT_NOT_SUPERIOR = -1072103373; + +const int STATUS_RECOVERY_NOT_NEEDED = 1075380276; + +const int STATUS_RM_ALREADY_STARTED = 1075380277; + +const int STATUS_FILE_IDENTITY_NOT_PERSISTENT = -1072103370; + +const int STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY = -1072103369; + +const int STATUS_CANT_CROSS_RM_BOUNDARY = -1072103368; + +const int STATUS_TXF_DIR_NOT_EMPTY = -1072103367; + +const int STATUS_INDOUBT_TRANSACTIONS_EXIST = -1072103366; + +const int STATUS_TM_VOLATILE = -1072103365; + +const int STATUS_ROLLBACK_TIMER_EXPIRED = -1072103364; + +const int STATUS_TXF_ATTRIBUTE_CORRUPT = -1072103363; + +const int STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION = -1072103362; + +const int STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED = -1072103361; + +const int STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = -1072103360; + +const int STATUS_TXF_METADATA_ALREADY_PRESENT = -2145845183; + +const int STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = -2145845182; + +const int STATUS_TRANSACTION_REQUIRED_PROMOTION = -1072103357; + +const int STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION = -1072103356; + +const int STATUS_TRANSACTIONS_NOT_FROZEN = -1072103355; + +const int STATUS_TRANSACTION_FREEZE_IN_PROGRESS = -1072103354; + +const int STATUS_NOT_SNAPSHOT_VOLUME = -1072103353; + +const int STATUS_NO_SAVEPOINT_WITH_OPEN_FILES = -1072103352; + +const int STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION = -1072103351; + +const int STATUS_TM_IDENTITY_MISMATCH = -1072103350; + +const int STATUS_FLOATED_SECTION = -1072103349; + +const int STATUS_CANNOT_ACCEPT_TRANSACTED_WORK = -1072103348; + +const int STATUS_CANNOT_ABORT_TRANSACTIONS = -1072103347; + +const int STATUS_TRANSACTION_NOT_FOUND = -1072103346; + +const int STATUS_RESOURCEMANAGER_NOT_FOUND = -1072103345; + +const int STATUS_ENLISTMENT_NOT_FOUND = -1072103344; + +const int STATUS_TRANSACTIONMANAGER_NOT_FOUND = -1072103343; + +const int STATUS_TRANSACTIONMANAGER_NOT_ONLINE = -1072103342; + +const int STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = -1072103341; + +const int STATUS_TRANSACTION_NOT_ROOT = -1072103340; + +const int STATUS_TRANSACTION_OBJECT_EXPIRED = -1072103339; + +const int STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = -1072103338; + +const int STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED = -1072103337; + +const int STATUS_TRANSACTION_RECORD_TOO_LONG = -1072103336; + +const int STATUS_NO_LINK_TRACKING_IN_TRANSACTION = -1072103335; + +const int STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION = -1072103334; + +const int STATUS_TRANSACTION_INTEGRITY_VIOLATED = -1072103333; + +const int STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH = -1072103332; + +const int STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT = -1072103331; + +const int STATUS_TRANSACTION_MUST_WRITETHROUGH = -1072103330; + +const int STATUS_TRANSACTION_NO_SUPERIOR = -1072103329; + +const int STATUS_EXPIRED_HANDLE = -1072103328; + +const int STATUS_TRANSACTION_NOT_ENLISTED = -1072103327; + +const int STATUS_LOG_SECTOR_INVALID = -1072037887; + +const int STATUS_LOG_SECTOR_PARITY_INVALID = -1072037886; + +const int STATUS_LOG_SECTOR_REMAPPED = -1072037885; + +const int STATUS_LOG_BLOCK_INCOMPLETE = -1072037884; + +const int STATUS_LOG_INVALID_RANGE = -1072037883; + +const int STATUS_LOG_BLOCKS_EXHAUSTED = -1072037882; + +const int STATUS_LOG_READ_CONTEXT_INVALID = -1072037881; + +const int STATUS_LOG_RESTART_INVALID = -1072037880; + +const int STATUS_LOG_BLOCK_VERSION = -1072037879; + +const int STATUS_LOG_BLOCK_INVALID = -1072037878; + +const int STATUS_LOG_READ_MODE_INVALID = -1072037877; + +const int STATUS_LOG_NO_RESTART = 1075445772; + +const int STATUS_LOG_METADATA_CORRUPT = -1072037875; + +const int STATUS_LOG_METADATA_INVALID = -1072037874; + +const int STATUS_LOG_METADATA_INCONSISTENT = -1072037873; + +const int STATUS_LOG_RESERVATION_INVALID = -1072037872; + +const int STATUS_LOG_CANT_DELETE = -1072037871; + +const int STATUS_LOG_CONTAINER_LIMIT_EXCEEDED = -1072037870; + +const int STATUS_LOG_START_OF_LOG = -1072037869; + +const int STATUS_LOG_POLICY_ALREADY_INSTALLED = -1072037868; + +const int STATUS_LOG_POLICY_NOT_INSTALLED = -1072037867; + +const int STATUS_LOG_POLICY_INVALID = -1072037866; + +const int STATUS_LOG_POLICY_CONFLICT = -1072037865; + +const int STATUS_LOG_PINNED_ARCHIVE_TAIL = -1072037864; + +const int STATUS_LOG_RECORD_NONEXISTENT = -1072037863; + +const int STATUS_LOG_RECORDS_RESERVED_INVALID = -1072037862; + +const int STATUS_LOG_SPACE_RESERVED_INVALID = -1072037861; + +const int STATUS_LOG_TAIL_INVALID = -1072037860; + +const int STATUS_LOG_FULL = -1072037859; + +const int STATUS_LOG_MULTIPLEXED = -1072037858; + +const int STATUS_LOG_DEDICATED = -1072037857; + +const int STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS = -1072037856; + +const int STATUS_LOG_ARCHIVE_IN_PROGRESS = -1072037855; + +const int STATUS_LOG_EPHEMERAL = -1072037854; + +const int STATUS_LOG_NOT_ENOUGH_CONTAINERS = -1072037853; + +const int STATUS_LOG_CLIENT_ALREADY_REGISTERED = -1072037852; + +const int STATUS_LOG_CLIENT_NOT_REGISTERED = -1072037851; + +const int STATUS_LOG_FULL_HANDLER_IN_PROGRESS = -1072037850; + +const int STATUS_LOG_CONTAINER_READ_FAILED = -1072037849; + +const int STATUS_LOG_CONTAINER_WRITE_FAILED = -1072037848; + +const int STATUS_LOG_CONTAINER_OPEN_FAILED = -1072037847; + +const int STATUS_LOG_CONTAINER_STATE_INVALID = -1072037846; + +const int STATUS_LOG_STATE_INVALID = -1072037845; + +const int STATUS_LOG_PINNED = -1072037844; + +const int STATUS_LOG_METADATA_FLUSH_FAILED = -1072037843; + +const int STATUS_LOG_INCONSISTENT_SECURITY = -1072037842; + +const int STATUS_LOG_APPENDED_FLUSH_FAILED = -1072037841; + +const int STATUS_LOG_PINNED_RESERVATION = -1072037840; + +const int STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD = -1071972118; + +const int STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = -2145713941; + +const int STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 1075511532; + +const int STATUS_MONITOR_NO_DESCRIPTOR = -1071841279; + +const int STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT = -1071841278; + +const int STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM = -1071841277; + +const int STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK = -1071841276; + +const int STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED = -1071841275; + +const int STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK = -1071841274; + +const int STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK = -1071841273; + +const int STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA = -1071841272; + +const int STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK = -1071841271; + +const int STATUS_MONITOR_INVALID_MANUFACTURE_DATE = -1071841270; + +const int STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER = -1071775744; + +const int STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER = -1071775743; + +const int STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER = -1071775742; + +const int STATUS_GRAPHICS_ADAPTER_WAS_RESET = -1071775741; + +const int STATUS_GRAPHICS_INVALID_DRIVER_MODEL = -1071775740; + +const int STATUS_GRAPHICS_PRESENT_MODE_CHANGED = -1071775739; + +const int STATUS_GRAPHICS_PRESENT_OCCLUDED = -1071775738; + +const int STATUS_GRAPHICS_PRESENT_DENIED = -1071775737; + +const int STATUS_GRAPHICS_CANNOTCOLORCONVERT = -1071775736; + +const int STATUS_GRAPHICS_DRIVER_MISMATCH = -1071775735; + +const int STATUS_GRAPHICS_PARTIAL_DATA_POPULATED = 1075707914; + +const int STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED = -1071775733; + +const int STATUS_GRAPHICS_PRESENT_UNOCCLUDED = -1071775732; + +const int STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE = -1071775731; + +const int STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED = -1071775730; + +const int STATUS_GRAPHICS_PRESENT_INVALID_WINDOW = -1071775729; + +const int STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND = -1071775728; + +const int STATUS_GRAPHICS_VAIL_STATE_CHANGED = -1071775727; + +const int STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN = -1071775726; + +const int STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED = -1071775725; + +const int STATUS_GRAPHICS_NO_VIDEO_MEMORY = -1071775488; + +const int STATUS_GRAPHICS_CANT_LOCK_MEMORY = -1071775487; + +const int STATUS_GRAPHICS_ALLOCATION_BUSY = -1071775486; + +const int STATUS_GRAPHICS_TOO_MANY_REFERENCES = -1071775485; + +const int STATUS_GRAPHICS_TRY_AGAIN_LATER = -1071775484; + +const int STATUS_GRAPHICS_TRY_AGAIN_NOW = -1071775483; + +const int STATUS_GRAPHICS_ALLOCATION_INVALID = -1071775482; + +const int STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = -1071775481; + +const int STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED = -1071775480; + +const int STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION = -1071775479; + +const int STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE = -1071775472; + +const int STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION = -1071775471; + +const int STATUS_GRAPHICS_ALLOCATION_CLOSED = -1071775470; + +const int STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE = -1071775469; + +const int STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE = -1071775468; + +const int STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE = -1071775467; + +const int STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST = -1071775466; + +const int STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE = -1071775232; + +const int STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION = 1075708417; + +const int STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY = -1071774976; + +const int STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED = -1071774975; + +const int STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED = -1071774974; + +const int STATUS_GRAPHICS_INVALID_VIDPN = -1071774973; + +const int STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE = -1071774972; + +const int STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET = -1071774971; + +const int STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED = -1071774970; + +const int STATUS_GRAPHICS_MODE_NOT_PINNED = 1075708679; + +const int STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET = -1071774968; + +const int STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET = -1071774967; + +const int STATUS_GRAPHICS_INVALID_FREQUENCY = -1071774966; + +const int STATUS_GRAPHICS_INVALID_ACTIVE_REGION = -1071774965; + +const int STATUS_GRAPHICS_INVALID_TOTAL_REGION = -1071774964; + +const int STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE = -1071774960; + +const int STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE = -1071774959; + +const int STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET = -1071774958; + +const int STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY = -1071774957; + +const int STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET = -1071774956; + +const int STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET = -1071774955; + +const int STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET = -1071774954; + +const int STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET = -1071774953; + +const int STATUS_GRAPHICS_TARGET_ALREADY_IN_SET = -1071774952; + +const int STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH = -1071774951; + +const int STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY = -1071774950; + +const int STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET = -1071774949; + +const int STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE = -1071774948; + +const int STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET = -1071774947; + +const int STATUS_GRAPHICS_NO_PREFERRED_MODE = 1075708702; + +const int STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET = -1071774945; + +const int STATUS_GRAPHICS_STALE_MODESET = -1071774944; + +const int STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET = -1071774943; + +const int STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE = -1071774942; + +const int STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN = -1071774941; + +const int STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE = -1071774940; + +const int STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION = + -1071774939; + +const int STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES = -1071774938; + +const int STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY = -1071774937; + +const int STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE = -1071774936; + +const int STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET = -1071774935; + +const int STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET = -1071774934; + +const int STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR = -1071774933; + +const int STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET = -1071774932; + +const int STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET = -1071774931; + +const int STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE = -1071774930; + +const int STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE = -1071774929; + +const int STATUS_GRAPHICS_RESOURCES_NOT_RELATED = -1071774928; + +const int STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE = -1071774927; + +const int STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE = -1071774926; + +const int STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET = -1071774925; + +const int STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER = + -1071774924; + +const int STATUS_GRAPHICS_NO_VIDPNMGR = -1071774923; + +const int STATUS_GRAPHICS_NO_ACTIVE_VIDPN = -1071774922; + +const int STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY = -1071774921; + +const int STATUS_GRAPHICS_MONITOR_NOT_CONNECTED = -1071774920; + +const int STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY = -1071774919; + +const int STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE = -1071774918; + +const int STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE = -1071774917; + +const int STATUS_GRAPHICS_INVALID_STRIDE = -1071774916; + +const int STATUS_GRAPHICS_INVALID_PIXELFORMAT = -1071774915; + +const int STATUS_GRAPHICS_INVALID_COLORBASIS = -1071774914; + +const int STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE = -1071774913; + +const int STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY = -1071774912; + +const int STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT = -1071774911; + +const int STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE = -1071774910; + +const int STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN = -1071774909; + +const int STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL = -1071774908; + +const int STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION = + -1071774907; + +const int STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED = + -1071774906; + +const int STATUS_GRAPHICS_INVALID_GAMMA_RAMP = -1071774905; + +const int STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED = -1071774904; + +const int STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED = -1071774903; + +const int STATUS_GRAPHICS_MODE_NOT_IN_MODESET = -1071774902; + +const int STATUS_GRAPHICS_DATASET_IS_EMPTY = 1075708747; + +const int STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 1075708748; + +const int STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON = + -1071774899; + +const int STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE = -1071774898; + +const int STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE = -1071774897; + +const int STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS = -1071774896; + +const int STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = + 1075708753; + +const int STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING = -1071774894; + +const int STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED = -1071774893; + +const int STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS = -1071774892; + +const int STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT = -1071774891; + +const int STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM = -1071774890; + +const int STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN = -1071774889; + +const int STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT = + -1071774888; + +const int STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED = -1071774887; + +const int STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION = -1071774886; + +const int STATUS_GRAPHICS_INVALID_CLIENT_TYPE = -1071774885; + +const int STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET = -1071774884; + +const int STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED = -1071774720; + +const int STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED = -1071774719; + +const int STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS = 1075708975; + +const int STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER = -1071774672; + +const int STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED = -1071774671; + +const int STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED = -1071774670; + +const int STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY = -1071774669; + +const int STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED = -1071774668; + +const int STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON = -1071774667; + +const int STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE = -1071774666; + +const int STATUS_GRAPHICS_LEADLINK_START_DEFERRED = 1075708983; + +const int STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER = -1071774664; + +const int STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY = 1075708985; + +const int STATUS_GRAPHICS_START_DEFERRED = 1075708986; + +const int STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED = -1071774661; + +const int STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS = 1075708988; + +const int STATUS_GRAPHICS_OPM_NOT_SUPPORTED = -1071774464; + +const int STATUS_GRAPHICS_COPP_NOT_SUPPORTED = -1071774463; + +const int STATUS_GRAPHICS_UAB_NOT_SUPPORTED = -1071774462; + +const int STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS = -1071774461; + +const int STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST = -1071774459; + +const int STATUS_GRAPHICS_OPM_INTERNAL_ERROR = -1071774453; + +const int STATUS_GRAPHICS_OPM_INVALID_HANDLE = -1071774452; + +const int STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH = -1071774450; + +const int STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED = -1071774449; + +const int STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED = -1071774448; + +const int STATUS_GRAPHICS_PVP_HFS_FAILED = -1071774447; + +const int STATUS_GRAPHICS_OPM_INVALID_SRM = -1071774446; + +const int STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP = -1071774445; + +const int STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP = -1071774444; + +const int STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA = -1071774443; + +const int STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET = -1071774442; + +const int STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH = -1071774441; + +const int STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE = -1071774440; + +const int STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS = -1071774438; + +const int STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS = + -1071774436; + +const int STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST = -1071774435; + +const int STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR = -1071774434; + +const int STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS = + -1071774433; + +const int STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED = -1071774432; + +const int STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST = -1071774431; + +const int STATUS_GRAPHICS_I2C_NOT_SUPPORTED = -1071774336; + +const int STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST = -1071774335; + +const int STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA = -1071774334; + +const int STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA = -1071774333; + +const int STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED = -1071774332; + +const int STATUS_GRAPHICS_DDCCI_INVALID_DATA = -1071774331; + +const int STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE = + -1071774330; + +const int STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING = -1071774329; + +const int STATUS_GRAPHICS_MCA_INTERNAL_ERROR = -1071774328; + +const int STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND = -1071774327; + +const int STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH = -1071774326; + +const int STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM = -1071774325; + +const int STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = -1071774324; + +const int STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS = -1071774323; + +const int STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED = -1071774240; + +const int STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = -1071774239; + +const int STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = -1071774238; + +const int STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED = -1071774237; + +const int STATUS_GRAPHICS_INVALID_POINTER = -1071774236; + +const int STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = + -1071774235; + +const int STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL = -1071774234; + +const int STATUS_GRAPHICS_INTERNAL_ERROR = -1071774233; + +const int STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS = -1071774232; + +const int STATUS_FVE_LOCKED_VOLUME = -1071579136; + +const int STATUS_FVE_NOT_ENCRYPTED = -1071579135; + +const int STATUS_FVE_BAD_INFORMATION = -1071579134; + +const int STATUS_FVE_TOO_SMALL = -1071579133; + +const int STATUS_FVE_FAILED_WRONG_FS = -1071579132; + +const int STATUS_FVE_BAD_PARTITION_SIZE = -1071579131; + +const int STATUS_FVE_FS_NOT_EXTENDED = -1071579130; + +const int STATUS_FVE_FS_MOUNTED = -1071579129; + +const int STATUS_FVE_NO_LICENSE = -1071579128; + +const int STATUS_FVE_ACTION_NOT_ALLOWED = -1071579127; + +const int STATUS_FVE_BAD_DATA = -1071579126; + +const int STATUS_FVE_VOLUME_NOT_BOUND = -1071579125; + +const int STATUS_FVE_NOT_DATA_VOLUME = -1071579124; + +const int STATUS_FVE_CONV_READ_ERROR = -1071579123; + +const int STATUS_FVE_CONV_WRITE_ERROR = -1071579122; + +const int STATUS_FVE_OVERLAPPED_UPDATE = -1071579121; + +const int STATUS_FVE_FAILED_SECTOR_SIZE = -1071579120; + +const int STATUS_FVE_FAILED_AUTHENTICATION = -1071579119; + +const int STATUS_FVE_NOT_OS_VOLUME = -1071579118; + +const int STATUS_FVE_KEYFILE_NOT_FOUND = -1071579117; + +const int STATUS_FVE_KEYFILE_INVALID = -1071579116; + +const int STATUS_FVE_KEYFILE_NO_VMK = -1071579115; + +const int STATUS_FVE_TPM_DISABLED = -1071579114; + +const int STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO = -1071579113; + +const int STATUS_FVE_TPM_INVALID_PCR = -1071579112; + +const int STATUS_FVE_TPM_NO_VMK = -1071579111; + +const int STATUS_FVE_PIN_INVALID = -1071579110; + +const int STATUS_FVE_AUTH_INVALID_APPLICATION = -1071579109; + +const int STATUS_FVE_AUTH_INVALID_CONFIG = -1071579108; + +const int STATUS_FVE_DEBUGGER_ENABLED = -1071579107; + +const int STATUS_FVE_DRY_RUN_FAILED = -1071579106; + +const int STATUS_FVE_BAD_METADATA_POINTER = -1071579105; + +const int STATUS_FVE_OLD_METADATA_COPY = -1071579104; + +const int STATUS_FVE_REBOOT_REQUIRED = -1071579103; + +const int STATUS_FVE_RAW_ACCESS = -1071579102; + +const int STATUS_FVE_RAW_BLOCKED = -1071579101; + +const int STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY = -1071579100; + +const int STATUS_FVE_MOR_FAILED = -1071579099; + +const int STATUS_FVE_NO_FEATURE_LICENSE = -1071579098; + +const int STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED = -1071579097; + +const int STATUS_FVE_CONV_RECOVERY_FAILED = -1071579096; + +const int STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG = -1071579095; + +const int STATUS_FVE_INVALID_DATUM_TYPE = -1071579094; + +const int STATUS_FVE_VOLUME_TOO_SMALL = -1071579088; + +const int STATUS_FVE_ENH_PIN_INVALID = -1071579087; + +const int STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE = -1071579086; + +const int STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE = -1071579085; + +const int STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK = -1071579084; + +const int STATUS_FVE_NOT_ALLOWED_ON_CLUSTER = -1071579083; + +const int STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING = -1071579082; + +const int STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE = -1071579081; + +const int STATUS_FVE_EDRIVE_DRY_RUN_FAILED = -1071579080; + +const int STATUS_FVE_SECUREBOOT_DISABLED = -1071579079; + +const int STATUS_FVE_SECUREBOOT_CONFIG_CHANGE = -1071579078; + +const int STATUS_FVE_DEVICE_LOCKEDOUT = -1071579077; + +const int STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT = -1071579076; + +const int STATUS_FVE_NOT_DE_VOLUME = -1071579075; + +const int STATUS_FVE_PROTECTION_DISABLED = -1071579074; + +const int STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED = -1071579073; + +const int STATUS_FVE_OSV_KSR_NOT_ALLOWED = -1071579072; + +const int STATUS_FWP_CALLOUT_NOT_FOUND = -1071513599; + +const int STATUS_FWP_CONDITION_NOT_FOUND = -1071513598; + +const int STATUS_FWP_FILTER_NOT_FOUND = -1071513597; + +const int STATUS_FWP_LAYER_NOT_FOUND = -1071513596; + +const int STATUS_FWP_PROVIDER_NOT_FOUND = -1071513595; + +const int STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND = -1071513594; + +const int STATUS_FWP_SUBLAYER_NOT_FOUND = -1071513593; + +const int STATUS_FWP_NOT_FOUND = -1071513592; + +const int STATUS_FWP_ALREADY_EXISTS = -1071513591; + +const int STATUS_FWP_IN_USE = -1071513590; + +const int STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS = -1071513589; + +const int STATUS_FWP_WRONG_SESSION = -1071513588; + +const int STATUS_FWP_NO_TXN_IN_PROGRESS = -1071513587; + +const int STATUS_FWP_TXN_IN_PROGRESS = -1071513586; + +const int STATUS_FWP_TXN_ABORTED = -1071513585; + +const int STATUS_FWP_SESSION_ABORTED = -1071513584; + +const int STATUS_FWP_INCOMPATIBLE_TXN = -1071513583; + +const int STATUS_FWP_TIMEOUT = -1071513582; + +const int STATUS_FWP_NET_EVENTS_DISABLED = -1071513581; + +const int STATUS_FWP_INCOMPATIBLE_LAYER = -1071513580; + +const int STATUS_FWP_KM_CLIENTS_ONLY = -1071513579; + +const int STATUS_FWP_LIFETIME_MISMATCH = -1071513578; + +const int STATUS_FWP_BUILTIN_OBJECT = -1071513577; + +const int STATUS_FWP_TOO_MANY_CALLOUTS = -1071513576; + +const int STATUS_FWP_NOTIFICATION_DROPPED = -1071513575; + +const int STATUS_FWP_TRAFFIC_MISMATCH = -1071513574; + +const int STATUS_FWP_INCOMPATIBLE_SA_STATE = -1071513573; + +const int STATUS_FWP_NULL_POINTER = -1071513572; + +const int STATUS_FWP_INVALID_ENUMERATOR = -1071513571; + +const int STATUS_FWP_INVALID_FLAGS = -1071513570; + +const int STATUS_FWP_INVALID_NET_MASK = -1071513569; + +const int STATUS_FWP_INVALID_RANGE = -1071513568; + +const int STATUS_FWP_INVALID_INTERVAL = -1071513567; + +const int STATUS_FWP_ZERO_LENGTH_ARRAY = -1071513566; + +const int STATUS_FWP_NULL_DISPLAY_NAME = -1071513565; + +const int STATUS_FWP_INVALID_ACTION_TYPE = -1071513564; + +const int STATUS_FWP_INVALID_WEIGHT = -1071513563; + +const int STATUS_FWP_MATCH_TYPE_MISMATCH = -1071513562; + +const int STATUS_FWP_TYPE_MISMATCH = -1071513561; + +const int STATUS_FWP_OUT_OF_BOUNDS = -1071513560; + +const int STATUS_FWP_RESERVED = -1071513559; + +const int STATUS_FWP_DUPLICATE_CONDITION = -1071513558; + +const int STATUS_FWP_DUPLICATE_KEYMOD = -1071513557; + +const int STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER = -1071513556; + +const int STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER = -1071513555; + +const int STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER = -1071513554; + +const int STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT = -1071513553; + +const int STATUS_FWP_INCOMPATIBLE_AUTH_METHOD = -1071513552; + +const int STATUS_FWP_INCOMPATIBLE_DH_GROUP = -1071513551; + +const int STATUS_FWP_EM_NOT_SUPPORTED = -1071513550; + +const int STATUS_FWP_NEVER_MATCH = -1071513549; + +const int STATUS_FWP_PROVIDER_CONTEXT_MISMATCH = -1071513548; + +const int STATUS_FWP_INVALID_PARAMETER = -1071513547; + +const int STATUS_FWP_TOO_MANY_SUBLAYERS = -1071513546; + +const int STATUS_FWP_CALLOUT_NOTIFICATION_FAILED = -1071513545; + +const int STATUS_FWP_INVALID_AUTH_TRANSFORM = -1071513544; + +const int STATUS_FWP_INVALID_CIPHER_TRANSFORM = -1071513543; + +const int STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM = -1071513542; + +const int STATUS_FWP_INVALID_TRANSFORM_COMBINATION = -1071513541; + +const int STATUS_FWP_DUPLICATE_AUTH_METHOD = -1071513540; + +const int STATUS_FWP_INVALID_TUNNEL_ENDPOINT = -1071513539; + +const int STATUS_FWP_L2_DRIVER_NOT_READY = -1071513538; + +const int STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED = -1071513537; + +const int STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL = -1071513536; + +const int STATUS_FWP_CONNECTIONS_DISABLED = -1071513535; + +const int STATUS_FWP_INVALID_DNS_NAME = -1071513534; + +const int STATUS_FWP_STILL_ON = -1071513533; + +const int STATUS_FWP_IKEEXT_NOT_RUNNING = -1071513532; + +const int STATUS_FWP_TCPIP_NOT_READY = -1071513344; + +const int STATUS_FWP_INJECT_HANDLE_CLOSING = -1071513343; + +const int STATUS_FWP_INJECT_HANDLE_STALE = -1071513342; + +const int STATUS_FWP_CANNOT_PEND = -1071513341; + +const int STATUS_FWP_DROP_NOICMP = -1071513340; + +const int STATUS_NDIS_CLOSING = -1071448062; + +const int STATUS_NDIS_BAD_VERSION = -1071448060; + +const int STATUS_NDIS_BAD_CHARACTERISTICS = -1071448059; + +const int STATUS_NDIS_ADAPTER_NOT_FOUND = -1071448058; + +const int STATUS_NDIS_OPEN_FAILED = -1071448057; + +const int STATUS_NDIS_DEVICE_FAILED = -1071448056; + +const int STATUS_NDIS_MULTICAST_FULL = -1071448055; + +const int STATUS_NDIS_MULTICAST_EXISTS = -1071448054; + +const int STATUS_NDIS_MULTICAST_NOT_FOUND = -1071448053; + +const int STATUS_NDIS_REQUEST_ABORTED = -1071448052; + +const int STATUS_NDIS_RESET_IN_PROGRESS = -1071448051; + +const int STATUS_NDIS_NOT_SUPPORTED = -1071447877; + +const int STATUS_NDIS_INVALID_PACKET = -1071448049; + +const int STATUS_NDIS_ADAPTER_NOT_READY = -1071448047; + +const int STATUS_NDIS_INVALID_LENGTH = -1071448044; + +const int STATUS_NDIS_INVALID_DATA = -1071448043; + +const int STATUS_NDIS_BUFFER_TOO_SHORT = -1071448042; + +const int STATUS_NDIS_INVALID_OID = -1071448041; + +const int STATUS_NDIS_ADAPTER_REMOVED = -1071448040; + +const int STATUS_NDIS_UNSUPPORTED_MEDIA = -1071448039; + +const int STATUS_NDIS_GROUP_ADDRESS_IN_USE = -1071448038; + +const int STATUS_NDIS_FILE_NOT_FOUND = -1071448037; + +const int STATUS_NDIS_ERROR_READING_FILE = -1071448036; + +const int STATUS_NDIS_ALREADY_MAPPED = -1071448035; + +const int STATUS_NDIS_RESOURCE_CONFLICT = -1071448034; + +const int STATUS_NDIS_MEDIA_DISCONNECTED = -1071448033; + +const int STATUS_NDIS_INVALID_ADDRESS = -1071448030; + +const int STATUS_NDIS_INVALID_DEVICE_REQUEST = -1071448048; + +const int STATUS_NDIS_PAUSED = -1071448022; + +const int STATUS_NDIS_INTERFACE_NOT_FOUND = -1071448021; + +const int STATUS_NDIS_UNSUPPORTED_REVISION = -1071448020; + +const int STATUS_NDIS_INVALID_PORT = -1071448019; + +const int STATUS_NDIS_INVALID_PORT_STATE = -1071448018; + +const int STATUS_NDIS_LOW_POWER_STATE = -1071448017; + +const int STATUS_NDIS_REINIT_REQUIRED = -1071448016; + +const int STATUS_NDIS_NO_QUEUES = -1071448015; + +const int STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED = -1071439872; + +const int STATUS_NDIS_DOT11_MEDIA_IN_USE = -1071439871; + +const int STATUS_NDIS_DOT11_POWER_STATE_INVALID = -1071439870; + +const int STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL = -1071439869; + +const int STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = -1071439868; + +const int STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE = -1071439867; + +const int STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE = -1071439866; + +const int STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED = -1071439865; + +const int STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED = -1071439864; + +const int STATUS_NDIS_INDICATION_REQUIRED = 1076035585; + +const int STATUS_NDIS_OFFLOAD_POLICY = -1071443953; + +const int STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED = -1071443950; + +const int STATUS_NDIS_OFFLOAD_PATH_REJECTED = -1071443949; + +const int STATUS_TPM_ERROR_MASK = -1071054848; + +const int STATUS_TPM_AUTHFAIL = -1071054847; + +const int STATUS_TPM_BADINDEX = -1071054846; + +const int STATUS_TPM_BAD_PARAMETER = -1071054845; + +const int STATUS_TPM_AUDITFAILURE = -1071054844; + +const int STATUS_TPM_CLEAR_DISABLED = -1071054843; + +const int STATUS_TPM_DEACTIVATED = -1071054842; + +const int STATUS_TPM_DISABLED = -1071054841; + +const int STATUS_TPM_DISABLED_CMD = -1071054840; + +const int STATUS_TPM_FAIL = -1071054839; + +const int STATUS_TPM_BAD_ORDINAL = -1071054838; + +const int STATUS_TPM_INSTALL_DISABLED = -1071054837; + +const int STATUS_TPM_INVALID_KEYHANDLE = -1071054836; + +const int STATUS_TPM_KEYNOTFOUND = -1071054835; + +const int STATUS_TPM_INAPPROPRIATE_ENC = -1071054834; + +const int STATUS_TPM_MIGRATEFAIL = -1071054833; + +const int STATUS_TPM_INVALID_PCR_INFO = -1071054832; + +const int STATUS_TPM_NOSPACE = -1071054831; + +const int STATUS_TPM_NOSRK = -1071054830; + +const int STATUS_TPM_NOTSEALED_BLOB = -1071054829; + +const int STATUS_TPM_OWNER_SET = -1071054828; + +const int STATUS_TPM_RESOURCES = -1071054827; + +const int STATUS_TPM_SHORTRANDOM = -1071054826; + +const int STATUS_TPM_SIZE = -1071054825; + +const int STATUS_TPM_WRONGPCRVAL = -1071054824; + +const int STATUS_TPM_BAD_PARAM_SIZE = -1071054823; + +const int STATUS_TPM_SHA_THREAD = -1071054822; + +const int STATUS_TPM_SHA_ERROR = -1071054821; + +const int STATUS_TPM_FAILEDSELFTEST = -1071054820; + +const int STATUS_TPM_AUTH2FAIL = -1071054819; + +const int STATUS_TPM_BADTAG = -1071054818; + +const int STATUS_TPM_IOERROR = -1071054817; + +const int STATUS_TPM_ENCRYPT_ERROR = -1071054816; + +const int STATUS_TPM_DECRYPT_ERROR = -1071054815; + +const int STATUS_TPM_INVALID_AUTHHANDLE = -1071054814; + +const int STATUS_TPM_NO_ENDORSEMENT = -1071054813; + +const int STATUS_TPM_INVALID_KEYUSAGE = -1071054812; + +const int STATUS_TPM_WRONG_ENTITYTYPE = -1071054811; + +const int STATUS_TPM_INVALID_POSTINIT = -1071054810; + +const int STATUS_TPM_INAPPROPRIATE_SIG = -1071054809; + +const int STATUS_TPM_BAD_KEY_PROPERTY = -1071054808; + +const int STATUS_TPM_BAD_MIGRATION = -1071054807; + +const int STATUS_TPM_BAD_SCHEME = -1071054806; + +const int STATUS_TPM_BAD_DATASIZE = -1071054805; + +const int STATUS_TPM_BAD_MODE = -1071054804; + +const int STATUS_TPM_BAD_PRESENCE = -1071054803; + +const int STATUS_TPM_BAD_VERSION = -1071054802; + +const int STATUS_TPM_NO_WRAP_TRANSPORT = -1071054801; + +const int STATUS_TPM_AUDITFAIL_UNSUCCESSFUL = -1071054800; + +const int STATUS_TPM_AUDITFAIL_SUCCESSFUL = -1071054799; + +const int STATUS_TPM_NOTRESETABLE = -1071054798; + +const int STATUS_TPM_NOTLOCAL = -1071054797; + +const int STATUS_TPM_BAD_TYPE = -1071054796; + +const int STATUS_TPM_INVALID_RESOURCE = -1071054795; + +const int STATUS_TPM_NOTFIPS = -1071054794; + +const int STATUS_TPM_INVALID_FAMILY = -1071054793; + +const int STATUS_TPM_NO_NV_PERMISSION = -1071054792; + +const int STATUS_TPM_REQUIRES_SIGN = -1071054791; + +const int STATUS_TPM_KEY_NOTSUPPORTED = -1071054790; + +const int STATUS_TPM_AUTH_CONFLICT = -1071054789; + +const int STATUS_TPM_AREA_LOCKED = -1071054788; + +const int STATUS_TPM_BAD_LOCALITY = -1071054787; + +const int STATUS_TPM_READ_ONLY = -1071054786; + +const int STATUS_TPM_PER_NOWRITE = -1071054785; + +const int STATUS_TPM_FAMILYCOUNT = -1071054784; + +const int STATUS_TPM_WRITE_LOCKED = -1071054783; + +const int STATUS_TPM_BAD_ATTRIBUTES = -1071054782; + +const int STATUS_TPM_INVALID_STRUCTURE = -1071054781; + +const int STATUS_TPM_KEY_OWNER_CONTROL = -1071054780; + +const int STATUS_TPM_BAD_COUNTER = -1071054779; + +const int STATUS_TPM_NOT_FULLWRITE = -1071054778; + +const int STATUS_TPM_CONTEXT_GAP = -1071054777; + +const int STATUS_TPM_MAXNVWRITES = -1071054776; + +const int STATUS_TPM_NOOPERATOR = -1071054775; + +const int STATUS_TPM_RESOURCEMISSING = -1071054774; + +const int STATUS_TPM_DELEGATE_LOCK = -1071054773; + +const int STATUS_TPM_DELEGATE_FAMILY = -1071054772; + +const int STATUS_TPM_DELEGATE_ADMIN = -1071054771; + +const int STATUS_TPM_TRANSPORT_NOTEXCLUSIVE = -1071054770; + +const int STATUS_TPM_OWNER_CONTROL = -1071054769; + +const int STATUS_TPM_DAA_RESOURCES = -1071054768; + +const int STATUS_TPM_DAA_INPUT_DATA0 = -1071054767; + +const int STATUS_TPM_DAA_INPUT_DATA1 = -1071054766; + +const int STATUS_TPM_DAA_ISSUER_SETTINGS = -1071054765; + +const int STATUS_TPM_DAA_TPM_SETTINGS = -1071054764; + +const int STATUS_TPM_DAA_STAGE = -1071054763; + +const int STATUS_TPM_DAA_ISSUER_VALIDITY = -1071054762; + +const int STATUS_TPM_DAA_WRONG_W = -1071054761; + +const int STATUS_TPM_BAD_HANDLE = -1071054760; + +const int STATUS_TPM_BAD_DELEGATE = -1071054759; + +const int STATUS_TPM_BADCONTEXT = -1071054758; + +const int STATUS_TPM_TOOMANYCONTEXTS = -1071054757; + +const int STATUS_TPM_MA_TICKET_SIGNATURE = -1071054756; + +const int STATUS_TPM_MA_DESTINATION = -1071054755; + +const int STATUS_TPM_MA_SOURCE = -1071054754; + +const int STATUS_TPM_MA_AUTHORITY = -1071054753; + +const int STATUS_TPM_PERMANENTEK = -1071054751; + +const int STATUS_TPM_BAD_SIGNATURE = -1071054750; + +const int STATUS_TPM_NOCONTEXTSPACE = -1071054749; + +const int STATUS_TPM_20_E_ASYMMETRIC = -1071054719; + +const int STATUS_TPM_20_E_ATTRIBUTES = -1071054718; + +const int STATUS_TPM_20_E_HASH = -1071054717; + +const int STATUS_TPM_20_E_VALUE = -1071054716; + +const int STATUS_TPM_20_E_HIERARCHY = -1071054715; + +const int STATUS_TPM_20_E_KEY_SIZE = -1071054713; + +const int STATUS_TPM_20_E_MGF = -1071054712; + +const int STATUS_TPM_20_E_MODE = -1071054711; + +const int STATUS_TPM_20_E_TYPE = -1071054710; + +const int STATUS_TPM_20_E_HANDLE = -1071054709; + +const int STATUS_TPM_20_E_KDF = -1071054708; + +const int STATUS_TPM_20_E_RANGE = -1071054707; + +const int STATUS_TPM_20_E_AUTH_FAIL = -1071054706; + +const int STATUS_TPM_20_E_NONCE = -1071054705; + +const int STATUS_TPM_20_E_PP = -1071054704; + +const int STATUS_TPM_20_E_SCHEME = -1071054702; + +const int STATUS_TPM_20_E_SIZE = -1071054699; + +const int STATUS_TPM_20_E_SYMMETRIC = -1071054698; + +const int STATUS_TPM_20_E_TAG = -1071054697; + +const int STATUS_TPM_20_E_SELECTOR = -1071054696; + +const int STATUS_TPM_20_E_INSUFFICIENT = -1071054694; + +const int STATUS_TPM_20_E_SIGNATURE = -1071054693; + +const int STATUS_TPM_20_E_KEY = -1071054692; + +const int STATUS_TPM_20_E_POLICY_FAIL = -1071054691; + +const int STATUS_TPM_20_E_INTEGRITY = -1071054689; + +const int STATUS_TPM_20_E_TICKET = -1071054688; + +const int STATUS_TPM_20_E_RESERVED_BITS = -1071054687; + +const int STATUS_TPM_20_E_BAD_AUTH = -1071054686; + +const int STATUS_TPM_20_E_EXPIRED = -1071054685; + +const int STATUS_TPM_20_E_POLICY_CC = -1071054684; + +const int STATUS_TPM_20_E_BINDING = -1071054683; + +const int STATUS_TPM_20_E_CURVE = -1071054682; + +const int STATUS_TPM_20_E_ECC_POINT = -1071054681; + +const int STATUS_TPM_20_E_INITIALIZE = -1071054592; + +const int STATUS_TPM_20_E_FAILURE = -1071054591; + +const int STATUS_TPM_20_E_SEQUENCE = -1071054589; + +const int STATUS_TPM_20_E_PRIVATE = -1071054581; + +const int STATUS_TPM_20_E_HMAC = -1071054567; + +const int STATUS_TPM_20_E_DISABLED = -1071054560; + +const int STATUS_TPM_20_E_EXCLUSIVE = -1071054559; + +const int STATUS_TPM_20_E_ECC_CURVE = -1071054557; + +const int STATUS_TPM_20_E_AUTH_TYPE = -1071054556; + +const int STATUS_TPM_20_E_AUTH_MISSING = -1071054555; + +const int STATUS_TPM_20_E_POLICY = -1071054554; + +const int STATUS_TPM_20_E_PCR = -1071054553; + +const int STATUS_TPM_20_E_PCR_CHANGED = -1071054552; + +const int STATUS_TPM_20_E_UPGRADE = -1071054547; + +const int STATUS_TPM_20_E_TOO_MANY_CONTEXTS = -1071054546; + +const int STATUS_TPM_20_E_AUTH_UNAVAILABLE = -1071054545; + +const int STATUS_TPM_20_E_REBOOT = -1071054544; + +const int STATUS_TPM_20_E_UNBALANCED = -1071054543; + +const int STATUS_TPM_20_E_COMMAND_SIZE = -1071054526; + +const int STATUS_TPM_20_E_COMMAND_CODE = -1071054525; + +const int STATUS_TPM_20_E_AUTHSIZE = -1071054524; + +const int STATUS_TPM_20_E_AUTH_CONTEXT = -1071054523; + +const int STATUS_TPM_20_E_NV_RANGE = -1071054522; + +const int STATUS_TPM_20_E_NV_SIZE = -1071054521; + +const int STATUS_TPM_20_E_NV_LOCKED = -1071054520; + +const int STATUS_TPM_20_E_NV_AUTHORIZATION = -1071054519; + +const int STATUS_TPM_20_E_NV_UNINITIALIZED = -1071054518; + +const int STATUS_TPM_20_E_NV_SPACE = -1071054517; + +const int STATUS_TPM_20_E_NV_DEFINED = -1071054516; + +const int STATUS_TPM_20_E_BAD_CONTEXT = -1071054512; + +const int STATUS_TPM_20_E_CPHASH = -1071054511; + +const int STATUS_TPM_20_E_PARENT = -1071054510; + +const int STATUS_TPM_20_E_NEEDS_TEST = -1071054509; + +const int STATUS_TPM_20_E_NO_RESULT = -1071054508; + +const int STATUS_TPM_20_E_SENSITIVE = -1071054507; + +const int STATUS_TPM_COMMAND_BLOCKED = -1071053824; + +const int STATUS_TPM_INVALID_HANDLE = -1071053823; + +const int STATUS_TPM_DUPLICATE_VHANDLE = -1071053822; + +const int STATUS_TPM_EMBEDDED_COMMAND_BLOCKED = -1071053821; + +const int STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED = -1071053820; + +const int STATUS_TPM_RETRY = -1071052800; + +const int STATUS_TPM_NEEDS_SELFTEST = -1071052799; + +const int STATUS_TPM_DOING_SELFTEST = -1071052798; + +const int STATUS_TPM_DEFEND_LOCK_RUNNING = -1071052797; + +const int STATUS_TPM_COMMAND_CANCELED = -1071050751; + +const int STATUS_TPM_TOO_MANY_CONTEXTS = -1071050750; + +const int STATUS_TPM_NOT_FOUND = -1071050749; + +const int STATUS_TPM_ACCESS_DENIED = -1071050748; + +const int STATUS_TPM_INSUFFICIENT_BUFFER = -1071050747; + +const int STATUS_TPM_PPI_FUNCTION_UNSUPPORTED = -1071050746; + +const int STATUS_PCP_ERROR_MASK = -1071046656; + +const int STATUS_PCP_DEVICE_NOT_READY = -1071046655; + +const int STATUS_PCP_INVALID_HANDLE = -1071046654; + +const int STATUS_PCP_INVALID_PARAMETER = -1071046653; + +const int STATUS_PCP_FLAG_NOT_SUPPORTED = -1071046652; + +const int STATUS_PCP_NOT_SUPPORTED = -1071046651; + +const int STATUS_PCP_BUFFER_TOO_SMALL = -1071046650; + +const int STATUS_PCP_INTERNAL_ERROR = -1071046649; + +const int STATUS_PCP_AUTHENTICATION_FAILED = -1071046648; + +const int STATUS_PCP_AUTHENTICATION_IGNORED = -1071046647; + +const int STATUS_PCP_POLICY_NOT_FOUND = -1071046646; + +const int STATUS_PCP_PROFILE_NOT_FOUND = -1071046645; + +const int STATUS_PCP_VALIDATION_FAILED = -1071046644; + +const int STATUS_PCP_DEVICE_NOT_FOUND = -1071046643; + +const int STATUS_PCP_WRONG_PARENT = -1071046642; + +const int STATUS_PCP_KEY_NOT_LOADED = -1071046641; + +const int STATUS_PCP_NO_KEY_CERTIFICATION = -1071046640; + +const int STATUS_PCP_KEY_NOT_FINALIZED = -1071046639; + +const int STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET = -1071046638; + +const int STATUS_PCP_NOT_PCR_BOUND = -1071046637; + +const int STATUS_PCP_KEY_ALREADY_FINALIZED = -1071046636; + +const int STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED = -1071046635; + +const int STATUS_PCP_KEY_USAGE_POLICY_INVALID = -1071046634; + +const int STATUS_PCP_SOFT_KEY_ERROR = -1071046633; + +const int STATUS_PCP_KEY_NOT_AUTHENTICATED = -1071046632; + +const int STATUS_PCP_KEY_NOT_AIK = -1071046631; + +const int STATUS_PCP_KEY_NOT_SIGNING_KEY = -1071046630; + +const int STATUS_PCP_LOCKED_OUT = -1071046629; + +const int STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED = -1071046628; + +const int STATUS_PCP_TPM_VERSION_NOT_SUPPORTED = -1071046627; + +const int STATUS_PCP_BUFFER_LENGTH_MISMATCH = -1071046626; + +const int STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED = -1071046625; + +const int STATUS_PCP_TICKET_MISSING = -1071046624; + +const int STATUS_PCP_RAW_POLICY_NOT_SUPPORTED = -1071046623; + +const int STATUS_PCP_KEY_HANDLE_INVALIDATED = -1071046622; + +const int STATUS_PCP_UNSUPPORTED_PSS_SALT = 1076437027; + +const int STATUS_RTPM_CONTEXT_CONTINUE = 2699264; + +const int STATUS_RTPM_CONTEXT_COMPLETE = 2699265; + +const int STATUS_RTPM_NO_RESULT = -1071042558; + +const int STATUS_RTPM_PCR_READ_INCOMPLETE = -1071042557; + +const int STATUS_RTPM_INVALID_CONTEXT = -1071042556; + +const int STATUS_RTPM_UNSUPPORTED_CMD = -1071042555; + +const int STATUS_TPM_ZERO_EXHAUST_ENABLED = -1071038464; + +const int STATUS_HV_INVALID_HYPERCALL_CODE = -1070268414; + +const int STATUS_HV_INVALID_HYPERCALL_INPUT = -1070268413; + +const int STATUS_HV_INVALID_ALIGNMENT = -1070268412; + +const int STATUS_HV_INVALID_PARAMETER = -1070268411; + +const int STATUS_HV_ACCESS_DENIED = -1070268410; + +const int STATUS_HV_INVALID_PARTITION_STATE = -1070268409; + +const int STATUS_HV_OPERATION_DENIED = -1070268408; + +const int STATUS_HV_UNKNOWN_PROPERTY = -1070268407; + +const int STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE = -1070268406; + +const int STATUS_HV_INSUFFICIENT_MEMORY = -1070268405; + +const int STATUS_HV_PARTITION_TOO_DEEP = -1070268404; + +const int STATUS_HV_INVALID_PARTITION_ID = -1070268403; + +const int STATUS_HV_INVALID_VP_INDEX = -1070268402; + +const int STATUS_HV_INVALID_PORT_ID = -1070268399; + +const int STATUS_HV_INVALID_CONNECTION_ID = -1070268398; + +const int STATUS_HV_INSUFFICIENT_BUFFERS = -1070268397; + +const int STATUS_HV_NOT_ACKNOWLEDGED = -1070268396; + +const int STATUS_HV_INVALID_VP_STATE = -1070268395; + +const int STATUS_HV_ACKNOWLEDGED = -1070268394; + +const int STATUS_HV_INVALID_SAVE_RESTORE_STATE = -1070268393; + +const int STATUS_HV_INVALID_SYNIC_STATE = -1070268392; + +const int STATUS_HV_OBJECT_IN_USE = -1070268391; + +const int STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO = -1070268390; + +const int STATUS_HV_NO_DATA = -1070268389; + +const int STATUS_HV_INACTIVE = -1070268388; + +const int STATUS_HV_NO_RESOURCES = -1070268387; + +const int STATUS_HV_FEATURE_UNAVAILABLE = -1070268386; + +const int STATUS_HV_INSUFFICIENT_BUFFER = -1070268365; + +const int STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS = -1070268360; + +const int STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR = -1070268356; + +const int STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR = -1070268355; + +const int STATUS_HV_PROCESSOR_STARTUP_TIMEOUT = -1070268354; + +const int STATUS_HV_SMX_ENABLED = -1070268353; + +const int STATUS_HV_INVALID_LP_INDEX = -1070268351; + +const int STATUS_HV_INVALID_REGISTER_VALUE = -1070268336; + +const int STATUS_HV_INVALID_VTL_STATE = -1070268335; + +const int STATUS_HV_NX_NOT_DETECTED = -1070268331; + +const int STATUS_HV_INVALID_DEVICE_ID = -1070268329; + +const int STATUS_HV_INVALID_DEVICE_STATE = -1070268328; + +const int STATUS_HV_PENDING_PAGE_REQUESTS = 3473497; + +const int STATUS_HV_PAGE_REQUEST_INVALID = -1070268320; + +const int STATUS_HV_INVALID_CPU_GROUP_ID = -1070268305; + +const int STATUS_HV_INVALID_CPU_GROUP_STATE = -1070268304; + +const int STATUS_HV_OPERATION_FAILED = -1070268303; + +const int STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE = -1070268302; + +const int STATUS_HV_INSUFFICIENT_ROOT_MEMORY = -1070268301; + +const int STATUS_HV_NOT_PRESENT = -1070264320; + +const int STATUS_VID_DUPLICATE_HANDLER = -1070137343; + +const int STATUS_VID_TOO_MANY_HANDLERS = -1070137342; + +const int STATUS_VID_QUEUE_FULL = -1070137341; + +const int STATUS_VID_HANDLER_NOT_PRESENT = -1070137340; + +const int STATUS_VID_INVALID_OBJECT_NAME = -1070137339; + +const int STATUS_VID_PARTITION_NAME_TOO_LONG = -1070137338; + +const int STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG = -1070137337; + +const int STATUS_VID_PARTITION_ALREADY_EXISTS = -1070137336; + +const int STATUS_VID_PARTITION_DOES_NOT_EXIST = -1070137335; + +const int STATUS_VID_PARTITION_NAME_NOT_FOUND = -1070137334; + +const int STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS = -1070137333; + +const int STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT = -1070137332; + +const int STATUS_VID_MB_STILL_REFERENCED = -1070137331; + +const int STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED = -1070137330; + +const int STATUS_VID_INVALID_NUMA_SETTINGS = -1070137329; + +const int STATUS_VID_INVALID_NUMA_NODE_INDEX = -1070137328; + +const int STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED = -1070137327; + +const int STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE = -1070137326; + +const int STATUS_VID_PAGE_RANGE_OVERFLOW = -1070137325; + +const int STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE = -1070137324; + +const int STATUS_VID_INVALID_GPA_RANGE_HANDLE = -1070137323; + +const int STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE = -1070137322; + +const int STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED = -1070137321; + +const int STATUS_VID_INVALID_PPM_HANDLE = -1070137320; + +const int STATUS_VID_MBPS_ARE_LOCKED = -1070137319; + +const int STATUS_VID_MESSAGE_QUEUE_CLOSED = -1070137318; + +const int STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED = -1070137317; + +const int STATUS_VID_STOP_PENDING = -1070137316; + +const int STATUS_VID_INVALID_PROCESSOR_STATE = -1070137315; + +const int STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT = -1070137314; + +const int STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED = -1070137313; + +const int STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET = -1070137312; + +const int STATUS_VID_MMIO_RANGE_DESTROYED = -1070137311; + +const int STATUS_VID_INVALID_CHILD_GPA_PAGE_SET = -1070137310; + +const int STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED = -1070137309; + +const int STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL = -1070137308; + +const int STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE = -1070137307; + +const int STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT = -1070137306; + +const int STATUS_VID_SAVED_STATE_CORRUPT = -1070137305; + +const int STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM = -1070137304; + +const int STATUS_VID_SAVED_STATE_INCOMPATIBLE = -1070137303; + +const int STATUS_VID_VTL_ACCESS_DENIED = -1070137302; + +const int STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED = -2143879167; + +const int STATUS_IPSEC_BAD_SPI = -1070202879; + +const int STATUS_IPSEC_SA_LIFETIME_EXPIRED = -1070202878; + +const int STATUS_IPSEC_WRONG_SA = -1070202877; + +const int STATUS_IPSEC_REPLAY_CHECK_FAILED = -1070202876; + +const int STATUS_IPSEC_INVALID_PACKET = -1070202875; + +const int STATUS_IPSEC_INTEGRITY_CHECK_FAILED = -1070202874; + +const int STATUS_IPSEC_CLEAR_TEXT_DROP = -1070202873; + +const int STATUS_IPSEC_AUTH_FIREWALL_DROP = -1070202872; + +const int STATUS_IPSEC_THROTTLE_DROP = -1070202871; + +const int STATUS_IPSEC_DOSP_BLOCK = -1070170112; + +const int STATUS_IPSEC_DOSP_RECEIVED_MULTICAST = -1070170111; + +const int STATUS_IPSEC_DOSP_INVALID_PACKET = -1070170110; + +const int STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED = -1070170109; + +const int STATUS_IPSEC_DOSP_MAX_ENTRIES = -1070170108; + +const int STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED = -1070170107; + +const int STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = -1070170106; + +const int STATUS_VOLMGR_INCOMPLETE_REGENERATION = -2143813631; + +const int STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION = -2143813630; + +const int STATUS_VOLMGR_DATABASE_FULL = -1070071807; + +const int STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED = -1070071806; + +const int STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC = -1070071805; + +const int STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED = -1070071804; + +const int STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME = -1070071803; + +const int STATUS_VOLMGR_DISK_DUPLICATE = -1070071802; + +const int STATUS_VOLMGR_DISK_DYNAMIC = -1070071801; + +const int STATUS_VOLMGR_DISK_ID_INVALID = -1070071800; + +const int STATUS_VOLMGR_DISK_INVALID = -1070071799; + +const int STATUS_VOLMGR_DISK_LAST_VOTER = -1070071798; + +const int STATUS_VOLMGR_DISK_LAYOUT_INVALID = -1070071797; + +const int STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS = + -1070071796; + +const int STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED = -1070071795; + +const int STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL = -1070071794; + +const int STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS = + -1070071793; + +const int STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS = -1070071792; + +const int STATUS_VOLMGR_DISK_MISSING = -1070071791; + +const int STATUS_VOLMGR_DISK_NOT_EMPTY = -1070071790; + +const int STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE = -1070071789; + +const int STATUS_VOLMGR_DISK_REVECTORING_FAILED = -1070071788; + +const int STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID = -1070071787; + +const int STATUS_VOLMGR_DISK_SET_NOT_CONTAINED = -1070071786; + +const int STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS = -1070071785; + +const int STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES = -1070071784; + +const int STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED = -1070071783; + +const int STATUS_VOLMGR_EXTENT_ALREADY_USED = -1070071782; + +const int STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS = -1070071781; + +const int STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION = -1070071780; + +const int STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED = -1070071779; + +const int STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION = -1070071778; + +const int STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH = -1070071777; + +const int STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED = -1070071776; + +const int STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID = -1070071775; + +const int STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS = -1070071774; + +const int STATUS_VOLMGR_MEMBER_IN_SYNC = -1070071773; + +const int STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE = -1070071772; + +const int STATUS_VOLMGR_MEMBER_INDEX_INVALID = -1070071771; + +const int STATUS_VOLMGR_MEMBER_MISSING = -1070071770; + +const int STATUS_VOLMGR_MEMBER_NOT_DETACHED = -1070071769; + +const int STATUS_VOLMGR_MEMBER_REGENERATING = -1070071768; + +const int STATUS_VOLMGR_ALL_DISKS_FAILED = -1070071767; + +const int STATUS_VOLMGR_NO_REGISTERED_USERS = -1070071766; + +const int STATUS_VOLMGR_NO_SUCH_USER = -1070071765; + +const int STATUS_VOLMGR_NOTIFICATION_RESET = -1070071764; + +const int STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID = -1070071763; + +const int STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID = -1070071762; + +const int STATUS_VOLMGR_PACK_DUPLICATE = -1070071761; + +const int STATUS_VOLMGR_PACK_ID_INVALID = -1070071760; + +const int STATUS_VOLMGR_PACK_INVALID = -1070071759; + +const int STATUS_VOLMGR_PACK_NAME_INVALID = -1070071758; + +const int STATUS_VOLMGR_PACK_OFFLINE = -1070071757; + +const int STATUS_VOLMGR_PACK_HAS_QUORUM = -1070071756; + +const int STATUS_VOLMGR_PACK_WITHOUT_QUORUM = -1070071755; + +const int STATUS_VOLMGR_PARTITION_STYLE_INVALID = -1070071754; + +const int STATUS_VOLMGR_PARTITION_UPDATE_FAILED = -1070071753; + +const int STATUS_VOLMGR_PLEX_IN_SYNC = -1070071752; + +const int STATUS_VOLMGR_PLEX_INDEX_DUPLICATE = -1070071751; + +const int STATUS_VOLMGR_PLEX_INDEX_INVALID = -1070071750; + +const int STATUS_VOLMGR_PLEX_LAST_ACTIVE = -1070071749; + +const int STATUS_VOLMGR_PLEX_MISSING = -1070071748; + +const int STATUS_VOLMGR_PLEX_REGENERATING = -1070071747; + +const int STATUS_VOLMGR_PLEX_TYPE_INVALID = -1070071746; + +const int STATUS_VOLMGR_PLEX_NOT_RAID5 = -1070071745; + +const int STATUS_VOLMGR_PLEX_NOT_SIMPLE = -1070071744; + +const int STATUS_VOLMGR_STRUCTURE_SIZE_INVALID = -1070071743; + +const int STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS = -1070071742; + +const int STATUS_VOLMGR_TRANSACTION_IN_PROGRESS = -1070071741; + +const int STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE = -1070071740; + +const int STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK = -1070071739; + +const int STATUS_VOLMGR_VOLUME_ID_INVALID = -1070071738; + +const int STATUS_VOLMGR_VOLUME_LENGTH_INVALID = -1070071737; + +const int STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE = -1070071736; + +const int STATUS_VOLMGR_VOLUME_NOT_MIRRORED = -1070071735; + +const int STATUS_VOLMGR_VOLUME_NOT_RETAINED = -1070071734; + +const int STATUS_VOLMGR_VOLUME_OFFLINE = -1070071733; + +const int STATUS_VOLMGR_VOLUME_RETAINED = -1070071732; + +const int STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID = -1070071731; + +const int STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE = -1070071730; + +const int STATUS_VOLMGR_BAD_BOOT_DISK = -1070071729; + +const int STATUS_VOLMGR_PACK_CONFIG_OFFLINE = -1070071728; + +const int STATUS_VOLMGR_PACK_CONFIG_ONLINE = -1070071727; + +const int STATUS_VOLMGR_NOT_PRIMARY_PACK = -1070071726; + +const int STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED = -1070071725; + +const int STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID = -1070071724; + +const int STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID = -1070071723; + +const int STATUS_VOLMGR_VOLUME_MIRRORED = -1070071722; + +const int STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED = -1070071721; + +const int STATUS_VOLMGR_NO_VALID_LOG_COPIES = -1070071720; + +const int STATUS_VOLMGR_PRIMARY_PACK_PRESENT = -1070071719; + +const int STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID = -1070071718; + +const int STATUS_VOLMGR_MIRROR_NOT_SUPPORTED = -1070071717; + +const int STATUS_VOLMGR_RAID5_NOT_SUPPORTED = -1070071716; + +const int STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED = -2143748095; + +const int STATUS_BCD_TOO_MANY_ELEMENTS = -1070006270; + +const int STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED = -2143748093; + +const int STATUS_VHD_DRIVE_FOOTER_MISSING = -1069940735; + +const int STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH = -1069940734; + +const int STATUS_VHD_DRIVE_FOOTER_CORRUPT = -1069940733; + +const int STATUS_VHD_FORMAT_UNKNOWN = -1069940732; + +const int STATUS_VHD_FORMAT_UNSUPPORTED_VERSION = -1069940731; + +const int STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH = -1069940730; + +const int STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION = -1069940729; + +const int STATUS_VHD_SPARSE_HEADER_CORRUPT = -1069940728; + +const int STATUS_VHD_BLOCK_ALLOCATION_FAILURE = -1069940727; + +const int STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT = -1069940726; + +const int STATUS_VHD_INVALID_BLOCK_SIZE = -1069940725; + +const int STATUS_VHD_BITMAP_MISMATCH = -1069940724; + +const int STATUS_VHD_PARENT_VHD_NOT_FOUND = -1069940723; + +const int STATUS_VHD_CHILD_PARENT_ID_MISMATCH = -1069940722; + +const int STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH = -1069940721; + +const int STATUS_VHD_METADATA_READ_FAILURE = -1069940720; + +const int STATUS_VHD_METADATA_WRITE_FAILURE = -1069940719; + +const int STATUS_VHD_INVALID_SIZE = -1069940718; + +const int STATUS_VHD_INVALID_FILE_SIZE = -1069940717; + +const int STATUS_VIRTDISK_PROVIDER_NOT_FOUND = -1069940716; + +const int STATUS_VIRTDISK_NOT_VIRTUAL_DISK = -1069940715; + +const int STATUS_VHD_PARENT_VHD_ACCESS_DENIED = -1069940714; + +const int STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH = -1069940713; + +const int STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED = -1069940712; + +const int STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT = -1069940711; + +const int STATUS_VIRTUAL_DISK_LIMITATION = -1069940710; + +const int STATUS_VHD_INVALID_TYPE = -1069940709; + +const int STATUS_VHD_INVALID_STATE = -1069940708; + +const int STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE = -1069940707; + +const int STATUS_VIRTDISK_DISK_ALREADY_OWNED = -1069940706; + +const int STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE = -1069940705; + +const int STATUS_CTLOG_TRACKING_NOT_INITIALIZED = -1069940704; + +const int STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE = -1069940703; + +const int STATUS_CTLOG_VHD_CHANGED_OFFLINE = -1069940702; + +const int STATUS_CTLOG_INVALID_TRACKING_STATE = -1069940701; + +const int STATUS_CTLOG_INCONSISTENT_TRACKING_FILE = -1069940700; + +const int STATUS_VHD_METADATA_FULL = -1069940696; + +const int STATUS_VHD_INVALID_CHANGE_TRACKING_ID = -1069940695; + +const int STATUS_VHD_CHANGE_TRACKING_DISABLED = -1069940694; + +const int STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION = -1069940688; + +const int STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA = -1069940687; + +const int STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE = -1069940686; + +const int STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE = -1069940685; + +const int STATUS_QUERY_STORAGE_ERROR = -2143682559; + +const int STATUS_GDI_HANDLE_LEAK = -2143354879; + +const int STATUS_RKF_KEY_NOT_FOUND = -1069547519; + +const int STATUS_RKF_DUPLICATE_KEY = -1069547518; + +const int STATUS_RKF_BLOB_FULL = -1069547517; + +const int STATUS_RKF_STORE_FULL = -1069547516; + +const int STATUS_RKF_FILE_BLOCKED = -1069547515; + +const int STATUS_RKF_ACTIVE_KEY = -1069547514; + +const int STATUS_RDBSS_RESTART_OPERATION = -1069481983; + +const int STATUS_RDBSS_CONTINUE_OPERATION = -1069481982; + +const int STATUS_RDBSS_POST_OPERATION = -1069481981; + +const int STATUS_RDBSS_RETRY_LOOKUP = -1069481980; + +const int STATUS_BTH_ATT_INVALID_HANDLE = -1069416447; + +const int STATUS_BTH_ATT_READ_NOT_PERMITTED = -1069416446; + +const int STATUS_BTH_ATT_WRITE_NOT_PERMITTED = -1069416445; + +const int STATUS_BTH_ATT_INVALID_PDU = -1069416444; + +const int STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION = -1069416443; + +const int STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED = -1069416442; + +const int STATUS_BTH_ATT_INVALID_OFFSET = -1069416441; + +const int STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION = -1069416440; + +const int STATUS_BTH_ATT_PREPARE_QUEUE_FULL = -1069416439; + +const int STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND = -1069416438; + +const int STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG = -1069416437; + +const int STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE = -1069416436; + +const int STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH = -1069416435; + +const int STATUS_BTH_ATT_UNLIKELY = -1069416434; + +const int STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION = -1069416433; + +const int STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE = -1069416432; + +const int STATUS_BTH_ATT_INSUFFICIENT_RESOURCES = -1069416431; + +const int STATUS_BTH_ATT_UNKNOWN_ERROR = -1069412352; + +const int STATUS_SECUREBOOT_ROLLBACK_DETECTED = -1069350911; + +const int STATUS_SECUREBOOT_POLICY_VIOLATION = -1069350910; + +const int STATUS_SECUREBOOT_INVALID_POLICY = -1069350909; + +const int STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = -1069350908; + +const int STATUS_SECUREBOOT_POLICY_NOT_SIGNED = -1069350907; + +const int STATUS_SECUREBOOT_NOT_ENABLED = -2143092730; + +const int STATUS_SECUREBOOT_FILE_REPLACED = -1069350905; + +const int STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED = -1069350904; + +const int STATUS_SECUREBOOT_POLICY_UNKNOWN = -1069350903; + +const int STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION = -1069350902; + +const int STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH = -1069350901; + +const int STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED = -1069350900; + +const int STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH = -1069350899; + +const int STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING = -1069350898; + +const int STATUS_SECUREBOOT_NOT_BASE_POLICY = -1069350897; + +const int STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY = -1069350896; + +const int STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED = -1058340863; + +const int STATUS_PLATFORM_MANIFEST_INVALID = -1058340862; + +const int STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED = -1058340861; + +const int STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED = -1058340860; + +const int STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND = -1058340859; + +const int STATUS_PLATFORM_MANIFEST_NOT_ACTIVE = -1058340858; + +const int STATUS_PLATFORM_MANIFEST_NOT_SIGNED = -1058340857; + +const int STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED = -1058471935; + +const int STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION = -1058471934; + +const int STATUS_SYSTEM_INTEGRITY_INVALID_POLICY = -1058471933; + +const int STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED = -1058471932; + +const int STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES = -1058471931; + +const int STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED = + -1058471930; + +const int STATUS_NO_APPLICABLE_APP_LICENSES_FOUND = -1058406399; + +const int STATUS_CLIP_LICENSE_NOT_FOUND = -1058406398; + +const int STATUS_CLIP_DEVICE_LICENSE_MISSING = -1058406397; + +const int STATUS_CLIP_LICENSE_INVALID_SIGNATURE = -1058406396; + +const int STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID = -1058406395; + +const int STATUS_CLIP_LICENSE_EXPIRED = -1058406394; + +const int STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE = -1058406393; + +const int STATUS_CLIP_LICENSE_NOT_SIGNED = -1058406392; + +const int STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE = -1058406391; + +const int STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH = -1058406390; + +const int STATUS_AUDIO_ENGINE_NODE_NOT_FOUND = -1069285375; + +const int STATUS_HDAUDIO_EMPTY_CONNECTION_LIST = -1069285374; + +const int STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED = -1069285373; + +const int STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED = -1069285372; + +const int STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY = -1069285371; + +const int STATUS_SPACES_REPAIRED = 15138816; + +const int STATUS_SPACES_PAUSE = 15138817; + +const int STATUS_SPACES_COMPLETE = 15138818; + +const int STATUS_SPACES_REDIRECT = 15138819; + +const int STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID = -1058603007; + +const int STATUS_SPACES_RESILIENCY_TYPE_INVALID = -1058603005; + +const int STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID = -1058603004; + +const int STATUS_SPACES_DRIVE_REDUNDANCY_INVALID = -1058603002; + +const int STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID = -1058603001; + +const int STATUS_SPACES_INTERLEAVE_LENGTH_INVALID = -1058602999; + +const int STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID = -1058602998; + +const int STATUS_SPACES_NOT_ENOUGH_DRIVES = -1058602997; + +const int STATUS_SPACES_EXTENDED_ERROR = -1058602996; + +const int STATUS_SPACES_PROVISIONING_TYPE_INVALID = -1058602995; + +const int STATUS_SPACES_ALLOCATION_SIZE_INVALID = -1058602994; + +const int STATUS_SPACES_ENCLOSURE_AWARE_INVALID = -1058602993; + +const int STATUS_SPACES_WRITE_CACHE_SIZE_INVALID = -1058602992; + +const int STATUS_SPACES_NUMBER_OF_GROUPS_INVALID = -1058602991; + +const int STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID = -1058602990; + +const int STATUS_SPACES_UPDATE_COLUMN_STATE = -1058602989; + +const int STATUS_SPACES_MAP_REQUIRED = -1058602988; + +const int STATUS_SPACES_UNSUPPORTED_VERSION = -1058602987; + +const int STATUS_SPACES_CORRUPT_METADATA = -1058602986; + +const int STATUS_SPACES_DRT_FULL = -1058602985; + +const int STATUS_SPACES_INCONSISTENCY = -1058602984; + +const int STATUS_SPACES_LOG_NOT_READY = -1058602983; + +const int STATUS_SPACES_NO_REDUNDANCY = -1058602982; + +const int STATUS_SPACES_DRIVE_NOT_READY = -1058602981; + +const int STATUS_SPACES_DRIVE_SPLIT = -1058602980; + +const int STATUS_SPACES_DRIVE_LOST_DATA = -1058602979; + +const int STATUS_SPACES_ENTRY_INCOMPLETE = -1058602978; + +const int STATUS_SPACES_ENTRY_INVALID = -1058602977; + +const int STATUS_SPACES_MARK_DIRTY = -1058602976; + +const int STATUS_VOLSNAP_BOOTFILE_NOT_VALID = -1068498941; + +const int STATUS_VOLSNAP_ACTIVATION_TIMEOUT = -1068498940; + +const int STATUS_IO_PREEMPTED = -1068433407; + +const int STATUS_SVHDX_ERROR_STORED = -1067712512; + +const int STATUS_SVHDX_ERROR_NOT_AVAILABLE = -1067647232; + +const int STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE = -1067647231; + +const int STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED = -1067647230; + +const int STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED = -1067647229; + +const int STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED = -1067647228; + +const int STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED = -1067647227; + +const int STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED = + -1067647226; + +const int STATUS_SVHDX_RESERVATION_CONFLICT = -1067647225; + +const int STATUS_SVHDX_WRONG_FILE_TYPE = -1067647224; + +const int STATUS_SVHDX_VERSION_MISMATCH = -1067647223; + +const int STATUS_VHD_SHARED = -1067647222; + +const int STATUS_SVHDX_NO_INITIATOR = -1067647221; + +const int STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND = -1067647220; + +const int STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP = -1067646976; + +const int STATUS_SMB_BAD_CLUSTER_DIALECT = -1067646975; + +const int STATUS_SMB_GUEST_LOGON_BLOCKED = -1067646974; + +const int STATUS_SECCORE_INVALID_COMMAND = -1058537472; + +const int STATUS_VSM_NOT_INITIALIZED = -1069219840; + +const int STATUS_VSM_DMA_PROTECTION_NOT_IN_USE = -1069219839; + +const int STATUS_APPEXEC_CONDITION_NOT_SATISFIED = -1058275328; + +const int STATUS_APPEXEC_HANDLE_INVALIDATED = -1058275327; + +const int STATUS_APPEXEC_INVALID_HOST_GENERATION = -1058275326; + +const int STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION = -1058275325; + +const int STATUS_APPEXEC_INVALID_HOST_STATE = -1058275324; + +const int STATUS_APPEXEC_NO_DONOR = -1058275323; + +const int STATUS_APPEXEC_HOST_ID_MISMATCH = -1058275322; + +const int STATUS_APPEXEC_UNKNOWN_USER = -1058275321; diff --git a/packages/ntquerysysteminformation/example/ntstatus/ntstatus.yaml b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.yaml new file mode 100644 index 00000000..c8c641fd --- /dev/null +++ b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.yaml @@ -0,0 +1,11 @@ +name: ntstatus +description: Bindings to `ntstatus.h`. +output: 'example/ntstatus/ntstatus.dart' +headers: + entry-points: + - 'example/ntstatus/_ntstatus.h' + include-directives: # include only these header files and necessary structs from other header files + - '**ntstatus.h' +size-map: + long: 4 + unsigned long: 4 \ No newline at end of file diff --git a/packages/ntquerysysteminformation/lib/dynamic_load.dart b/packages/ntquerysysteminformation/lib/dynamic_load.dart new file mode 100644 index 00000000..624398c4 --- /dev/null +++ b/packages/ntquerysysteminformation/lib/dynamic_load.dart @@ -0,0 +1,14 @@ +import 'package:ffi/ffi.dart'; +import 'package:win32/win32.dart'; + +int getFuncAddress(String module, String func) { + return using((Arena arena) { + final hModule = GetModuleHandle(module.toNativeUtf16(allocator: arena)); + if (hModule == NULL) throw Exception('Could not load $module'); + + final pFuncAddress = GetProcAddress(hModule, func.toANSI(allocator: arena)); + if (pFuncAddress == NULL) throw Exception('Could not find $func()'); + + return pFuncAddress; + }); +} diff --git a/packages/ntquerysysteminformation/pubspec.lock b/packages/ntquerysysteminformation/pubspec.lock new file mode 100644 index 00000000..d014105a --- /dev/null +++ b/packages/ntquerysysteminformation/pubspec.lock @@ -0,0 +1,152 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + ffi: + dependency: "direct main" + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + ffigen: + dependency: "direct dev" + description: + name: ffigen + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0-dev.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.1" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.0" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + win32: + dependency: "direct main" + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.14.0-115.0.dev <3.0.0" diff --git a/packages/ntquerysysteminformation/pubspec.yaml b/packages/ntquerysysteminformation/pubspec.yaml new file mode 100644 index 00000000..eed670e1 --- /dev/null +++ b/packages/ntquerysysteminformation/pubspec.yaml @@ -0,0 +1,15 @@ +name: dynamic_load +description: A simple command-line application. +version: 1.0.0 +# homepage: https://www.example.com + +environment: + sdk: '>=2.14.0-115.0.dev <3.0.0' + +dependencies: + ffi: ^1.1.0 + win32: ^2.1.1 + +dev_dependencies: + pedantic: ^1.10.0 + ffigen: ^4.0.0-dev.2 From ece0404bd0e8f656d678a94fb472e77554383938 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:22:14 -0400 Subject: [PATCH 46/83] Ignore warnings from experiments --- .../example/NtQuerySystemInformation.dart | 5 +++-- .../ntquerysysteminformation/example/ntdll/_winternl.dart | 2 ++ .../ntquerysysteminformation/example/ntstatus/ntstatus.dart | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart b/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart index 93f3582e..09c3b7f1 100644 --- a/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart +++ b/packages/ntquerysysteminformation/example/NtQuerySystemInformation.dart @@ -1,4 +1,4 @@ -// ignore_for_file: omit_local_variable_types +// ignore_for_file: omit_local_variable_types, unused_local_variable import 'dart:ffi'; @@ -27,8 +27,9 @@ void main() { pBuffer.cast(), pNeedSize.value, nullptr); - if (status < 0) + if (status < 0) { throw Exception('Query SystemProcessInformation error: $status'); + } var address = pBuffer.address; var nextEntryOffset = 0; diff --git a/packages/ntquerysysteminformation/example/ntdll/_winternl.dart b/packages/ntquerysysteminformation/example/ntdll/_winternl.dart index dd2d86e3..5b261b46 100644 --- a/packages/ntquerysysteminformation/example/ntdll/_winternl.dart +++ b/packages/ntquerysysteminformation/example/ntdll/_winternl.dart @@ -1,6 +1,8 @@ // AUTO GENERATED FILE, DO NOT EDIT. // // Generated by `package:ffigen`. +// ignore_for_file: unused_element, unused_field + import 'dart:ffi' as ffi; /// Bindings to `winternl.h`. diff --git a/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart index b833efd1..a1b4cfeb 100644 --- a/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart +++ b/packages/ntquerysysteminformation/example/ntstatus/ntstatus.dart @@ -1,6 +1,8 @@ // AUTO GENERATED FILE, DO NOT EDIT. // // Generated by `package:ffigen`. +// ignore_for_file: unused_import + import 'dart:ffi' as ffi; const int STATUS_WAIT_0 = 0; From 7e081a07d83ac9b42a45ad0a636f9c6176ca2dc6 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:15:17 -0400 Subject: [PATCH 47/83] Refactor toggle active to seperate dart sub-app --- .gitignore | 1 + .../active_window/active_window.dart | 184 ------------------ lib/domain/arguments/argument_parser.dart | 19 -- lib/main.dart | 4 - packages/active_window/.gitignore | 6 + packages/active_window/.vscode/launch.json | 13 ++ packages/active_window/CHANGELOG.md | 3 + packages/active_window/README.md | 1 + packages/active_window/analysis_options.yaml | 5 + .../bin/toggle_active_window.dart | 48 +++++ .../hotkey/toggle_active_hotkey.ahk | 19 ++ packages/active_window/lib/active_window.dart | 4 + .../active_window/lib/src/active_window.dart | 89 +++++++++ packages/active_window/lib/src/logger.dart | 20 ++ packages/active_window/pubspec.lock | 96 +++++++++ packages/active_window/pubspec.yaml | 16 ++ .../lib/src/active_window.dart | 28 +++ .../native_platform/lib/src/linux/linux.dart | 15 ++ .../lib/src/native_platform.dart | 3 + .../native_platform/lib/src/win32/win32.dart | 15 ++ packages/native_platform/pubspec.yaml | 1 + test/window/active_window_test.dart | 40 ---- 22 files changed, 383 insertions(+), 247 deletions(-) delete mode 100644 lib/application/active_window/active_window.dart create mode 100644 packages/active_window/.gitignore create mode 100644 packages/active_window/.vscode/launch.json create mode 100644 packages/active_window/CHANGELOG.md create mode 100644 packages/active_window/README.md create mode 100644 packages/active_window/analysis_options.yaml create mode 100644 packages/active_window/bin/toggle_active_window.dart create mode 100644 packages/active_window/hotkey/toggle_active_hotkey.ahk create mode 100644 packages/active_window/lib/active_window.dart create mode 100644 packages/active_window/lib/src/active_window.dart create mode 100644 packages/active_window/lib/src/logger.dart create mode 100644 packages/active_window/pubspec.lock create mode 100644 packages/active_window/pubspec.yaml create mode 100644 packages/native_platform/lib/src/active_window.dart delete mode 100644 test/window/active_window_test.dart diff --git a/.gitignore b/.gitignore index dbdb1ac7..96a13f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Packaging output *.AppImage +*.exe *.snap *.zsync appimage-builder-cache diff --git a/lib/application/active_window/active_window.dart b/lib/application/active_window/active_window.dart deleted file mode 100644 index 1da7591d..00000000 --- a/lib/application/active_window/active_window.dart +++ /dev/null @@ -1,184 +0,0 @@ -import 'dart:io' as io; - -import 'package:flutter/foundation.dart'; -import 'package:logging/logging.dart'; -import 'package:native_platform/native_platform.dart'; -import 'package:nyrna/domain/arguments/argument_parser.dart'; -import 'package:nyrna/infrastructure/logger/log_file.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:win32/win32.dart'; - -/// Represents the active, foreground window on the system. -/// -/// Initialize() must be called before anything else. -class ActiveWindow { - final _nativePlatform = NativePlatform(); - - static final _log = Logger('ActiveWindow'); - - final _prefs = Preferences(); - - /// Nyrna's own PID. - final int nyrnaPid = io.pid; - - late int? id; - - late int pid; - - @visibleForTesting - Future initialize() async { - pid = await _nativePlatform.activeWindowPid; - await _verifyPid(); - id = await _nativePlatform.activeWindowId; - } - - /// Hide the Nyrna window. - /// - /// Necessary when using the toggle active window feature, - /// until Flutter has a way to run without GUI. - Future _hideNyrna() async { - switch (io.Platform.operatingSystem) { - case 'linux': - await _hideLinux(); - break; - case 'windows': - await _hideWindows(); - break; - default: - break; - } - } - - /// Hide own window using `xdotool`. - Future _hideLinux() async { - await io.Process.run( - 'xdotool', - ['getactivewindow', 'windowminimize', '--sync'], - ); - } - - /// Hide own window using the win32 API. - Future _hideWindows() async { - var id = GetForegroundWindow(); - // We would prefer SW_HIDE, however that leaves Nyrna still - // considered the foreground window. So, minimize instead. - ShowWindow(id, SW_FORCEMINIMIZE); - } - - int? _getSavedProcess() => _prefs.getInt('savedProcess'); - - Future _setSavedProcess(int pid) async { - await _prefs.setInt(key: 'savedProcess', value: pid); - } - - /// The unique hex ID of the window suspended via [ActiveWindow.toggle()]. - int? _getSavedWindowId() => _prefs.getInt('savedWindowId'); - - Future _setSavedWindowId(int id) async { - await _prefs.setInt(key: 'savedWindowId', value: id); - } - - Future _removeSavedProcess() async { - await _prefs.remove('savedProcess'); - await _prefs.remove('savedWindowId'); - } - - Future _verifyPid() async { - // Verify active window wasn't Nyrna. - // This _could_ happen because we have to hide Nyrna's window instead of - // just not running the GUI for now. Sanity check: don't suspend self. - if (pid == nyrnaPid) { - _log.severe("Active window PID was Nyrna's own, exiting."); - if (ArgumentParser.logToFile) await LogFile.instance.write(); - io.exit(1); - } - final savedProcess = _getSavedProcess(); - if (savedProcess != null) await _checkStillExists(savedProcess); - } - - /// Check that saved process still exists. - Future _checkStillExists(int savedPid) async { - final savedProcess = NativeProcess(savedPid); - final exists = await savedProcess.exists(); - if (!exists) { - await _removeSavedProcess(); - _log.warning('Saved pid no longer exists, removed.'); - if (ArgumentParser.logToFile) await LogFile.instance.write(); - io.exit(0); - } - } - - /// Toggle the suspend / resume state of the given process. - Future _toggleProcess() async { - final savedProcess = _getSavedProcess(); - final savedWindowId = _getSavedWindowId(); - if ((savedProcess != null) && (savedWindowId != null)) { - final successful = await _resume( - pid: savedProcess, - id: savedWindowId, - ); - return successful; - } else { - final successful = await _suspend(); - return successful; - } - } - - Future _resume({ - required int pid, - required int id, - }) async { - var successful = false; - final process = NativeProcess(pid); - final _status = await process.status; - if (_status == ProcessStatus.unknown) { - await _removeSavedProcess(); - _log.warning('Issue getting status, removed saved process.'); - } - if (_status == ProcessStatus.suspended) { - successful = await process.toggle(); - await _removeSavedProcess(); - if (!successful) { - _log.warning('Failed to resume PID: $pid'); - return successful; - } - await NativePlatform().restoreWindow(id); - } - return successful; - } - - Future _suspend() async { - var successful = false; - final process = NativeProcess(pid); - await NativePlatform().minimizeWindow(id!); - // Small delay on Windows to ensure the window actually minimizes. - // Doesn't seem to be necessary on Linux. - if (io.Platform.isWindows) { - await Future.delayed(Duration(milliseconds: 500)); - } - successful = await process.toggle(); - await _setSavedProcess(pid); - await _setSavedWindowId(id!); - if (!successful) { - _log.warning('Failed to suspend PID: $pid'); - } - return successful; - } - - /// Toggle suspend / resume for the active, foreground window. - Future toggle() async { - final _log = Logger('toggleActiveWindow'); - _log.info('toggleActiveWindow beginning'); - await _hideNyrna(); - await initialize(); - final successful = await _toggleProcess(); - if (!successful) { - await _removeSavedProcess(); - _log.warning('Failed to toggle active window. Cleared saved pid.'); - } - _log.info('Finished toggle window, exiting.'); - if (ArgumentParser.logToFile) await LogFile.instance.write(); - // Not yet possible to run without GUI, so we just exit after toggling. - io.exit(0); - } -} diff --git a/lib/domain/arguments/argument_parser.dart b/lib/domain/arguments/argument_parser.dart index 71f67395..fc936b44 100644 --- a/lib/domain/arguments/argument_parser.dart +++ b/lib/domain/arguments/argument_parser.dart @@ -5,11 +5,7 @@ import 'package:nyrna/infrastructure/logger/log_file.dart'; /// Parse command-line arguments. /// -/// `Toggle` flag available with `-t` or `--toggle`. -/// /// `Logger` flag available with `-l` or `--log`. -/// -/// Both options available with `-tl`. class ArgumentParser { ArgumentParser(this.args) { _setFlags(); @@ -20,15 +16,6 @@ class ArgumentParser { final _parser = ArgParser(); void _setFlags() { - // Toggle flag means Nyrna should toggle the suspend / resume state of the - // active application and then exit. Needed as a workaround since Flutter - // doesn't currently support a global hotkey. Not reliable if Nyrna is - // already running. - _parser.addFlag( - 'toggle', - abbr: 't', - defaultsTo: false, - ); // Log flag is to enable conditional use of the Logger() class for debug. _parser.addFlag( 'log', @@ -54,12 +41,6 @@ class ArgumentParser { } } - /// Check if `toggle` flag was received. - /// - /// If toggle is true => toggle suspend for active window, - /// do not load GUI. - bool get toggleFlagged => _results.wasParsed('toggle'); - static bool _logToFile = false; static bool get logToFile => _logToFile; diff --git a/lib/main.dart b/lib/main.dart index 98295cde..aa3d0a68 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,6 @@ import 'package:nyrna/infrastructure/logger/app_logger.dart'; import 'package:nyrna/infrastructure/versions/versions.dart'; import 'package:nyrna/presentation/app_widget.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/application/active_window/active_window.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'application/app/app.dart'; @@ -24,9 +23,6 @@ Future main(List args) async { AppLogger().initialize(); - // `-t` or `--toggle` flag detected. - if (parser.toggleFlagged) await ActiveWindow().toggle(); - Bloc.observer = AppBlocObserver(); final nativePlatform = NativePlatform(); diff --git a/packages/active_window/.gitignore b/packages/active_window/.gitignore new file mode 100644 index 00000000..3c8a1572 --- /dev/null +++ b/packages/active_window/.gitignore @@ -0,0 +1,6 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build output. +build/ diff --git a/packages/active_window/.vscode/launch.json b/packages/active_window/.vscode/launch.json new file mode 100644 index 00000000..fa865c18 --- /dev/null +++ b/packages/active_window/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "active_window", + "request": "launch", + "type": "dart" + } + ] +} \ No newline at end of file diff --git a/packages/active_window/CHANGELOG.md b/packages/active_window/CHANGELOG.md new file mode 100644 index 00000000..effe43c8 --- /dev/null +++ b/packages/active_window/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/packages/active_window/README.md b/packages/active_window/README.md new file mode 100644 index 00000000..a3075394 --- /dev/null +++ b/packages/active_window/README.md @@ -0,0 +1 @@ +A simple command-line application. diff --git a/packages/active_window/analysis_options.yaml b/packages/active_window/analysis_options.yaml new file mode 100644 index 00000000..11fda60d --- /dev/null +++ b/packages/active_window/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + errors: + omit_local_variable_types: ignore diff --git a/packages/active_window/bin/toggle_active_window.dart b/packages/active_window/bin/toggle_active_window.dart new file mode 100644 index 00000000..189c1a99 --- /dev/null +++ b/packages/active_window/bin/toggle_active_window.dart @@ -0,0 +1,48 @@ +import 'dart:io'; + +import 'package:active_window/active_window.dart'; +import 'package:hive/hive.dart'; +import 'package:native_platform/native_platform.dart'; + +/// The portion of Nyrna that will act as a toggle to +/// suspend / resume the active, foreground window. +/// +/// It is a self-contained executable, and should be bound to a hotkey +/// using the operating system's default methods on Linux, or by using +/// the included `toggle_active_hotkey.exe` on Windows which sits in the +/// system tray and listens for the `Pause` keyboard key to activate. +/// +/// When the hotkey launches the executable it will: +/// - Find the active, foreground window +/// - Minimize the window +/// - Suspend the process that owns the window +/// - Save the PID of said process & window id to a file +/// +/// On subsequent launch when the file with a saved PID is found: +/// - Resume the suspended process +/// - Restore / unminimize the associated window +/// - Delete the file containing the PID & window id so next call will suspend. + +Future main(List arguments) async { + if (arguments.isNotEmpty) { + if (arguments[0] == 'log') Logger.shouldLog = true; + } + + Hive.init(Directory.systemTemp.path); + + final nativePlatform = NativePlatform(); + + final activeWindow = ActiveWindow(nativePlatform); + + final savedPid = await activeWindow.savedPid(); + + if (savedPid != null) { + final successful = await activeWindow.resume(savedPid); + if (!successful) await Logger.log('Failed to resume successfully.'); + } else { + final successful = await activeWindow.suspend(); + if (!successful) await Logger.log('Failed to suspend successfully.'); + } + + await Hive.close(); +} diff --git a/packages/active_window/hotkey/toggle_active_hotkey.ahk b/packages/active_window/hotkey/toggle_active_hotkey.ahk new file mode 100644 index 00000000..810e66f4 --- /dev/null +++ b/packages/active_window/hotkey/toggle_active_hotkey.ahk @@ -0,0 +1,19 @@ +#SingleInstance, Force +SendMode Input +SetWorkingDir, %A_ScriptDir% + +; Simple tray icon for Windows that monitors for the user to press +; the `Pause` keyboard key, then activates Nyrna's `toggle active` function. + +Menu, Tray, NoStandard +Menu, Tray, Add, Exit +Menu, Tray, Tip, Nyrna - Toggle Active Hotkey +Menu, Tray, Icon, data\flutter_assets\assets\icons\nyrna.ico + +Pause:: + Run, toggle_active_window.exe +Return + +Exit: +ExitApp +Return diff --git a/packages/active_window/lib/active_window.dart b/packages/active_window/lib/active_window.dart new file mode 100644 index 00000000..9b21f4fd --- /dev/null +++ b/packages/active_window/lib/active_window.dart @@ -0,0 +1,4 @@ +library active_window; + +export 'src/active_window.dart'; +export 'src/logger.dart'; diff --git a/packages/active_window/lib/src/active_window.dart b/packages/active_window/lib/src/active_window.dart new file mode 100644 index 00000000..8c107b63 --- /dev/null +++ b/packages/active_window/lib/src/active_window.dart @@ -0,0 +1,89 @@ +import 'dart:io'; + +import 'package:hive/hive.dart'; +import 'package:native_platform/native_platform.dart'; + +import 'logger.dart'; + +class ActiveWindow { + final NativePlatform _nativePlatform; + + const ActiveWindow(this._nativePlatform); + + /// Get a value from Hive. + Future _getSavedValue(String key) async { + final box = await Hive.openBox('saved'); + var value = box.get(key); + if (value != null) value = value as int; + return value; + } + + /// Save a value to Hive. + Future _saveValue({ + required String key, + required int value, + }) async { + final box = await Hive.openBox('saved'); + await box.put(key, value); + } + + /// Delete the saved information, so the next run will suspend. + Future _deleteSaved() async => await Hive.deleteBoxFromDisk('saved'); + + Future savedPid() async => await _getSavedValue('pid'); + + Future resume(int pid) async { + await Logger.log('resuming, pid: $pid'); + final process = NativeProcess(pid); + final resumed = await process.resume(); + if (!resumed) { + await Logger.log('Failed to resume! Try resuming process manually?'); + await _deleteSaved(); // Must delete here, or enter infinite loop of failing to resume. + return false; + } + final windowId = await _getSavedValue('windowId'); + await _deleteSaved(); + if (windowId == null) { + await Logger.log('Failed to find saved windowId, cannot restore.'); + } else { + final restored = await _nativePlatform.restoreWindow(windowId); + if (!restored) await Logger.log('Failed to restore window.'); + } + await Logger.log('Resumed $pid successfully.'); + return true; + } + + Future suspend() async { + await Logger.log('Suspending'); + var activeWindow = await _nativePlatform.activeWindow(); + if (Platform.isWindows) { + // Once in a blue moon on Windows we get "explorer.exe" as the active + // window, even when no file explorer windows are open / the desktop + // is not the active element, etc. So we filter it just in case. + final executable = await activeWindow.executable(); + if (executable == 'explorer.exe') { + await Logger.log('Only got explorer as active window!'); + return false; + } + } + final minimized = await activeWindow.minimize(); + if (!minimized) { + await Logger.log('Failed to minimize window.'); + return false; + } + // Small delay on Windows to ensure the window actually minimizes. + // Doesn't seem to be necessary on Linux. + if (Platform.isWindows) { + await Future.delayed(Duration(milliseconds: 500)); + } + final suspended = await activeWindow.suspend(); + if (!suspended) { + await Logger.log('Failed to suspend active window.'); + return false; + } + await _saveValue(key: 'pid', value: activeWindow.pid); + await _saveValue(key: 'windowId', value: activeWindow.id); + await Logger.log('Suspended ${activeWindow.pid} successfully'); + return true; + } +} diff --git a/packages/active_window/lib/src/logger.dart b/packages/active_window/lib/src/logger.dart new file mode 100644 index 00000000..8ff37a0c --- /dev/null +++ b/packages/active_window/lib/src/logger.dart @@ -0,0 +1,20 @@ +import 'dart:io'; + +/// We log to a temp file on the system since this runs +/// with neiter a console nor a GUI, giving us a way to debug issues +/// which only manifest in a release build. +class Logger { + static bool shouldLog = false; + + static Future log(String value, [bool? override]) async { + if (shouldLog || override == true) { + final tempDir = Directory.systemTemp.path; + final file = File('$tempDir/nyrna_toggle_log.txt'); + await file.writeAsString( + '$value \n', + mode: FileMode.append, + flush: true, + ); + } + } +} diff --git a/packages/active_window/pubspec.lock b/packages/active_window/pubspec.lock new file mode 100644 index 00000000..38d4e557 --- /dev/null +++ b/packages/active_window/pubspec.lock @@ -0,0 +1,96 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + lints: + dependency: "direct dev" + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + native_platform: + dependency: "direct main" + description: + path: "../native_platform" + relative: true + source: path + version: "1.0.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.5" + win32_suspend_process: + dependency: transitive + description: + name: win32_suspend_process + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" +sdks: + dart: ">=2.13.0 <3.0.0" diff --git a/packages/active_window/pubspec.yaml b/packages/active_window/pubspec.yaml new file mode 100644 index 00000000..e59f3e46 --- /dev/null +++ b/packages/active_window/pubspec.yaml @@ -0,0 +1,16 @@ +name: active_window +description: Toggle the suspend state of the active window +version: 1.0.0 +publish_to: none + +environment: + sdk: '>=2.12.0 <3.0.0' + +dependencies: + hive: ^2.0.4 + native_platform: + path: ../native_platform + +dev_dependencies: + lints: ^1.0.0 + pedantic: ^1.11.1 diff --git a/packages/native_platform/lib/src/active_window.dart b/packages/native_platform/lib/src/active_window.dart new file mode 100644 index 00000000..da913882 --- /dev/null +++ b/packages/native_platform/lib/src/active_window.dart @@ -0,0 +1,28 @@ +import '../native_platform.dart'; + +class NativeActiveWindow { + final NativePlatform _nativePlatform; + final NativeProcess _nativeProcess; + + final int id; + final int pid; + + const NativeActiveWindow( + this._nativePlatform, + this._nativeProcess, { + required this.id, + required this.pid, + }); + + Future executable() async => await _nativeProcess.executable; + + Future minimize() async => await _nativePlatform.minimizeWindow(id); + + Future restore() async => await _nativePlatform.restoreWindow(id); + + Future status() async => await _nativeProcess.status; + + Future suspend() async => await _nativeProcess.suspend(); + + Future resume() async => await _nativeProcess.resume(); +} diff --git a/packages/native_platform/lib/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart index 699a3b45..fbb223e2 100644 --- a/packages/native_platform/lib/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -1,5 +1,6 @@ import 'dart:io' as io; +import '../active_window.dart'; import '../native_platform.dart'; import '../native_process.dart'; import '../process.dart'; @@ -62,6 +63,20 @@ class Linux implements NativePlatform { return windows; } + @override + Future activeWindow() async { + final windowId = await activeWindowId; + final pid = await windowPid(windowId); + final linuxProcess = LinuxProcess(pid); + final activeWindow = NativeActiveWindow( + NativePlatform(), + linuxProcess, + id: windowId, + pid: pid, + ); + return activeWindow; + } + // Returns the PID of the active window as reported by xdotool. @override Future get activeWindowPid async { diff --git a/packages/native_platform/lib/src/native_platform.dart b/packages/native_platform/lib/src/native_platform.dart index 5734bdc3..f7f105d5 100644 --- a/packages/native_platform/lib/src/native_platform.dart +++ b/packages/native_platform/lib/src/native_platform.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'active_window.dart'; import 'linux/linux.dart'; import 'native_process.dart'; import 'win32/win32.dart'; @@ -31,6 +32,8 @@ abstract class NativePlatform { /// List of [Window] objects for every visible window with title text. Future> windows(); + Future activeWindow(); + /// Returns the pid associated with the active window. Future get activeWindowPid; diff --git a/packages/native_platform/lib/src/win32/win32.dart b/packages/native_platform/lib/src/win32/win32.dart index c9dacef2..50df528a 100644 --- a/packages/native_platform/lib/src/win32/win32.dart +++ b/packages/native_platform/lib/src/win32/win32.dart @@ -3,6 +3,7 @@ import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:win32/win32.dart'; +import '../active_window.dart'; import '../native_platform.dart'; import '../native_process.dart'; import '../process.dart'; @@ -52,6 +53,20 @@ class Win32 implements NativePlatform { return _windowPid; } + @override + Future activeWindow() async { + final windowId = await activeWindowId; + final pid = await windowPid(windowId); + final win32Process = Win32Process(pid); + final activeWindow = NativeActiveWindow( + NativePlatform(), + win32Process, + id: windowId, + pid: pid, + ); + return activeWindow; + } + @override Future get activeWindowPid async { final windowId = await activeWindowId; diff --git a/packages/native_platform/pubspec.yaml b/packages/native_platform/pubspec.yaml index 03a8225d..cc984730 100644 --- a/packages/native_platform/pubspec.yaml +++ b/packages/native_platform/pubspec.yaml @@ -6,6 +6,7 @@ environment: dependencies: equatable: ^2.0.3 + logging: ^1.0.1 win32: ^2.2.5 win32_suspend_process: ^1.0.0 diff --git a/test/window/active_window_test.dart b/test/window/active_window_test.dart deleted file mode 100644 index 97efae59..00000000 --- a/test/window/active_window_test.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:nyrna/infrastructure/preferences/preferences.dart'; -import 'package:nyrna/application/active_window/active_window.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -Future main() async { - final sharedPreferences = await SharedPreferences.getInstance(); - // ignore: unused_local_variable - final prefs = Preferences(sharedPreferences); - - ActiveWindow? activeWindow; - - setUp(() async { - activeWindow = ActiveWindow(); - await activeWindow!.initialize(); - }); - - tearDown(() => activeWindow = null); - - test( - 'Can instantiate ActiveWindow', - () { - expect(activeWindow.runtimeType, ActiveWindow); - }, - ); - test( - 'ActiveWindow pid is not null', - () { - print('Active window pid: ${activeWindow!.pid}'); - expect(activeWindow!.pid, isNot(null)); - }, - ); - test( - 'ActiveWindow id is not null', - () { - print('Active window id: ${activeWindow!.id}'); - expect(activeWindow!.id, isNot(null)); - }, - ); -} From 35af0c6675f8376e536179e67788829e72bc523d Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:17:13 -0400 Subject: [PATCH 48/83] Remove redundant arg tests --- test/arguments/argument_parser_test.dart | 38 +----------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/test/arguments/argument_parser_test.dart b/test/arguments/argument_parser_test.dart index ec987938..23fd12d7 100644 --- a/test/arguments/argument_parser_test.dart +++ b/test/arguments/argument_parser_test.dart @@ -5,7 +5,7 @@ void main() { test('With no flags log is false', () async { final parser = ArgumentParser([]); await parser.parse(); - expect(parser.toggleFlagged, false); + expect(ArgumentParser.logToFile, false); }); test('Config.log is true with -l flag', () async { @@ -19,40 +19,4 @@ void main() { await parser.parse(); expect(ArgumentParser.logToFile, true); }); - - test( - 'With no flags toggle is false', - () async { - final parser = ArgumentParser([]); - await parser.parse(); - expect(parser.toggleFlagged, false); - }, - ); - test( - '--toggle sets Config.toggle to true', - () async { - final parser = ArgumentParser(['--toggle']); - await parser.parse(); - expect(parser.toggleFlagged, true); - }, - ); - - test( - '-t sets Config.toggle to true', - () async { - final parser = ArgumentParser(['-t']); - await parser.parse(); - expect(parser.toggleFlagged, true); - }, - ); - - test( - 'With log and toggle flags log and toggle are true', - () async { - final parser = ArgumentParser(['-tl']); - await parser.parse(); - expect(parser.toggleFlagged, true); - expect(ArgumentParser.logToFile, true); - }, - ); } From 124df963d70a5688ff823fe63d17d3a18e9eb58e Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:35:46 -0400 Subject: [PATCH 49/83] Add toggle active to CI builds for Windows --- .github/workflows/build-win32.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index 11989f69..c4eb9be6 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -28,6 +28,12 @@ jobs: xcopy C:\Windows\System32\msvcp140.dll build\Nyrna xcopy C:\Windows\System32\vcruntime140.dll build\Nyrna xcopy C:\Windows\System32\vcruntime140_1.dll build\Nyrna + + dart compile exe .\packages\active_window\bin\toggle_active_window.dart + editbin.exe /subsystem:windows .\packages\active_window\bin\toggle_active_window.exe + xcopy .\packages\active_window\bin\toggle_active_window.exe .\build\Nyrna + + Ahk2Exe.exe /in .\packages\active_window\hotkey\toggle_active_hotkey.ahk /out .\build\Nyrna\toggle_active_hotkey.exe - name: Package with Inno Setup run: | iscc packaging\win32\inno_setup_script.iss From 649ecb26db974a683bcb165c07755b367ae0c4c4 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:45:27 -0400 Subject: [PATCH 50/83] Build dart app from base directory --- .github/workflows/build-win32.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index c4eb9be6..b6144970 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -29,11 +29,14 @@ jobs: xcopy C:\Windows\System32\vcruntime140.dll build\Nyrna xcopy C:\Windows\System32\vcruntime140_1.dll build\Nyrna - dart compile exe .\packages\active_window\bin\toggle_active_window.dart - editbin.exe /subsystem:windows .\packages\active_window\bin\toggle_active_window.exe - xcopy .\packages\active_window\bin\toggle_active_window.exe .\build\Nyrna + cd .\packages\active_window + dart pub get + dart compile exe .\bin\toggle_active_window.dart + editbin.exe /subsystem:windows .\bin\toggle_active_window.exe + xcopy .\bin\toggle_active_window.exe ..\..\build\Nyrna - Ahk2Exe.exe /in .\packages\active_window\hotkey\toggle_active_hotkey.ahk /out .\build\Nyrna\toggle_active_hotkey.exe + Ahk2Exe.exe /in .\hotkey\toggle_active_hotkey.ahk /out ..\..\build\Nyrna\toggle_active_hotkey.exe + cd ..\.. - name: Package with Inno Setup run: | iscc packaging\win32\inno_setup_script.iss From 5e55cf3518dd8181559c13b52908b29e44bd4803 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 12:57:29 -0400 Subject: [PATCH 51/83] Add Visual Studio shell to github action --- .github/workflows/build-win32.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index b6144970..6bb23186 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -16,6 +16,10 @@ jobs: - name: Read VERSION file id: getversion run: echo "::set-output name=version::$(cat VERSION)" + - name: Set up Visual Studio shell + uses: egor-tensin/vs-shell@v2 + with: + arch: x64 - name: Build Nyrna portable run: | flutter config --enable-windows-desktop From 06ae575b7fe5dec90ff002c438058e31ad2b18a8 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 13:18:27 -0400 Subject: [PATCH 52/83] Add autohotkey to workflow --- .github/workflows/build-win32.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index 6bb23186..219f6835 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -20,6 +20,8 @@ jobs: uses: egor-tensin/vs-shell@v2 with: arch: x64 + - name: Install AutoHotkey + run: choco install autohotkey - name: Build Nyrna portable run: | flutter config --enable-windows-desktop From 87db5ceea7fbdbf60c356a2946ef38d24bedc98f Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 13:31:21 -0400 Subject: [PATCH 53/83] Add autohotkey to action's path --- .github/workflows/build-win32.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index 219f6835..1054c378 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -22,6 +22,8 @@ jobs: arch: x64 - name: Install AutoHotkey run: choco install autohotkey + - name: Add AutoHotkey to path + run: echo "C:\Program Files\AutoHotkey\Compiler" >> $GITHUB_PATH - name: Build Nyrna portable run: | flutter config --enable-windows-desktop From af36018ffeddc172d90a6014fafdb448d6c4a592 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Fri, 6 Aug 2021 13:41:20 -0400 Subject: [PATCH 54/83] Update path command --- .github/workflows/build-win32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index 1054c378..0dccadbe 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -23,7 +23,7 @@ jobs: - name: Install AutoHotkey run: choco install autohotkey - name: Add AutoHotkey to path - run: echo "C:\Program Files\AutoHotkey\Compiler" >> $GITHUB_PATH + run: echo "C:\Program Files\AutoHotkey\Compiler" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Build Nyrna portable run: | flutter config --enable-windows-desktop From 4402d49b03955a18d0f322c1043ccf762560044e Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 7 Aug 2021 09:55:22 -0400 Subject: [PATCH 55/83] Add donate link --- .../preferences/pages/preferences_page.dart | 2 + .../preferences/widgets/donate.dart | 51 +++++++++++++++++++ .../preferences/widgets/widgets.dart | 1 + lib/presentation/styles.dart | 1 + 4 files changed, 55 insertions(+) create mode 100644 lib/presentation/preferences/widgets/donate.dart diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index 7e5d5370..3fa41c90 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -17,6 +17,8 @@ class PreferencesPage extends StatelessWidget { horizontal: 130, ), children: [ + const Donate(), + Spacers.verticalLarge, const BehaviourSection(), Spacers.verticalMedium, const ThemeSection(), diff --git a/lib/presentation/preferences/widgets/donate.dart b/lib/presentation/preferences/widgets/donate.dart new file mode 100644 index 00000000..2fb268f9 --- /dev/null +++ b/lib/presentation/preferences/widgets/donate.dart @@ -0,0 +1,51 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/presentation/styles.dart'; + +class Donate extends StatelessWidget { + const Donate({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Center( + child: Card( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 20), + child: Column( + children: [ + Text.rich( + TextSpan( + children: [ + TextSpan(text: 'Nyrna is free software, made with 💙 by '), + TextSpan( + text: 'Kristen McWilliam', + style: TextStyle(color: Colors.lightBlueAccent), + recognizer: TapGestureRecognizer() + ..onTap = () { + print('tap'); + appCubit.launchURL('https://merritt.codes/'); + }, + ), + TextSpan(text: '.'), + ], + ), + ), + Spacers.verticalXtraSmall, + ElevatedButton.icon( + onPressed: () { + appCubit.launchURL('https://merritt.codes/support'); + }, + icon: Icon( + Icons.favorite, + color: Colors.red, + ), + label: Text('Donate'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/presentation/preferences/widgets/widgets.dart b/lib/presentation/preferences/widgets/widgets.dart index 62e5e86e..b87a1c4d 100644 --- a/lib/presentation/preferences/widgets/widgets.dart +++ b/lib/presentation/preferences/widgets/widgets.dart @@ -1,4 +1,5 @@ export 'about_section.dart'; export 'behaviour_section.dart'; +export 'donate.dart'; export 'integration_section.dart'; export 'theme_section.dart'; diff --git a/lib/presentation/styles.dart b/lib/presentation/styles.dart index aefdf164..24b8c212 100644 --- a/lib/presentation/styles.dart +++ b/lib/presentation/styles.dart @@ -10,6 +10,7 @@ abstract class Spacers { static const verticalXtraSmall = SizedBox(height: 10); static const verticalSmall = SizedBox(height: 20); static const verticalMedium = SizedBox(height: 30); + static const verticalLarge = SizedBox(height: 40); } class TextStyles { From a84e28c99f122e18f846323875a8e006724a4a3e Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 7 Aug 2021 09:57:43 -0400 Subject: [PATCH 56/83] Set preferences scrollbar to always visible --- .../preferences/pages/preferences_page.dart | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/presentation/preferences/pages/preferences_page.dart b/lib/presentation/preferences/pages/preferences_page.dart index 3fa41c90..55972894 100644 --- a/lib/presentation/preferences/pages/preferences_page.dart +++ b/lib/presentation/preferences/pages/preferences_page.dart @@ -11,28 +11,31 @@ class PreferencesPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Preferences')), - body: ListView( - padding: const EdgeInsets.symmetric( - vertical: 30, - horizontal: 130, - ), - children: [ - const Donate(), - Spacers.verticalLarge, - const BehaviourSection(), - Spacers.verticalMedium, - const ThemeSection(), - const IntegrationSection(), - Spacers.verticalMedium, - const Text('Troubleshooting'), - ListTile( - leading: const Icon(Icons.article_outlined), - title: const Text('Logs'), - onTap: () => Navigator.pushNamed(context, LogPage.id), + body: Scrollbar( + isAlwaysShown: true, + child: ListView( + padding: const EdgeInsets.symmetric( + vertical: 30, + horizontal: 130, ), - Spacers.verticalMedium, - const AboutSection(), - ], + children: [ + const Donate(), + Spacers.verticalLarge, + const BehaviourSection(), + Spacers.verticalMedium, + const ThemeSection(), + const IntegrationSection(), + Spacers.verticalMedium, + const Text('Troubleshooting'), + ListTile( + leading: const Icon(Icons.article_outlined), + title: const Text('Logs'), + onTap: () => Navigator.pushNamed(context, LogPage.id), + ), + Spacers.verticalMedium, + const AboutSection(), + ], + ), ), ); } From b2275b59649abbcb941a084c6f52642578c05373 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 7 Aug 2021 10:32:50 -0400 Subject: [PATCH 57/83] Remove leftover print statement --- lib/presentation/preferences/widgets/donate.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/presentation/preferences/widgets/donate.dart b/lib/presentation/preferences/widgets/donate.dart index 2fb268f9..f9c80db0 100644 --- a/lib/presentation/preferences/widgets/donate.dart +++ b/lib/presentation/preferences/widgets/donate.dart @@ -23,7 +23,6 @@ class Donate extends StatelessWidget { style: TextStyle(color: Colors.lightBlueAccent), recognizer: TapGestureRecognizer() ..onTap = () { - print('tap'); appCubit.launchURL('https://merritt.codes/'); }, ), From 916f9a8a1d9f95af42ca6e1363d13c6d61dd829f Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 7 Aug 2021 10:49:30 -0400 Subject: [PATCH 58/83] Move applist padding to layoutbuilder --- lib/presentation/app/pages/apps_page.dart | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index a4f9f06e..188006f0 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -20,11 +20,16 @@ class AppsPage extends StatelessWidget { builder: (context, state) { return Stack( children: [ - Center( - child: Container( - width: MediaQuery.of(context).size.width / 1.20, - child: ListView( - padding: const EdgeInsets.only(top: 40), + LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + final width = constraints.maxWidth; + final horizontalPadding = width / 6; + + return ListView( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + vertical: 40, + ), children: [ ...state.windows .map( @@ -35,8 +40,8 @@ class AppsPage extends StatelessWidget { ) .toList(), ], - ), - ), + ); + }, ), _ProgressOverlay(), ], From 27018dafc0761b0fbdf64eed1ba763bb93c7d699 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 7 Aug 2021 10:52:07 -0400 Subject: [PATCH 59/83] Always show applist scrollbar when needed --- lib/presentation/app/pages/apps_page.dart | 31 +++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/presentation/app/pages/apps_page.dart b/lib/presentation/app/pages/apps_page.dart index 188006f0..f08fed22 100644 --- a/lib/presentation/app/pages/apps_page.dart +++ b/lib/presentation/app/pages/apps_page.dart @@ -25,21 +25,24 @@ class AppsPage extends StatelessWidget { final width = constraints.maxWidth; final horizontalPadding = width / 6; - return ListView( - padding: EdgeInsets.symmetric( - horizontal: horizontalPadding, - vertical: 40, + return Scrollbar( + isAlwaysShown: true, + child: ListView( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + vertical: 40, + ), + children: [ + ...state.windows + .map( + (window) => WindowTile( + key: ValueKey(window), + window: window, + ), + ) + .toList(), + ], ), - children: [ - ...state.windows - .map( - (window) => WindowTile( - key: ValueKey(window), - window: window, - ), - ) - .toList(), - ], ); }, ), From 3e997dbea0e6933883fc7f73a6977d4a695edbd7 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:08:58 -0400 Subject: [PATCH 60/83] Add preference to choose tray icon color --- .../preferences/cubit/preferences_cubit.dart | 22 +++ .../preferences/cubit/preferences_state.dart | 8 +- .../icon_manager/icon_manager.dart | 57 ++++++- .../preferences/widgets/theme_section.dart | 148 ++++++++++-------- lib/presentation/styles.dart | 4 + pubspec.lock | 21 +++ pubspec.yaml | 1 + 7 files changed, 188 insertions(+), 73 deletions(-) diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index 78801f7b..cbbd6ed2 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -1,10 +1,15 @@ import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ui'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:nyrna/application/app/app.dart'; +import 'package:nyrna/infrastructure/icon_manager/icon_manager.dart'; import 'package:nyrna/infrastructure/launcher/launcher.dart'; import 'package:nyrna/infrastructure/preferences/preferences.dart'; +import 'package:nyrna/presentation/styles.dart'; part 'preferences_state.dart'; @@ -19,6 +24,9 @@ class PreferencesCubit extends Cubit { PreferencesState( autoRefresh: _checkAutoRefresh(prefs), refreshInterval: prefs.getInt('refreshInterval') ?? 5, + trayIconColor: Color( + prefs.getInt('trayIconColor') ?? AppColors.defaultIconColor, + ), ), ) { preferencesCubit = this; @@ -56,4 +64,18 @@ class PreferencesCubit extends Cubit { emit(state.copyWith(autoRefresh: autoEnabled)); } } + + Future iconBytes() async { + final iconManager = IconManager(); + final iconBytes = await iconManager.iconBytes(); + return iconBytes; + } + + Future updateIconColor(Color newColor) async { + final successful = await IconManager().updateIconColor(newColor); + if (successful) { + await _prefs.setInt(key: 'trayIconColor', value: newColor.value); + emit(state.copyWith(trayIconColor: newColor)); + } + } } diff --git a/lib/application/preferences/cubit/preferences_state.dart b/lib/application/preferences/cubit/preferences_state.dart index ddc6b6ed..48696ffe 100644 --- a/lib/application/preferences/cubit/preferences_state.dart +++ b/lib/application/preferences/cubit/preferences_state.dart @@ -7,22 +7,26 @@ class PreferencesState extends Equatable { /// How often to automatically refresh the list of open windows, in seconds. final int refreshInterval; + final Color trayIconColor; + const PreferencesState({ required this.autoRefresh, required this.refreshInterval, + required this.trayIconColor, }); @override - List get props => [autoRefresh, refreshInterval]; + List get props => [autoRefresh, refreshInterval, trayIconColor]; PreferencesState copyWith({ bool? autoRefresh, - bool? isPortable, int? refreshInterval, + Color? trayIconColor, }) { return PreferencesState( autoRefresh: autoRefresh ?? this.autoRefresh, refreshInterval: refreshInterval ?? this.refreshInterval, + trayIconColor: trayIconColor ?? this.trayIconColor, ); } } diff --git a/lib/infrastructure/icon_manager/icon_manager.dart b/lib/infrastructure/icon_manager/icon_manager.dart index 54a8ca58..7fdfab0f 100644 --- a/lib/infrastructure/icon_manager/icon_manager.dart +++ b/lib/infrastructure/icon_manager/icon_manager.dart @@ -1,13 +1,60 @@ +import 'dart:io'; import 'dart:typed_data'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:image/image.dart' as image; class IconManager { - Future get iconUint8List async { - final iconBytes = await rootBundle.load('assets/icons/nyrna.png'); - final iconAsUint8List = iconBytes.buffer.asUint8List(); - return iconAsUint8List; + Uint8List? _loadedIconBytes; + + Future iconBytes() async { + if (_loadedIconBytes != null) return Future.value(_loadedIconBytes); + final byteData = await rootBundle.load('assets/icons/nyrna.png'); + final iconBytes = byteData.buffer.asUint8List(); + _loadedIconBytes = iconBytes; + return iconBytes; + } + + /// Re-launch the tray application so it shows the new icon. + Future _refreshTray() async { + try { + await Process.start('toggle_active_hotkey.exe', []); + } on ProcessException { + print('Unable to launch hotkey executable'); + } } - // updateIcon({required int color}) {} + Future updateIconColor(Color color) async { + final _iconBytes = await iconBytes(); + final loadedImage = image.decodePng(_iconBytes); + if (loadedImage == null) return false; + var updatedImage = image.adjustColor( + loadedImage, + blacks: 0, + whites: 0, + mids: 0, + ); + updatedImage = image.colorOffset( + loadedImage, + red: color.red, + green: color.green, + blue: color.blue, + ); + final icoBytes = image.encodeIco(updatedImage); + final assetPath = kDebugMode + ? '\\assets\\icons' + : '\\data\\flutter_assets\\assets\\icons'; + final icoDirectory = Directory.current.path + assetPath; + final ico = File(icoDirectory + '\\nyrna.ico'); + try { + await ico.writeAsBytes(icoBytes, flush: true); + } catch (e) { + print('Unable to write icon file: $e'); + return false; + } + await _refreshTray(); + return true; + } } diff --git a/lib/presentation/preferences/widgets/theme_section.dart b/lib/presentation/preferences/widgets/theme_section.dart index 6b47fd4c..e8d3ad0b 100644 --- a/lib/presentation/preferences/widgets/theme_section.dart +++ b/lib/presentation/preferences/widgets/theme_section.dart @@ -1,5 +1,9 @@ +import 'dart:io'; + +import 'package:flex_color_picker/flex_color_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import 'package:nyrna/application/theme/theme.dart'; class ThemeSection extends StatelessWidget { @@ -10,7 +14,8 @@ class ThemeSection extends StatelessWidget { return Column( children: [ const _ThemeChooser(), - // const _IconCustomizer(), + if (Platform.isWindows) const Divider(), + if (Platform.isWindows) const _IconCustomizer(), ], ); } @@ -54,70 +59,81 @@ class _ThemeChooser extends StatelessWidget { } } -// class _IconCustomizer extends StatelessWidget { -// const _IconCustomizer({Key? key}) : super(key: key); +/// Choose a custom color for the tray icon. +class _IconCustomizer extends StatelessWidget { + const _IconCustomizer({Key? key}) : super(key: key); -// @override -// Widget build(BuildContext context) { -// return ListTile( -// leading: Icon(Icons.color_lens), -// title: Text('Icon color'), -// trailing: ColorIndicator(), -// onTap: () => _pickIconColor(), -// ); -// } + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return ListTile( + leading: ColorIndicator( + color: state.trayIconColor, + ), + title: Text('System tray icon color'), + onTap: () => _pickIconColor( + context: context, + currentColor: state.trayIconColor, + ), + ); + }, + ); + } -// Future _pickIconColor() async { -// var iconColor = Color(settings.iconColor); -// final iconManager = IconManager(); -// final iconUint8List = await iconManager.iconUint8List; -// final confirmed = await showDialog( -// context: context, -// builder: (context) { -// return AlertDialog( -// content: StatefulBuilder( -// builder: (context, setState) { -// return Column( -// mainAxisSize: MainAxisSize.min, -// children: [ -// ColorPicker( -// // Current color is pre-selected. -// color: iconColor, -// onColorChanged: (Color color) { -// setState(() => iconColor = color); -// }, -// heading: Text('Select color'), -// subheading: Text('Select color shade'), -// pickersEnabled: const { -// ColorPickerType.primary: true, -// ColorPickerType.accent: false, -// }, -// ), -// Image.memory( -// iconUint8List, -// height: 150, -// width: 150, -// color: iconColor, -// ), -// ], -// ); -// }, -// ), -// actions: [ -// TextButton( -// onPressed: () => Navigator.pop(context), -// child: Text('Cancel'), -// ), -// TextButton( -// onPressed: () {}, -// child: Text('Save'), -// ), -// ], -// ); -// }, -// ); -// if (confirmed == null) return; -// // await _updateIcon(); -// // await settings.setIconColor(newColor!.value); -// } -// } + Future _pickIconColor({ + required BuildContext context, + required Color currentColor, + }) async { + Color iconColor = currentColor; + final iconBytes = await preferencesCubit.iconBytes(); + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + content: StatefulBuilder( + builder: (context, setState) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ColorPicker( + // Current color is pre-selected. + color: iconColor, + onColorChanged: (Color color) { + setState(() => iconColor = color); + }, + heading: Text('Select color'), + subheading: Text('Select color shade'), + pickersEnabled: const { + ColorPickerType.primary: true, + ColorPickerType.accent: false, + }, + ), + Image.memory( + iconBytes, + height: 150, + width: 150, + color: iconColor, + ), + ], + ); + }, + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Cancel'), + ), + TextButton( + onPressed: () async { + await preferencesCubit.updateIconColor(iconColor); + Navigator.pop(context); + }, + child: Text('Save'), + ), + ], + ); + }, + ); + } +} diff --git a/lib/presentation/styles.dart b/lib/presentation/styles.dart index 24b8c212..138ddab3 100644 --- a/lib/presentation/styles.dart +++ b/lib/presentation/styles.dart @@ -1,5 +1,9 @@ import 'package:flutter/material.dart'; +abstract class AppColors { + static const defaultIconColor = 0xFF00B3FF; +} + abstract class BorderRadii { static BorderRadius gentlyRounded = BorderRadius.circular(10); } diff --git a/pubspec.lock b/pubspec.lock index f8fb9f3b..1bb78f57 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -215,6 +215,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + image: + dependency: "direct main" + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" integration_test: dependency: "direct dev" description: flutter @@ -346,6 +353,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.11.0" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" platform: dependency: transitive description: @@ -652,6 +666,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.2" yaml: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9cf4da52..bb708739 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: win32: ^2.1.1 win32_suspend_process: ^1.0.0 yaml: ^3.1.0 + image: ^3.0.2 dev_dependencies: flutter_test: From 0e88bb52576173bc60b75d3429266529de4d5e41 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:26:11 -0400 Subject: [PATCH 61/83] Add build active_window to linux portable CI --- .github/workflows/build-linux-portable.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-linux-portable.yml b/.github/workflows/build-linux-portable.yml index 93c91015..eb3b3a8d 100644 --- a/.github/workflows/build-linux-portable.yml +++ b/.github/workflows/build-linux-portable.yml @@ -26,6 +26,13 @@ jobs: mv build/linux/x64/release/bundle nyrna touch nyrna/PORTABLE cp VERSION nyrna/VERSION + - name: Build toggle_active_window + run: | + cd packages/active_window + dart pub get + dart compile exe bin/toggle_active_window.dart + cp bin/toggle_active_window ../../build/Nyrna + cd ../.. - uses: actions/upload-artifact@v2 with: name: nyrna-linux-portable From 317e2898b8150274c22f64f54b46cc99edcc9de4 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:36:19 -0400 Subject: [PATCH 62/83] Output directory tree --- .github/workflows/build-linux-portable.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-linux-portable.yml b/.github/workflows/build-linux-portable.yml index eb3b3a8d..244e2834 100644 --- a/.github/workflows/build-linux-portable.yml +++ b/.github/workflows/build-linux-portable.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: sudo apt-get update -y - - run: sudo apt-get install -y ninja-build libgtk-3-dev libblkid-dev + - run: sudo apt-get install -y ninja-build libgtk-3-dev libblkid-dev tree - uses: actions/checkout@v2 - uses: subosito/flutter-action@v1.4.0 with: @@ -31,6 +31,7 @@ jobs: cd packages/active_window dart pub get dart compile exe bin/toggle_active_window.dart + tree cp bin/toggle_active_window ../../build/Nyrna cd ../.. - uses: actions/upload-artifact@v2 From 98ee0feaaee3c3e1912266b9b2ac5dc6ff8f2640 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 11:55:03 -0400 Subject: [PATCH 63/83] Specify output filename so Linux vers isn't exe Apparently .exe is default on all platforms...... --- .github/workflows/build-linux-portable.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-linux-portable.yml b/.github/workflows/build-linux-portable.yml index 244e2834..efd34744 100644 --- a/.github/workflows/build-linux-portable.yml +++ b/.github/workflows/build-linux-portable.yml @@ -30,8 +30,7 @@ jobs: run: | cd packages/active_window dart pub get - dart compile exe bin/toggle_active_window.dart - tree + dart compile exe bin/toggle_active_window.dart -o bin/toggle_active_window cp bin/toggle_active_window ../../build/Nyrna cd ../.. - uses: actions/upload-artifact@v2 From 3a1c1a4e2d9d111566bf997ea01ba145d1771d6d Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:57:13 -0400 Subject: [PATCH 64/83] Move toggle_active to portable folder --- .github/workflows/build-linux-portable.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-linux-portable.yml b/.github/workflows/build-linux-portable.yml index efd34744..60d81d7d 100644 --- a/.github/workflows/build-linux-portable.yml +++ b/.github/workflows/build-linux-portable.yml @@ -31,7 +31,7 @@ jobs: cd packages/active_window dart pub get dart compile exe bin/toggle_active_window.dart -o bin/toggle_active_window - cp bin/toggle_active_window ../../build/Nyrna + cp bin/toggle_active_window ../../nyrna cd ../.. - uses: actions/upload-artifact@v2 with: From 6269bb0abb035eeeaa2f7f85c4bcba670a626adc Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:20:07 -0400 Subject: [PATCH 65/83] Await the async foreach --- packages/native_platform/lib/src/linux/linux.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/native_platform/lib/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart index fbb223e2..07852950 100644 --- a/packages/native_platform/lib/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -32,7 +32,7 @@ class Linux implements NativePlatform { // 0x03600041 1 1459 SHODAN Inbox - Unified Folders - Mozilla Thunderbird // windowId, desktopId, pid, user, window title final lines = result.stdout.toString().split('\n'); - lines.forEach((line) async { + await Future.forEach(lines, (String line) async { final parts = line.split(' '); parts.removeWhere((part) => part == ''); // Happens with multiple spaces. if (parts.length > 1) { From ad647c1692e50d0cbadb6f3ac56764c753a2eb4a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:20:51 -0400 Subject: [PATCH 66/83] Throw exception for non-existent id or pid --- packages/native_platform/lib/src/linux/linux.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/native_platform/lib/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart index 07852950..08c1787a 100644 --- a/packages/native_platform/lib/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -66,7 +66,9 @@ class Linux implements NativePlatform { @override Future activeWindow() async { final windowId = await activeWindowId; + if (windowId == 0) throw (Exception('No window id')); final pid = await windowPid(windowId); + if (pid == 0) throw (Exception('No pid')); final linuxProcess = LinuxProcess(pid); final activeWindow = NativeActiveWindow( NativePlatform(), From 55a05f8911e145fe4ae40b98169ac4165f108e02 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:21:13 -0400 Subject: [PATCH 67/83] Fix xdotool command order --- packages/native_platform/lib/src/linux/linux.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/native_platform/lib/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart index 08c1787a..facadb43 100644 --- a/packages/native_platform/lib/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -118,7 +118,7 @@ class Linux implements NativePlatform { Future windowPid(int windowId) async { final result = await io.Process.run( 'xdotool', - ['$windowId', 'getwindowpid'], + ['getwindowpid', '$windowId'], ); final _pid = int.tryParse(result.stdout.toString().trim()); return _pid ?? 0; From b6d831fa936e230a5eb96ef541d1e86c6a9cbd90 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 10:47:56 -0400 Subject: [PATCH 68/83] Return success or failure on minimize linux window --- packages/native_platform/lib/src/linux/linux.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/native_platform/lib/src/linux/linux.dart b/packages/native_platform/lib/src/linux/linux.dart index facadb43..4cc37597 100644 --- a/packages/native_platform/lib/src/linux/linux.dart +++ b/packages/native_platform/lib/src/linux/linux.dart @@ -135,21 +135,17 @@ class Linux implements NativePlatform { Future minimizeWindow(int windowId) async { final result = await io.Process.run( 'xdotool', - ['windowminimize', '$windowId', '--sync'], + ['windowminimize', '$windowId'], ); - return true; - // TODO: Check for possible stderr for meaningful return value. - // result.stderr + return (result.stderr == '') ? true : false; } @override Future restoreWindow(int windowId) async { final result = await io.Process.run( 'xdotool', - ['windowactivate', '$windowId', '--sync'], + ['windowactivate', '$windowId'], ); - return true; - // TODO: Check for possible stderr for meaningful return value. - // result.stderr + return (result.stderr == '') ? true : false; } } From 399a4ed7111187180c3df0aec54c44a144987ee6 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 11:35:13 -0400 Subject: [PATCH 69/83] Add PORTABLE file for windows portable version --- .github/workflows/build-win32.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index 0dccadbe..fc089ed9 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -48,6 +48,8 @@ jobs: - name: Package with Inno Setup run: | iscc packaging\win32\inno_setup_script.iss + - name: Add PORTABLE file + run: type NUL > build\Nyrna\PORTABLE - uses: actions/upload-artifact@v2 with: name: nyrna-windows-portable From ef025c69ae6cdf523a9f9f52bd7a54993d8964e3 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:27:48 -0400 Subject: [PATCH 70/83] Add hotkey shortcut to windows installer --- packaging/win32/inno_setup_script.iss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/win32/inno_setup_script.iss b/packaging/win32/inno_setup_script.iss index 61f76c8b..92381482 100644 --- a/packaging/win32/inno_setup_script.iss +++ b/packaging/win32/inno_setup_script.iss @@ -42,7 +42,8 @@ Source: "..\..\build\Nyrna\*"; DestDir: "{app}"; Flags: ignoreversion recursesub ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] -Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autoprograms}\{#MyAppName}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autoprograms}\{#MyAppName}\{#MyAppName} Hotkey"; Filename: "{app}\toggle_active_hotkey.exe" Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon [Run] From 2802c1f18f9c33db31bb60894279beaecdf087ed Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:29:27 -0400 Subject: [PATCH 71/83] Remove auto refresh warning on Windows --- .../widgets/behaviour_section.dart | 44 +------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/lib/presentation/preferences/widgets/behaviour_section.dart b/lib/presentation/preferences/widgets/behaviour_section.dart index 32d71a29..00b41c5b 100644 --- a/lib/presentation/preferences/widgets/behaviour_section.dart +++ b/lib/presentation/preferences/widgets/behaviour_section.dart @@ -20,14 +20,7 @@ class BehaviourSection extends StatelessWidget { ListTile( title: const Text('Auto Refresh'), leading: const Icon(Icons.refresh), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Update window & process info automatically'), - const SizedBox(height: 5), - if (Platform.isWindows) const _WarningChip(), - ], - ), + subtitle: const Text('Update window & process info automatically'), trailing: BlocBuilder( builder: (context, state) { return Switch( @@ -69,38 +62,3 @@ class BehaviourSection extends StatelessWidget { await preferencesCubit.updateAutoRefresh(); } } - -class _WarningChip extends StatelessWidget { - const _WarningChip({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ActionChip( - label: Text( - 'Caution', - style: TextStyle(color: Colors.red[800]), - ), - backgroundColor: Colors.yellow, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: const Text( - 'Note: Auto refresh can cause issues with memory consumption on ' - 'Windows at the moment. Until the problem is resolved, consider ' - 'keeping auto refresh off if you experience issues.', - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: const Text('Close'), - ), - ], - ); - }, - ); - }, - ); - } -} From a8d3a056239b5f43df39d3516bd0f85cdf708045 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:30:12 -0400 Subject: [PATCH 72/83] Bump nyrna's version to 2.1.0 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bb708739..b33eb2d5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: nyrna description: Suspend any game or application. publish_to: 'none' -version: 2.0.0 +version: 2.1.0 environment: sdk: '>=2.12.0 <3.0.0' From ba6e9891b00c6487869c37377c1ce8002b09db28 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:30:38 -0400 Subject: [PATCH 73/83] Remove unneeded import --- lib/presentation/preferences/widgets/behaviour_section.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/presentation/preferences/widgets/behaviour_section.dart b/lib/presentation/preferences/widgets/behaviour_section.dart index 00b41c5b..49fc49ab 100644 --- a/lib/presentation/preferences/widgets/behaviour_section.dart +++ b/lib/presentation/preferences/widgets/behaviour_section.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; From 70ca8c12369a7fc435002d1e551db16b354500f9 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:46:08 -0400 Subject: [PATCH 74/83] Add pref to autolaunch hotkey at boot --- .../preferences/cubit/preferences_cubit.dart | 9 +++ .../preferences/cubit/preferences_state.dart | 8 +- lib/infrastructure/launcher/launcher.dart | 4 + lib/infrastructure/launcher/src/hotkey.dart | 62 ++++++++++++++ .../widgets/integration_section.dart | 81 ++++++++++++++----- 5 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 lib/infrastructure/launcher/src/hotkey.dart diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index cbbd6ed2..9f829c9c 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -22,6 +22,7 @@ class PreferencesCubit extends Cubit { : _prefs = prefs, super( PreferencesState( + autoStartHotkey: prefs.getBool('autoStartHotkey') ?? false, autoRefresh: _checkAutoRefresh(prefs), refreshInterval: prefs.getInt('refreshInterval') ?? 5, trayIconColor: Color( @@ -54,6 +55,14 @@ class PreferencesCubit extends Cubit { } } + Future updateAutoStartHotkey(bool value) async { + final successful = await Launcher.hotkey.autoStart(value); + if (!successful) return false; + await _prefs.setBool(key: 'autoStartHotkey', value: value); + emit(state.copyWith(autoStartHotkey: value)); + return true; + } + Future updateAutoRefresh([bool? autoEnabled]) async { if (autoEnabled != null) { await _prefs.setBool(key: 'autoRefresh', value: autoEnabled); diff --git a/lib/application/preferences/cubit/preferences_state.dart b/lib/application/preferences/cubit/preferences_state.dart index 48696ffe..81dc7b35 100644 --- a/lib/application/preferences/cubit/preferences_state.dart +++ b/lib/application/preferences/cubit/preferences_state.dart @@ -1,6 +1,8 @@ part of 'preferences_cubit.dart'; class PreferencesState extends Equatable { + final bool autoStartHotkey; + /// Whether or not to automatically refresh the list of open windows. final bool autoRefresh; @@ -10,20 +12,24 @@ class PreferencesState extends Equatable { final Color trayIconColor; const PreferencesState({ + required this.autoStartHotkey, required this.autoRefresh, required this.refreshInterval, required this.trayIconColor, }); @override - List get props => [autoRefresh, refreshInterval, trayIconColor]; + List get props => + [autoStartHotkey, autoRefresh, refreshInterval, trayIconColor]; PreferencesState copyWith({ + bool? autoStartHotkey, bool? autoRefresh, int? refreshInterval, Color? trayIconColor, }) { return PreferencesState( + autoStartHotkey: autoStartHotkey ?? this.autoStartHotkey, autoRefresh: autoRefresh ?? this.autoRefresh, refreshInterval: refreshInterval ?? this.refreshInterval, trayIconColor: trayIconColor ?? this.trayIconColor, diff --git a/lib/infrastructure/launcher/launcher.dart b/lib/infrastructure/launcher/launcher.dart index e4b26a75..1598590f 100644 --- a/lib/infrastructure/launcher/launcher.dart +++ b/lib/infrastructure/launcher/launcher.dart @@ -2,6 +2,8 @@ import 'dart:io'; import 'package:path_provider/path_provider.dart' as pp; +import 'src/hotkey.dart'; + /// Manage launcher entry. /// /// Enables system integration for Nyrna to provide a shortcut in the user's @@ -9,6 +11,8 @@ import 'package:path_provider/path_provider.dart' as pp; /// /// Currently only for the portable version on Linux. class Launcher { + static Hotkey get hotkey => Hotkey(); + /// Add a launcher entry for Nyrna with icon. static Future add() async { await _addLauncher(); diff --git a/lib/infrastructure/launcher/src/hotkey.dart b/lib/infrastructure/launcher/src/hotkey.dart new file mode 100644 index 00000000..3437e5fb --- /dev/null +++ b/lib/infrastructure/launcher/src/hotkey.dart @@ -0,0 +1,62 @@ +import 'dart:io'; + +/// Hotkey service only exists for Windows, as Linux supports settings +/// custom hotkeys very easily by the end-user with no overhead. +class Hotkey { + String _hotkeyExePath() { + return Directory.current.path + '\\toggle_active_hotkey.exe'; + } + + Future _createStartupShortcut() async { + final exePath = _hotkeyExePath(); + final result = await Process.run('powershell', [ + '-NoProfile', + '\$wShell = New-Object -comObject WScript.Shell', + ';', + '\$startupDir = \$env:APPDATA + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"', + ';', + '\$shortcut = \$wShell.CreateShortcut("\$startupDir\\Nyrna Hotkey.lnk")', + ';', + '\$shortcut.TargetPath = "$exePath"', + ';', + '\$shortcut.Save()', + ]); + if (result.stderr != '') { + print('Unable to create startup shortcut: ${result.stderr}'); + return false; + } + return true; + } + + Future _deleteStartupShortcut() async { + final result = await Process.run('powershell', [ + '-NoProfile', + '\$startupDir = \$env:APPDATA + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"', + ';', + '\$startupDir', + ]); + if (result.stderr != '') { + print('Unable to find startup dir: ${result.stderr}'); + return false; + } + final startupDir = result.stdout.toString().trim(); + final shortcut = File(startupDir + '\\Nyrna Hotkey.lnk'); + final exists = await shortcut.exists(); + if (!exists) return false; + try { + await shortcut.delete(); + } catch (e) { + print('Unable to delete shortcut: $e'); + return false; + } + return true; + } + + /// Enable or disable the Windows hotkey trigger being + /// auto-launched at system startup. + Future autoStart(bool enabled) async { + return (enabled) + ? await _createStartupShortcut() + : await _deleteStartupShortcut(); + } +} diff --git a/lib/presentation/preferences/widgets/integration_section.dart b/lib/presentation/preferences/widgets/integration_section.dart index 93dce607..f60b26c9 100644 --- a/lib/presentation/preferences/widgets/integration_section.dart +++ b/lib/presentation/preferences/widgets/integration_section.dart @@ -7,33 +7,74 @@ import 'package:nyrna/application/preferences/cubit/preferences_cubit.dart'; import '../../styles.dart'; -/// Add shortcuts and icons for portable builds. +/// Add shortcuts and icons for portable builds or autostart. class IntegrationSection extends StatelessWidget { const IntegrationSection({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return (!Platform.isLinux) // TODO: Add integration function for Windows. - ? const SizedBox() - : BlocBuilder( + if (Platform.isWindows) { + return const _WindowsIntegration(); + } else { + return const _LinuxIntegration(); + } + } +} + +class _WindowsIntegration extends StatelessWidget { + const _WindowsIntegration({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Spacers.verticalMedium, + const Text('System Integration'), + Spacers.verticalXtraSmall, + ListTile( + title: const Text('Start hotkey automatically at system startup'), + leading: const Icon(Icons.add_circle_outline), + trailing: BlocBuilder( builder: (context, state) { - return state.isPortable - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Spacers.verticalMedium, - const Text('System Integration'), - const SizedBox(height: 8), - ListTile( - leading: const Icon(Icons.add_circle_outline), - title: const Text('Add Nyrna to launcher'), - onTap: () => _confirmAddToLauncher(context), - ), - ], - ) - : const SizedBox(); + return Switch( + value: state.autoStartHotkey, + onChanged: (value) async { + await preferencesCubit.updateAutoStartHotkey(value); + }, + ); }, - ); + ), + ), + ], + ); + } +} + +class _LinuxIntegration extends StatelessWidget { + const _LinuxIntegration({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return state.isPortable + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Spacers.verticalMedium, + const Text('System Integration'), + Spacers.verticalXtraSmall, + ListTile( + leading: const Icon(Icons.add_circle_outline), + title: const Text('Add Nyrna to launcher'), + onTap: () => _confirmAddToLauncher(context), + ), + ], + ) + : const SizedBox(); + }, + ); } /// Confirm with the user before adding .desktop and icon files. From 525ef9710ddcdea86e71efbc0def99a6f37c9fa7 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:46:45 -0400 Subject: [PATCH 75/83] Enable autorefresh by default on Windows --- lib/application/preferences/cubit/preferences_cubit.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index 9f829c9c..c8bad95a 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -34,9 +34,7 @@ class PreferencesCubit extends Cubit { } static bool _checkAutoRefresh(Preferences prefs) { - bool? enabled = prefs.getBool('autoRefresh'); - enabled ??= (Platform.isWindows) ? false : true; - return enabled; + return prefs.getBool('autoRefresh') ?? true; } Future createLauncher() async { From 030acdea0c4c1f89b8a3c6d84b8d464c9f332aa5 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:48:09 -0400 Subject: [PATCH 76/83] Remove unused import --- lib/application/preferences/cubit/preferences_cubit.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/application/preferences/cubit/preferences_cubit.dart b/lib/application/preferences/cubit/preferences_cubit.dart index c8bad95a..51878a53 100644 --- a/lib/application/preferences/cubit/preferences_cubit.dart +++ b/lib/application/preferences/cubit/preferences_cubit.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; From ceb66d3ca745882af74c733c42e80892bd026075 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:58:29 -0400 Subject: [PATCH 77/83] Use New-Item to create PORTABLE file --- .github/workflows/build-win32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index fc089ed9..dab440ab 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -49,7 +49,7 @@ jobs: run: | iscc packaging\win32\inno_setup_script.iss - name: Add PORTABLE file - run: type NUL > build\Nyrna\PORTABLE + run: New-Item -Path .\build\Nyrna\ -Name "PORTABLE" -ItemType "file" - uses: actions/upload-artifact@v2 with: name: nyrna-windows-portable From 16f632f38bfd2060cc2d4ffc9b18d1c15f439740 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 12:08:06 -0400 Subject: [PATCH 78/83] Bump snapcraft version --- snap/snapcraft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index e83f3b39..28ad2863 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: nyrna -version: 2.0.0 +version: 2.1.0 summary: Suspend games and applications description: | Similar to the incredibly useful sleep/suspend function found in From 190e7c690f330ef17ee23945c5a2fdf89ed19ee6 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 12:08:48 -0400 Subject: [PATCH 79/83] Update CI version logic Only needed for the AppImage for updating now --- .github/workflows/build-linux-appimage.yml | 4 +++- .github/workflows/build-linux-portable.yml | 4 ---- .github/workflows/build-win32.yml | 4 ---- VERSION | 1 - 4 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 VERSION diff --git a/.github/workflows/build-linux-appimage.yml b/.github/workflows/build-linux-appimage.yml index bc4b4b0e..5abde2a2 100644 --- a/.github/workflows/build-linux-appimage.yml +++ b/.github/workflows/build-linux-appimage.yml @@ -17,9 +17,11 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y ninja-build libgtk-3-dev libblkid-dev zsync + sudo apt install -y python3 jq + pip install yq - name: Set environment variables run: | - VER=$(cat VERSION) + VER=$(yq -r .version < pubspec.yaml) echo "VERSION=$VER" >> $GITHUB_ENV - name: Flutter setup run: | diff --git a/.github/workflows/build-linux-portable.yml b/.github/workflows/build-linux-portable.yml index 60d81d7d..9f3d86a7 100644 --- a/.github/workflows/build-linux-portable.yml +++ b/.github/workflows/build-linux-portable.yml @@ -16,16 +16,12 @@ jobs: with: channel: beta - run: | - VER=$(cat VERSION) - echo "VERSION=$VER" >> $GITHUB_ENV - flutter config --enable-linux-desktop flutter pub get flutter build linux mv build/linux/x64/release/bundle nyrna touch nyrna/PORTABLE - cp VERSION nyrna/VERSION - name: Build toggle_active_window run: | cd packages/active_window diff --git a/.github/workflows/build-win32.yml b/.github/workflows/build-win32.yml index dab440ab..95d453d3 100644 --- a/.github/workflows/build-win32.yml +++ b/.github/workflows/build-win32.yml @@ -13,9 +13,6 @@ jobs: - uses: subosito/flutter-action@v1 with: channel: beta - - name: Read VERSION file - id: getversion - run: echo "::set-output name=version::$(cat VERSION)" - name: Set up Visual Studio shell uses: egor-tensin/vs-shell@v2 with: @@ -32,7 +29,6 @@ jobs: move build\windows\runner\Release build\Nyrna - copy VERSION build\Nyrna xcopy C:\Windows\System32\msvcp140.dll build\Nyrna xcopy C:\Windows\System32\vcruntime140.dll build\Nyrna xcopy C:\Windows\System32\vcruntime140_1.dll build\Nyrna diff --git a/VERSION b/VERSION deleted file mode 100644 index 359a5b95..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.0.0 \ No newline at end of file From fe6255561d45993e91c50494afd8c2c15dd9731b Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 12:15:18 -0400 Subject: [PATCH 80/83] AppImage: do not reference VERSION file --- packaging/linux/appimage/AppImageBuilder.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/linux/appimage/AppImageBuilder.yml b/packaging/linux/appimage/AppImageBuilder.yml index 5578387c..37085516 100644 --- a/packaging/linux/appimage/AppImageBuilder.yml +++ b/packaging/linux/appimage/AppImageBuilder.yml @@ -3,7 +3,6 @@ version: 1 script: - rm -rf AppDir || true - cp -r build/linux/x64/release/bundle build/AppDir - - cp VERSION build/AppDir - mkdir -p build/AppDir/usr/share/icons/hicolor/256x256/apps/ - cp assets/icons/nyrna.png build/AppDir/usr/share/icons/hicolor/256x256/apps/ - mkdir -p build/AppDir/usr/share/applications From 2e914fdbb373b225605e40bac32cedc54d825bf6 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 13:47:47 -0400 Subject: [PATCH 81/83] Add screenshot to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8819fa1e..0cce23b6 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ **Suspend games and applications.** +![Nyrna interface](assets/../docs/assets/images/nyrna-window.png) + Similar to the incredibly useful sleep/suspend function found in consoles like the Nintendo Switch and Sony PlayStation; suspend your game (and its resource usage) at any time, and resume whenever you wish - at the push of a button. Nyrna can be used to suspend normal, non-game applications as well. For example: From 1eb30821280463d94c1e90f88ad788959a9ee10a Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 14:08:19 -0400 Subject: [PATCH 82/83] Update usage instructions --- docs/_pages/usage.md | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/docs/_pages/usage.md b/docs/_pages/usage.md index d038b5c7..c48b6491 100644 --- a/docs/_pages/usage.md +++ b/docs/_pages/usage.md @@ -32,14 +32,25 @@ permalink: /usage ## Toggle active window -Nyrna can be used to toggle the suspend / resume state of one active window by -setting a hotkey to launch Nyrna with the `-t` or `--toggle` flag. +Nyrna can be used to toggle the suspend / resume state of one active window: -Once the hotkey is set, simply press that key to have the window of your +- Linux + - Set a hotkey in system settings to run the `toggle_active_window` executable + from the Nyrna directory + +- Windows + - Run the `toggle_active_window.exe` file from the Nyrna directory to add an + icon to the system tray that will listen for the `Pause` key to be pressed. + - Optionally, from Nyrna's settings you can set this hotkey monitor to run + automatically at boot. + +Now simply press the hotkey on your keyboard to have the window of your currently active application suspended. A subsequent press will resume that application. -*Note: Not reliable if Nyrna is already running.* +**Tip:** You can use something like +[AntiMicro](https://github.com/AntiMicro/antimicro) to trigger this hotkey with +your gamepad, allowing you to suspend/resume your game with just your controller. **Linux Example** @@ -50,7 +61,7 @@ application. - Edit -> - New -> - Global Shortcut - - Action: `/path/to/nyrna -t` + - Action: `/path/to/nyrna/toggle_active_window` ![KDE custom shortcut](assets/images/custom-shortcut-linux-kde.png) {% endcapture %} @@ -59,22 +70,3 @@ application.

          KDE System Settings:

          {{ linux-example-text | markdownify }} - - -**Windows Example** - -{% capture windows-example-text %} -- Right click shortcut -> Properties -- Shortcut tab - - Target -> Edit ending to include `-t` or `--toggle`, like: - `C:\Nyrna\nyrna.exe -t` - - Shortcut key -> Choose key to trigger the toggle function - - Apply - -![Windows custom shortcut](assets/images/custom-shortcut-windows.png) -{% endcapture %} - -
          -

          Create or edit Nyrna shortcut:

          - {{ windows-example-text | markdownify }} -
          From cf0176622e92f8bba73693d96765a0910d9159c1 Mon Sep 17 00:00:00 2001 From: Kristen McWilliam <9575627+Merrit@users.noreply.github.com> Date: Sat, 14 Aug 2021 14:09:50 -0400 Subject: [PATCH 83/83] Remove unused build scripts Building is handled by GitHub CI nowadays.. --- packaging/linux/build-linux.sh | 54 ---------------------------- packaging/win32/build.bat | 66 ---------------------------------- 2 files changed, 120 deletions(-) delete mode 100755 packaging/linux/build-linux.sh delete mode 100644 packaging/win32/build.bat diff --git a/packaging/linux/build-linux.sh b/packaging/linux/build-linux.sh deleted file mode 100755 index 7748b2c2..00000000 --- a/packaging/linux/build-linux.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -echo -e "Nyrna build script for Linux \n" - -# Generic callable confirm function. -confirm() { - # call with a prompt string or use a default - read -r -p "${1:-Are you sure? [y/N]} " response - case "$response" in - [yY][eE][sS]|[yY]) - true - ;; - *) - false - ;; - esac -} - - -# Confirm tests were run. -if confirm "Did you run tests? [y/N]"; then - echo -else - echo "Run tests first." && exit -fi - - -# Confirm version number has been updated. -if confirm "Did you update version number (constant, pubspec, changelog)? [y/N]"; then - echo -else - echo "Update version number first." && exit -fi - - -# Build -echo -e "Starting build.. \n" - - -cd ../.. - -flutter clean - -flutter pub get - -flutter build linux - -cd build/linux/release/ || cd build/linux/x64/release/ - -mv bundle nyrna - -tar -zcvf nyrna.tar.gz nyrna - -rm -rf nyrna diff --git a/packaging/win32/build.bat b/packaging/win32/build.bat deleted file mode 100644 index 5a5d477f..00000000 --- a/packaging/win32/build.bat +++ /dev/null @@ -1,66 +0,0 @@ -@echo off - -:: Run this script from project root - -set appName=Nyrna - -:: Remember to update the version number before packaging. -setlocal -:PROMPT -SET /P AREYOUSURE=Did you update VERSION? (Y/[N])? -IF /I "%AREYOUSURE%" NEQ "Y" GOTO END - - -:: Start the packaging process. - - -echo Cleaning project.. -:: Make sure output directory is clean. -rmdir /s /Q %cd%\build -echo. -call flutter clean - -echo Getting dependencies.. -echo. -call flutter pub get - -echo. -echo Building %appName% Windows version.. -echo. -call flutter build windows - -echo Moving & renaming compiled bundle -move %cd%\build\windows\runner\Release %cd%\build\%appName% - -:: Set directory variables. -set compiledFolder=%cd%\build\%appName% - -echo. -echo Copying Visual C++ Redistributable libraries to output directory -echo. -xcopy C:\Windows\System32\msvcp140.dll %compiledFolder% -xcopy C:\Windows\System32\vcruntime140.dll %compiledFolder% -xcopy C:\Windows\System32\vcruntime140_1.dll %compiledFolder% - - -echo. -echo Copying VERSION into bundle -echo. -copy VERSION %compiledFolder%\VERSION - -echo Creating installer version.. -call iscc %cd%\packaging\win32\inno_setup_script.iss - -echo. -echo Creating PORTABLE file before packaging portable version -echo. -echo null > %compiledFolder%\PORTABLE - -echo Creating portable version archive.. -call powershell Compress-Archive %compiledFolder% %cd%\build\%appName%-windows-portable.zip - - -echo Finished building and packaging %appName% - -:END -endlocal