From 03fd29c1e6e086aaa42a93e6095147c663553500 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:40:53 +0100 Subject: [PATCH 1/8] feat(config): add example vendor configuration for Open Resin Alliance --- example_vendor.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 example_vendor.cfg diff --git a/example_vendor.cfg b/example_vendor.cfg new file mode 100644 index 0000000..e64bb4c --- /dev/null +++ b/example_vendor.cfg @@ -0,0 +1,8 @@ +{ + "vendor": { + "vendorName": "Open Resin Alliance", + "vendorMachineName": "Ares V2", + "vendorUrl": "https://openresin.org", + "vendorThemeSeed": "#FF00FA00" + } +} \ No newline at end of file From 72c19edf0b1d29e3466a38446bfc08089161103f Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:41:19 +0100 Subject: [PATCH 2/8] chore(notice, settings): update attribution to Open Resin Alliance --- NOTICE | 4 ++-- lib/settings/settings_screen.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NOTICE b/NOTICE index c694407..101c959 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,6 @@ NOTICE -This product includes software developed by [TheContrappostoShop](https://github.com/TheContrappostoShop). +This product includes software developed by [Open Resin Alliance](https://github.com/Open-Resin-Alliance). Orion is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -10,4 +10,4 @@ Unless required by applicable law or agreed to in writing, software distributed This product also includes third-party software components. Please refer to the LICENSE file for more information. -© 2024 TheContrappostoShop. All rights reserved. \ No newline at end of file +© 2024 Open Resin Alliance. All rights reserved. diff --git a/lib/settings/settings_screen.dart b/lib/settings/settings_screen.dart index 7259268..756e571 100644 --- a/lib/settings/settings_screen.dart +++ b/lib/settings/settings_screen.dart @@ -277,7 +277,7 @@ class SettingsScreenState extends State { 'Version {{ version }} - {{ commit }}', applicationName: 'Orion', applicationLegalese: - 'Apache License 2.0 - Copyright © TheContrappostoShop {{ year }}', + 'Apache License 2.0 - Copyright © {{ year }} Open Resin Alliance', children: [ Padding( padding: From c289beeae38185018de9a16401adfaa82ee94860 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:41:54 +0100 Subject: [PATCH 3/8] feat(dependencies): add flex_seed_scheme package version 3.4.1 --- lib/themes/themes.dart | 15 +++++++++++---- pubspec.lock | 8 ++++++++ pubspec.yaml | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/themes/themes.dart b/lib/themes/themes.dart index deb3b9d..ef286d2 100644 --- a/lib/themes/themes.dart +++ b/lib/themes/themes.dart @@ -16,12 +16,18 @@ */ import 'package:flutter/material.dart'; +import 'package:flex_seed_scheme/flex_seed_scheme.dart'; +import '../util/orion_config.dart'; + +final _config = OrionConfig(); +final _seedColor = _config.getVendorThemeSeed(); final ThemeData themeLight = ThemeData( fontFamily: 'AtkinsonHyperlegible', - colorScheme: ColorScheme.fromSeed( - seedColor: const Color(0xff6750a4), + colorScheme: SeedColorScheme.fromSeeds( + primaryKey: _seedColor, brightness: Brightness.light, + variant: FlexSchemeVariant.soft, ), appBarTheme: const AppBarTheme( titleTextStyle: TextStyle( @@ -57,9 +63,10 @@ final ThemeData themeLight = ThemeData( final ThemeData themeDark = ThemeData( fontFamily: 'AtkinsonHyperlegible', - colorScheme: ColorScheme.fromSeed( - seedColor: const Color(0xff6750a4), + colorScheme: SeedColorScheme.fromSeeds( + primaryKey: _seedColor, brightness: Brightness.dark, + variant: FlexSchemeVariant.soft, ), appBarTheme: const AppBarTheme( titleTextStyle: TextStyle( diff --git a/pubspec.lock b/pubspec.lock index a5bfc28..fae069b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -190,6 +190,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + flex_seed_scheme: + dependency: "direct main" + description: + name: flex_seed_scheme + sha256: "7639d2c86268eff84a909026eb169f008064af0fb3696a651b24b0fa24a40334" + url: "https://pub.dev" + source: hosted + version: "3.4.1" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index af4e1ad..104d38b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,6 +63,7 @@ dependencies: toastification: ^2.0.0 async: ^2.11.0 fading_edge_scrollview: ^4.1.1 + flex_seed_scheme: ^3.4.1 dev_dependencies: flutter_test: From ba5bf4d5af9e35bedebc49d52aef7ad1fb671c46 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:43:02 +0100 Subject: [PATCH 4/8] feat(home): update app bar title to use dynamic machine name --- lib/home/home_screen.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/home/home_screen.dart b/lib/home/home_screen.dart index fc95efb..6508354 100644 --- a/lib/home/home_screen.dart +++ b/lib/home/home_screen.dart @@ -21,6 +21,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:orion/api_services/api_services.dart'; +import 'package:orion/settings/about_screen.dart'; import 'package:orion/util/hold_button.dart'; import 'package:orion/util/orion_config.dart'; @@ -61,8 +62,8 @@ class HomeScreenState extends State { return Scaffold( appBar: AppBar( - title: const Text( - '3D Printer', + title: Text( + config.getString('machineName', category: 'machine'), textAlign: TextAlign.center, ), centerTitle: true, From 27f0a1e9375bc11f1d6820b1a3a18d6208fcbd16 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:43:29 +0100 Subject: [PATCH 5/8] feat(settings): AboutScreen: implement dynamic machine name editing in About screen --- lib/settings/about_screen.dart | 102 ++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 8 deletions(-) diff --git a/lib/settings/about_screen.dart b/lib/settings/about_screen.dart index f4923da..64282f3 100644 --- a/lib/settings/about_screen.dart +++ b/lib/settings/about_screen.dart @@ -21,11 +21,15 @@ import 'package:logging/logging.dart'; import 'package:orion/pubspec.dart'; import 'package:orion/themes/themes.dart'; import 'package:orion/util/orion_config.dart'; +import 'package:orion/util/orion_kb/orion_keyboard_expander.dart'; +import 'package:orion/util/orion_kb/orion_textfield_spawn.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:toastification/toastification.dart'; import 'dart:io'; Logger _logger = Logger('AboutScreen'); +OrionConfig config = OrionConfig(); Future executeCommand(String command, List arguments) async { final result = await Process.run(command, arguments); @@ -77,6 +81,12 @@ class AboutScreenState extends State { int qrTapCount = 0; Toastification toastification = Toastification(); + late String customName; + + final ScrollController _scrollController = ScrollController(); + final GlobalKey cNameTextFieldKey = + GlobalKey(); + @override Widget build(BuildContext context) { bool isLandscape = @@ -99,7 +109,7 @@ class AboutScreenState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildNameCard('3D Printer'), + buildNameCard(config.getString('machineName', category: 'machine')), buildInfoCard('Serial Number', kDebugMode ? 'DBG-0001-001' : 'N/A'), buildVersionCard(), buildHardwareCard(), @@ -116,7 +126,8 @@ class AboutScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildNameCard('3D Printer'), + buildNameCard( + config.getString('machineName', category: 'machine')), buildInfoCard('Serial Number', kDebugMode ? 'DBG-0001-001' : 'Currently Unavailable'), buildVersionCard(), @@ -178,12 +189,87 @@ class AboutScreenState extends State { return Card.outlined( elevation: 1.0, child: ListTile( - title: Text( - title, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary), + contentPadding: const EdgeInsets.symmetric(horizontal: 16.0), + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + title, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary), + overflow: TextOverflow.fade, + softWrap: false, + ), + ), + ElevatedButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Center(child: Text('Custom Machine Name')), + content: SizedBox( + width: MediaQuery.of(context).size.width * 0.5, + child: SingleChildScrollView( + child: Column( + children: [ + SpawnOrionTextField( + key: cNameTextFieldKey, + keyboardHint: 'Enter a custom name', + locale: + Localizations.localeOf(context).toString(), + scrollController: _scrollController, + presetText: config.getString('machineName', + category: 'machine'), + ), + OrionKbExpander(textFieldKey: cNameTextFieldKey), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Close', + style: TextStyle(fontSize: 20)), + ), + TextButton( + onPressed: () { + setState(() { + customName = cNameTextFieldKey.currentState! + .getCurrentText(); + config.setString('machineName', customName, + category: 'machine'); + }); + Navigator.of(context).pop(); + }, + child: const Text('Confirm', + style: TextStyle(fontSize: 20)), + ), + ], + ); + }, + ); + }, + child: Row( + children: [ + const Text( + 'Edit', + style: TextStyle( + fontSize: 20, + ), + ), + const SizedBox(width: 10), + PhosphorIcon(PhosphorIcons.notePencil()), + ], + ), + ), + ], ), ), ); From fe9d7590590d9954ead963e308f6bc8e6e660d68 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:44:00 +0100 Subject: [PATCH 6/8] feat(util): orion_config: enhance vendor configuration handling and add theme seed retrieval --- lib/util/orion_config.dart | 131 +++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/lib/util/orion_config.dart b/lib/util/orion_config.dart index 5b807c1..1b4ba44 100644 --- a/lib/util/orion_config.dart +++ b/lib/util/orion_config.dart @@ -83,78 +83,93 @@ class OrionConfig { setFlag(flagName, !currentValue, category: category); } + Color getVendorThemeSeed() { + var config = _getConfig(); + var seedHex = config['vendor']?['vendorThemeSeed'] ?? '#ff6750a4'; + // Remove the '#' and parse the hex color + _logger.config('Vendor theme seed: $seedHex'); + return Color(int.parse('${seedHex.replaceAll('#', '')}', radix: 16)); + } + + Map _getVendorConfig() { + var fullPath = path.join(_configPath, 'vendor.cfg'); + var vendorFile = File(fullPath); + + if (!vendorFile.existsSync() || vendorFile.readAsStringSync().isEmpty) { + return {}; + } + + try { + return Map.from( + json.decode(vendorFile.readAsStringSync())); + } catch (e) { + _logger.warning('Failed to parse vendor.cfg: $e'); + return {}; + } + } + Map _getConfig() { var fullPath = path.join(_configPath, 'orion.cfg'); var configFile = File(fullPath); + var vendorConfig = _getVendorConfig(); + + // Get vendor machine name if available + var defaultMachineName = + vendorConfig['vendor']?['vendorMachineName'] ?? '3D Printer'; + + var defaultConfig = { + 'general': { + 'themeMode': 'dark', + }, + 'advanced': {}, + 'machine': { + 'machineName': defaultMachineName, + 'firstRun': true, + }, + }; if (!configFile.existsSync() || configFile.readAsStringSync().isEmpty) { - var defaultConfig = { - 'general': { - 'themeMode': 'dark', - }, - 'advanced': {}, - }; - _writeConfig(defaultConfig); - return defaultConfig; + // Remove vendor section before writing + var configToWrite = Map.from(defaultConfig); + _writeConfig(configToWrite); + // Return merged view for reading + return _mergeConfigs(defaultConfig, vendorConfig); } - return json.decode(configFile.readAsStringSync()); + var userConfig = + Map.from(json.decode(configFile.readAsStringSync())); + + // Return merged view for reading + return _mergeConfigs( + _mergeConfigs(defaultConfig, vendorConfig), userConfig); } void _writeConfig(Map config) { + // Remove any vendor section before writing to orion.cfg + var configToWrite = Map.from(config); + configToWrite.remove('vendor'); + var fullPath = path.join(_configPath, 'orion.cfg'); var configFile = File(fullPath); var encoder = const JsonEncoder.withIndent(' '); - configFile.writeAsStringSync(encoder.convert(config)); + configFile.writeAsStringSync(encoder.convert(configToWrite)); } - void blowUp(BuildContext context, String imagePath) { - _logger.severe('Blowing up the app'); - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return FutureBuilder( - future: Future.delayed(const Duration(seconds: 4)), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return SafeArea( - child: Dialog( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.zero), - insetPadding: EdgeInsets.zero, - backgroundColor: Theme.of(context).colorScheme.surface, - child: const Center( - child: SizedBox( - height: 75, - width: 75, - child: CircularProgressIndicator( - strokeWidth: 6, - ), - ), - ), - ), - ); - } else { - Future.delayed(const Duration(seconds: 10), () { - Navigator.of(context).pop(true); - }); - return SafeArea( - child: Dialog( - insetPadding: EdgeInsets.zero, - backgroundColor: Colors.transparent, - child: Image.asset( - imagePath, - fit: BoxFit.fill, - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - ), - ), - ); - } - }, - ); - }, - ); + Map _mergeConfigs( + Map base, Map overlay) { + var result = Map.from(base); + + overlay.forEach((key, value) { + if (value is Map) { + result[key] = result.containsKey(key) + ? _mergeConfigs(Map.from(result[key] ?? {}), + Map.from(value)) + : Map.from(value); + } else { + result[key] = value; + } + }); + + return result; } } From a00cd36e335205018089e182f0ba924dc3e2ae5a Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Sun, 8 Dec 2024 00:44:35 +0100 Subject: [PATCH 7/8] feat(settings): GeneralCfgScreen: refactor to remove self-destruct mode and add machine name configuration --- lib/settings/general_screen.dart | 60 ++------------------------------ 1 file changed, 2 insertions(+), 58 deletions(-) diff --git a/lib/settings/general_screen.dart b/lib/settings/general_screen.dart index 99cd5be..3fa47d5 100644 --- a/lib/settings/general_screen.dart +++ b/lib/settings/general_screen.dart @@ -48,7 +48,7 @@ class GeneralCfgScreenState extends State { late bool overrideUpdateCheck; late String overrideRelease; late bool verboseLogging; - late bool selfDestructMode; + late String machineName; late String originalRotation; @@ -80,23 +80,10 @@ class GeneralCfgScreenState extends State { overrideRelease = config.getString('overrideRelease', category: 'developer'); verboseLogging = config.getFlag('verboseLogging', category: 'developer'); - selfDestructMode = - config.getFlag('selfDestructMode', category: 'topsecret'); - screenRotation = screenRotation == '' ? '0' : screenRotation; config.setString('screenRotation', screenRotation, category: 'advanced'); originalRotation = screenRotation; - } - - bool shouldDestruct() { - final rand = Random(); - if (selfDestructMode && rand.nextInt(1000) < 2) { - setState(() { - selfDestructMode = false; - }); - return true; - } - return !selfDestructMode; + machineName = config.getString('machineName', category: 'machine'); } bool isJune() { @@ -136,49 +123,6 @@ class GeneralCfgScreenState extends State { ), ), ), - if (shouldDestruct()) - Card( - elevation: 1, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - 10), // match this with your Card's border radius - gradient: LinearGradient( - colors: [ - Colors.red, - Colors.orange, - Colors.yellow, - Colors.green, - Colors.blue, - Colors.indigo, - Colors.purple - ] - .map((color) => - Color.lerp(color, Colors.black, 0.25)) - .where((color) => color != null) - .cast() - .toList(), - ), - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: OrionListTile( - ignoreColor: true, - title: 'Self-Destruct Mode', - icon: PhosphorIcons.skull, - value: selfDestructMode, - onChanged: (bool value) { - setState(() { - selfDestructMode = value; - config.setFlag('selfDestructMode', selfDestructMode, - category: 'topsecret'); - config.blowUp(context, 'assets/images/bsod.png'); - }); - }, - ), - ), - ), - ), Card.outlined( elevation: 1, child: Padding( From e2e2c544242754415bde8437f68ca04156a6b8f2 Mon Sep 17 00:00:00 2001 From: PaulGD03 Date: Tue, 7 Jan 2025 16:30:43 +0100 Subject: [PATCH 8/8] fix(settings, util): undo removal of self-destruct easter egg - will be replaced by a new easter egg in the future. --- lib/settings/general_screen.dart | 57 ++++++++++++++++++++++++++++++++ lib/util/orion_config.dart | 50 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/lib/settings/general_screen.dart b/lib/settings/general_screen.dart index 3fa47d5..2f4b784 100644 --- a/lib/settings/general_screen.dart +++ b/lib/settings/general_screen.dart @@ -48,6 +48,7 @@ class GeneralCfgScreenState extends State { late bool overrideUpdateCheck; late String overrideRelease; late bool verboseLogging; + late bool selfDestructMode; late String machineName; late String originalRotation; @@ -80,12 +81,25 @@ class GeneralCfgScreenState extends State { overrideRelease = config.getString('overrideRelease', category: 'developer'); verboseLogging = config.getFlag('verboseLogging', category: 'developer'); + selfDestructMode = + config.getFlag('selfDestructMode', category: 'topsecret'); screenRotation = screenRotation == '' ? '0' : screenRotation; config.setString('screenRotation', screenRotation, category: 'advanced'); originalRotation = screenRotation; machineName = config.getString('machineName', category: 'machine'); } + bool shouldDestruct() { + final rand = Random(); + if (selfDestructMode && rand.nextInt(1000) < 2) { + setState(() { + selfDestructMode = false; + }); + return true; + } + return !selfDestructMode; + } + bool isJune() { final now = DateTime.now(); return now.month == 6; @@ -123,6 +137,49 @@ class GeneralCfgScreenState extends State { ), ), ), + if (shouldDestruct()) + Card( + elevation: 1, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + 10), // match this with your Card's border radius + gradient: LinearGradient( + colors: [ + Colors.red, + Colors.orange, + Colors.yellow, + Colors.green, + Colors.blue, + Colors.indigo, + Colors.purple + ] + .map((color) => + Color.lerp(color, Colors.black, 0.25)) + .where((color) => color != null) + .cast() + .toList(), + ), + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: OrionListTile( + ignoreColor: true, + title: 'Self-Destruct Mode', + icon: PhosphorIcons.skull, + value: selfDestructMode, + onChanged: (bool value) { + setState(() { + selfDestructMode = value; + config.setFlag('selfDestructMode', selfDestructMode, + category: 'topsecret'); + config.blowUp(context, 'assets/images/bsod.png'); + }); + }, + ), + ), + ), + ), Card.outlined( elevation: 1, child: Padding( diff --git a/lib/util/orion_config.dart b/lib/util/orion_config.dart index 1b4ba44..d90ac5e 100644 --- a/lib/util/orion_config.dart +++ b/lib/util/orion_config.dart @@ -155,6 +155,56 @@ class OrionConfig { configFile.writeAsStringSync(encoder.convert(configToWrite)); } + void blowUp(BuildContext context, String imagePath) { + _logger.severe('Blowing up the app'); + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return FutureBuilder( + future: Future.delayed(const Duration(seconds: 4)), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return SafeArea( + child: Dialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.zero), + insetPadding: EdgeInsets.zero, + backgroundColor: Theme.of(context).colorScheme.surface, + child: const Center( + child: SizedBox( + height: 75, + width: 75, + child: CircularProgressIndicator( + strokeWidth: 6, + ), + ), + ), + ), + ); + } else { + Future.delayed(const Duration(seconds: 10), () { + Navigator.of(context).pop(true); + }); + return SafeArea( + child: Dialog( + insetPadding: EdgeInsets.zero, + backgroundColor: Colors.transparent, + child: Image.asset( + imagePath, + fit: BoxFit.fill, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + ), + ), + ); + } + }, + ); + }, + ); + } + Map _mergeConfigs( Map base, Map overlay) { var result = Map.from(base);