diff --git a/lib/core/color_utils.dart b/lib/core/color_utils.dart index e7fd974..009fb99 100644 --- a/lib/core/color_utils.dart +++ b/lib/core/color_utils.dart @@ -1,4 +1,4 @@ -import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'parser/parser.dart'; @@ -25,6 +25,30 @@ class ColorUtils { ]; } } + + static Color darken(Color color, double amount) { + assert(amount >= 0 && amount <= 1); + + final hsl = HSLColor.fromColor(color); + final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0)); + + return hslDark.toColor(); + } + + static Color lighten(Color color, double amount) { + assert(amount >= 0 && amount <= 1); + + final hsl = HSLColor.fromColor(color); + final hslLight = + hsl.withLightness((hsl.lightness + amount).clamp(0.0, 1.0)); + + return hslLight.toColor(); + } + + static Brightness getBrightness(Color color) => ThemeData.estimateBrightnessForColor(color); + + static bool isDark(Color color) => getBrightness(color) == Brightness.dark; + static bool isLight(Color color) => getBrightness(color) == Brightness.light; } class ColoredText extends ColorToken { @@ -378,3 +402,4 @@ const xtermColorMap = { 254: 0xFFE4E4E4, 255: 0xFFEEEEEE, }; + diff --git a/lib/core/features/game_button.dart b/lib/core/features/game_button.dart index 9371bf3..f039c53 100644 --- a/lib/core/features/game_button.dart +++ b/lib/core/features/game_button.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter/src/gestures/events.dart'; +import '../color_utils.dart'; import '../platform_utils.dart'; import '../store.dart'; @@ -248,6 +250,8 @@ class _GameButtonState extends State with GameStoreStateMixin { final parentAutomation = Automation.empty(); Offset? _dragStart; Offset? _dragEnd; + bool isHovering = false; + bool isClicking = false; // GameButtonData get data => widget.data; @@ -261,12 +265,37 @@ class _GameButtonState extends State with GameStoreStateMixin { @override Widget build(BuildContext context) { final curLabel = _currentDirectionIcon(context) ?? data.label; - final child = Container( + // final tooltip = Tooltip( + // message: [ + // GameButtonInteraction.press, + // GameButtonInteraction.longPress, + // GameButtonInteraction.dragUp, + // GameButtonInteraction.dragDown, + // GameButtonInteraction.dragLeft, + // GameButtonInteraction.dragRight, + // ] + // .map((dir) { + // final content = data.getAction(_direction)?.content; + // if (content == null || content.isEmpty) { + // return ''; + // } + // final label = dir.name.capitalize(); + // return '$label: $content'; + // }) + // .where((s) => s.isNotEmpty) + // .join('\n'), + // ); + final child = AnimatedContainer( + duration: const Duration(milliseconds: 100), width: data.size, height: data.size, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - color: _color(context), + color: isClicking + ? _dragColor(context) + : isHovering + ? _hoverColor(context) + : _color(context), ), child: GameButtonLabel(data: curLabel), ); @@ -290,15 +319,22 @@ class _GameButtonState extends State with GameStoreStateMixin { required Widget child, }) { if (PlatformUtils.isDesktop) { - return Listener( - onPointerDown: _onPointerDown, - onPointerMove: _onPointerMove, - onPointerUp: _onPointerUp, - child: child, + return MouseRegion( + onEnter: (_) => setState(() => isHovering = true), + onExit: (_) => setState(() => isHovering = false), + cursor: SystemMouseCursors.click, + child: Listener( + onPointerDown: _onPointerDown, + onPointerMove: _onPointerMove, + onPointerUp: _onPointerUp, + child: child, + ), ); } return GestureDetector( + onTapDown: _onTapDown, + onTapUp: _onTapUp, onTap: _onPressed, onLongPress: _onLongPress, onVerticalDragStart: _onDragStart, @@ -331,12 +367,43 @@ class _GameButtonState extends State with GameStoreStateMixin { Theme.of(context).buttonTheme.colorScheme?.background ?? Colors.grey; + Color _hoverColor(BuildContext context) { + final source = _color(context); + if (ColorUtils.isDark(source)) { + return ColorUtils.lighten(source, 0.05); + } + return ColorUtils.darken(source, 0.05); + } + + Color _dragColor(BuildContext context) { + final source = _color(context); + if (ColorUtils.isDark(source)) { + return ColorUtils.lighten(source, 0.1); + } + return ColorUtils.darken(source, 0.1); + } + void _onPressed() { _callCurrentDirection(); } void _onLongPress() { _callAction(data.longPressAction); + setState(() { + isClicking = false; + }); + } + + void _onTapDown(TapDownDetails details) { + setState(() { + isClicking = true; + }); + } + + void _onTapUp(TapUpDetails details) { + setState(() { + isClicking = false; + }); } void _onDragStart(DragStartDetails details) { @@ -367,6 +434,7 @@ class _GameButtonState extends State with GameStoreStateMixin { void _onPointerUp(PointerUpEvent event) { _callCurrentDirection(); setState(() { + isClicking = false; _direction = GameButtonInteraction.press; }); } @@ -374,6 +442,7 @@ class _GameButtonState extends State with GameStoreStateMixin { void _onPointerDown(PointerDownEvent event) { _dragStart = event.position; setState(() { + isClicking = true; _direction = GameButtonInteraction.press; }); } @@ -516,3 +585,4 @@ enum GameButtonInteraction { dragLeft, dragRight, } + diff --git a/lib/core/features/game_button_set.dart b/lib/core/features/game_button_set.dart index 198d933..cfdfa7c 100644 --- a/lib/core/features/game_button_set.dart +++ b/lib/core/features/game_button_set.dart @@ -23,15 +23,10 @@ class GameButtonSet extends StatelessWidget { child: Builder( builder: (context) { final containerSize = data.size; - return Container( - // decoration: BoxDecoration( - // border: Border.all(color: Colors.white), - // ), - child: SizedBox( - width: containerSize.width, - height: containerSize.height, - child: _buildButtonContainer(context), - ), + return SizedBox( + width: containerSize.width, + height: containerSize.height, + child: _buildButtonContainer(context), ); }, ), diff --git a/lib/core/features/lua.dart b/lib/core/features/lua.dart index 68b4032..e1f857d 100644 --- a/lib/core/features/lua.dart +++ b/lib/core/features/lua.dart @@ -96,7 +96,6 @@ class LuaBindings { } profile.variables[name]!.value = value; profile.saveVariable( - profile.variables.values.toList(), profile.variables[name]!, ); return 0; @@ -125,14 +124,12 @@ class LuaAliasBindings extends LuaAutomationBindings { i.enabled = state; return store.currentProfile.saveAlias(i); })); - return store.currentProfile.getAliases(); } @override Future saveSingle(Alias item, bool state) async { item.enabled = state; await store.currentProfile.saveAlias(item); - return store.currentProfile.getAliases(); } } @@ -158,14 +155,12 @@ class LuaTriggerBindings extends LuaAutomationBindings { i.enabled = state; return store.currentProfile.saveTrigger(i); })); - return store.currentProfile.getTriggers(); } @override Future saveSingle(Trigger item, bool state) async { item.enabled = state; await store.currentProfile.saveTrigger(item); - return store.currentProfile.getTriggers(); } } @@ -191,14 +186,12 @@ class LuaButtonSetBindings extends LuaAutomationBindings { i.enabled = state; return store.currentProfile.saveButtonSet(i); })); - return store.currentProfile.getTriggers(); } @override Future saveSingle(GameButtonSetData item, bool state) async { item.enabled = state; await store.currentProfile.saveButtonSet(item); - return store.currentProfile.getTriggers(); } } diff --git a/lib/core/features/plugin.dart b/lib/core/features/plugin.dart index 5b435c4..7ba3a98 100644 --- a/lib/core/features/plugin.dart +++ b/lib/core/features/plugin.dart @@ -29,7 +29,7 @@ class PluginBase extends ChangeNotifier { List> additionalLoaders() => []; - Future> loadTriggers() async { + Future> _loadTriggers() async { debugPrint('$this loadTriggers'); final triggers = await storage.readDirectory('triggers'); final triggerFiles = >[]; @@ -42,7 +42,7 @@ class PluginBase extends ChangeNotifier { return triggerFiles.map((e) => Trigger.fromJson(e)).toList(); } - Future> loadAliases() async { + Future> _loadAliases() async { debugPrint('$this loadAliases'); final aliases = await storage.readDirectory('aliases'); final aliasFiles = >[]; @@ -145,41 +145,29 @@ class PluginBase extends ChangeNotifier { return storage.deleteFile('button_sets/${buttonSet.id}'); } - Future saveVariable(List current, Variable update) async { + Future saveVariable(Variable update) async { debugPrint('$this saveVariable: $update'); - final existing = current.indexWhere( - (v) => v.name == update.name, - ); - if (existing >= 0) { - current[existing] = update; - } else { - current.add(update); - } + variables[update.name] = update; notifyListeners(); return storage.writeFile( 'vars', - {'vars': current.map((v) => v.toJson()).toList()}, + {'vars': variables.values.map((v) => v.toJson()).toList()}, ); } - Future deleteVariable(List current, Variable update) async { + Future deleteVariable(Variable update) async { debugPrint('$this deleteVariable: $update'); - final existing = current.indexWhere( - (v) => v.name == update.name, - ); - if (existing >= 0) { - current.removeAt(existing); - } + variables.remove(update.name); notifyListeners(); return storage.writeFile( 'vars', - {'vars': current.map((v) => v.toJson()).toList()}, + {'vars': variables.values.map((v) => v.toJson()).toList()}, ); } Future getTriggers() async { debugPrint('loadTriggers'); - final list = await loadTriggers(); + final list = await _loadTriggers(); triggers.clear(); triggers.addAll(list); notifyListeners(); @@ -187,7 +175,7 @@ class PluginBase extends ChangeNotifier { } Future getAliases() async { - final list = await loadAliases(); + final list = await _loadAliases(); aliases.clear(); aliases.addAll(list); notifyListeners(); diff --git a/lib/core/routes.dart b/lib/core/routes.dart index 250be59..620ad06 100644 --- a/lib/core/routes.dart +++ b/lib/core/routes.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import '../core/features/alias.dart'; import '../core/features/trigger.dart'; import '../core/store.dart'; +import '../pages/about_page.dart'; import '../pages/alias_list_page.dart'; import '../pages/alias_page.dart'; import '../pages/button_set_page.dart'; @@ -43,6 +44,7 @@ class Paths { static const shortcuts = '/shortcuts'; static const settings = '/settings'; + static const about = '/about'; } final routes = { @@ -89,7 +91,12 @@ final routes = { // variables Paths.variables: (context) => GameStore.consumer( - builder: (context, store, child) => const VariableListPage(), + builder: (context, store, child) => VariableListPage( + variables: store.currentProfile.variables.values.toList(), + onSave: (variable) async { + store.currentProfile.saveVariable(variable); + }, + ), ), Paths.variable: (context) { final variable = ModalRoute.of(context)!.settings.arguments as Variable?; @@ -143,6 +150,9 @@ final routes = { ); }, + // about + Paths.about: (context) => const AboutPage(), + // home Paths.home: (context) => HomeScaffold( builder: (context, _) { diff --git a/lib/core/string_utils.dart b/lib/core/string_utils.dart index b5da968..decfaef 100644 --- a/lib/core/string_utils.dart +++ b/lib/core/string_utils.dart @@ -12,8 +12,17 @@ List splitIntoWords(String string) { .split(RegExp(r'[\W_]+|(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])')); } -String capitalize(String string) { +String _capitalize(String string) { return splitIntoWords(string) .map((word) => word[0].toUpperCase() + word.substring(1)) .join(' '); } + +extension StringExtension on String { + String capitalize() { + return _capitalize(this); + } + String trimMultiline() { + return split('\n').map((e) => e.trim()).join('\n').trim(); + } +} diff --git a/lib/dialogs/button_editor_dialog.dart b/lib/dialogs/button_editor_dialog.dart index ac173f0..781221d 100644 --- a/lib/dialogs/button_editor_dialog.dart +++ b/lib/dialogs/button_editor_dialog.dart @@ -60,7 +60,7 @@ class _ButtonEditorDialogState extends State { initialValue: data.getAction(interaction)?.content ?? '', decoration: InputDecoration( - label: Text(capitalize(interaction.name)), + label: Text(interaction.name.capitalize()), ), onChanged: (value) { setState(() { diff --git a/lib/main.dart b/lib/main.dart index 2769137..3f9ef45 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,7 +41,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final theme = ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey), useMaterial3: true, ); return MaterialApp( diff --git a/lib/pages/about_page.dart b/lib/pages/about_page.dart new file mode 100644 index 0000000..44218f4 --- /dev/null +++ b/lib/pages/about_page.dart @@ -0,0 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class AboutPage extends StatelessWidget { + const AboutPage({super.key}); + + @override + Widget build(BuildContext context) { + final logo = SizedBox.square( + dimension: 288, child: Image.asset('assets/images/logo/logo@4x.png')); + final title = ListTile( + title: Text( + 'Mudblock', + style: Theme.of(context).textTheme.titleLarge, + ), + subtitle: const Text('By Chen Asraf'), + ); + final version = ListTile( + title: const Text( + 'Version: ', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + subtitle: FutureBuilder( + future: PackageInfo.fromPlatform().then((pkg) => pkg.version), + builder: (context, snapshot) => Text( + snapshot.hasData ? snapshot.data ?? '-' : '...', + ), + ), + ); + return Scaffold( + appBar: AppBar( + title: const Text('About Mudblock'), + ), + body: Center( + child: SizedBox( + width: 800, + child: ListView( + children: [ + if (MediaQuery.of(context).size.width <= 600) ...[ + logo, + title, + version, + ], + if (MediaQuery.of(context).size.width > 600) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + logo, + const SizedBox(width: 32), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + title, + version, + ], + ), + ), + ], + ), + ], + const SizedBox(height: 32), + ListTile( + title: const Text('GitHub'), + subtitle: const Text('View the source code on GitHub'), + onTap: () => launchUrl(Uri.parse('https://github.com/chenasraf/mudblock')), + ), + ListTile( + title: const Text('Discord'), + subtitle: const Text('Join our Discord server'), + onTap: () => launchUrl(Uri.parse('https://discord.gg/22XRWSyK')), + ), + ListTile( + title: const Text('Privacy Policy'), + subtitle: const Text('https://mudblock.app/privacy'), + onTap: () => launchUrl(Uri.parse('https://mudblock.app/privacy')), + ), + ], + ), + ), + ), + ); + } +} + diff --git a/lib/pages/button_set_page.dart b/lib/pages/button_set_page.dart index 4901011..987834c 100644 --- a/lib/pages/button_set_page.dart +++ b/lib/pages/button_set_page.dart @@ -27,6 +27,7 @@ class _GameButtonSetPageState extends State { @override Widget build(BuildContext context) { final platformWindowName = PlatformUtils.isDesktop ? 'window' : 'screen'; + final interaction = PlatformUtils.isDesktop ? 'Click' : 'Tap'; return Scaffold( appBar: AppBar( title: const Text('Button Set'), @@ -77,7 +78,7 @@ class _GameButtonSetPageState extends State { .map( (e) => DropdownMenuEntry( value: e, - label: capitalize(e.name), + label: e.name.capitalize(), ), ) .toList(), @@ -105,7 +106,7 @@ class _GameButtonSetPageState extends State { .map( (e) => DropdownMenuEntry( value: e, - label: capitalize(e.toString().split('.')[1]), + label: (e.toString().split('.')[1]).capitalize(), ), ) .toList(), @@ -116,12 +117,26 @@ class _GameButtonSetPageState extends State { }, ), const SizedBox(height: 16), + Text( + 'Buttons', + style: Theme.of(context).textTheme.titleLarge!, + textAlign: TextAlign.center, + ), + Text( + ''' + $interaction a space (with +) to add buttons. + $interaction a button to edit it, or add buttons next to it. + '''.trimMultiline(), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), ButtonSetEditor( key: Key(buttonSet.type.name), data: buttonSet, onUpdate: (data) { setState(() { - buttonSet = buttonSet.copyWith(buttons: data.buttons); + buttonSet = + buttonSet.copyWith(buttons: data.buttons); }); }, ), diff --git a/lib/pages/home_scaffold.dart b/lib/pages/home_scaffold.dart index 937a718..4429ea9 100644 --- a/lib/pages/home_scaffold.dart +++ b/lib/pages/home_scaffold.dart @@ -47,6 +47,7 @@ class HomeScaffold extends StatelessWidget with GameStoreMixin { return Text('v$version'); }, ), + onTap: () => Navigator.pushNamed(context, Paths.about), ), const Divider(), GameStore.consumer( diff --git a/lib/pages/variable_list_page.dart b/lib/pages/variable_list_page.dart index f0c1387..1a5bc6c 100644 --- a/lib/pages/variable_list_page.dart +++ b/lib/pages/variable_list_page.dart @@ -5,7 +5,14 @@ import '../core/features/variable.dart'; import '../core/routes.dart'; class VariableListPage extends StatelessWidget with GameStoreMixin { - const VariableListPage({super.key}); + const VariableListPage({ + super.key, + required this.variables, + required this.onSave, + }); + + final List variables; + final Future Function(Variable variable) onSave; @override Widget build(BuildContext context) { @@ -13,30 +20,23 @@ class VariableListPage extends StatelessWidget with GameStoreMixin { appBar: AppBar( title: const Text('Variables'), ), - // TODO extract this to props - body: GameStore.consumer( - builder: (context, store, child) { - debugPrint('Variable list rebuild'); - final variables = store.currentProfile.variables.values; - return ListView.builder( - itemCount: variables.length, - itemBuilder: (context, item) { - final variable = variables.elementAt(item); - return ListTile( - key: Key(variable.name), - title: Text(variable.name), - subtitle: Text(variable.value), - onTap: () async { - final updated = await Navigator.pushNamed( - context, - Paths.variable, - arguments: variable, - ); - if (updated != null) { - await save(store, updated as Variable); - } - }, + body: ListView.builder( + itemCount: variables.length, + itemBuilder: (context, item) { + final variable = variables.elementAt(item); + return ListTile( + key: Key(variable.name), + title: Text(variable.name), + subtitle: Text(variable.value), + onTap: () async { + final updated = await Navigator.pushNamed( + context, + Paths.variable, + arguments: variable, ); + if (updated != null) { + await onSave(updated as Variable); + } }, ); }, @@ -44,21 +44,13 @@ class VariableListPage extends StatelessWidget with GameStoreMixin { floatingActionButton: FloatingActionButton( child: const Icon(Icons.add), onPressed: () async { - final store = storeOf(context); final variable = await Navigator.pushNamed(context, Paths.variable); if (variable != null) { - save(store, variable as Variable); + onSave(variable as Variable); } }, ), ); } - - // TODO extract this to props - Future save(GameStore store, Variable updated) async { - await store.currentProfile - .saveVariable(store.currentProfile.variables.values.toList(), updated); - await store.currentProfile.loadVariables(); - } } diff --git a/lib/widgets/button_set_editor.dart b/lib/widgets/button_set_editor.dart index ae26587..9815f70 100644 --- a/lib/widgets/button_set_editor.dart +++ b/lib/widgets/button_set_editor.dart @@ -32,19 +32,30 @@ class _ButtonSetEditorState extends State { return _buildContainer( context, (context, index) { + final theme = Theme.of(context); final button = data.buttons[index]; final size = button?.size ?? GameButtonData.defaultSize; final Widget child = button != null ? FakeGameButton(label: button.label) - : const Icon(Icons.add); + : const Icon(Icons.add, color: Colors.white); return Container( - height: size - data.spacing, - width: size - data.spacing, - color: Colors.grey, + height: size, + width: size, + decoration: BoxDecoration( + color: button == null + ? theme.dividerColor.withOpacity(0.2) + : theme.dividerColor.withOpacity(0.5), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: theme.dividerColor, + width: 1, + style: BorderStyle.solid, + ), + ), + // color: Colors.grey, child: GameButtonWrapper( size: size, isEmpty: button == null, - spacing: data.spacing, onAdd: () { showDialog( context: context, @@ -87,7 +98,10 @@ class _ButtonSetEditorState extends State { : data.type == GameButtonSetType.row ? _rowMenuItems(index) : _columnMenuItems(index), - child: child, + child: Padding( + padding: EdgeInsets.all(data.spacing / 2), + child: child, + ), ), ); }, @@ -168,11 +182,11 @@ class _ButtonSetEditorState extends State { value: 'add_row_below', label: 'Add row below', onSelected: () { - final rowIndices = data - .getRowIndices( - data.getRowFromIndex(index), - ) - .reversed; + final rowIndices = data.getRowIndices( + data.getRowFromIndex(index), + ); + + debugPrint('rowIndices: $rowIndices'); setState(() { for (final index in rowIndices) { @@ -264,20 +278,32 @@ class _ButtonSetEditorState extends State { BuildContext context, Widget Function(BuildContext context, int index) builder, ) { - final size = data.size; + final size = Size( + data.size.width + data.spacing * 6, + data.size.height + data.spacing * 10, + ); return Center( - child: SizedBox( + child: Container( width: size.width, height: size.height, - child: GameButtonSet.buildContainer( - context: context, - type: data.type, - size: data.size, - count: data.buttons.length, - crossAxisCount: data.crossAxisCount, - spacing: data.spacing, - alignment: data.alignment, - builder: builder, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(16), + ), + child: Center( + child: Padding( + padding: const EdgeInsets.all(16), + child: GameButtonSet.buildContainer( + context: context, + type: data.type, + size: data.size, + count: data.buttons.length, + crossAxisCount: data.crossAxisCount, + spacing: data.spacing / 3, + alignment: data.alignment, + builder: builder, + ), + ), ), ), ); @@ -293,7 +319,6 @@ class GameButtonWrapper extends StatelessWidget { required this.onDelete, required this.onClear, required this.size, - required this.spacing, required this.isEmpty, this.emptySpaceControls = const [], }); @@ -304,7 +329,6 @@ class GameButtonWrapper extends StatelessWidget { final void Function() onClear; final void Function() onDelete; final double size; - final double spacing; final List emptySpaceControls; final bool isEmpty; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index b7a6d08..0cacc75 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,12 +7,16 @@ #include "generated_plugin_registrant.h" #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) screen_retriever_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); g_autoptr(FlPluginRegistrar) window_manager_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); window_manager_plugin_register_with_registrar(window_manager_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 913ac71..62f151f 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST screen_retriever + url_launcher_linux window_manager ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index a57d098..10b4601 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import package_info_plus import path_provider_foundation import screen_retriever import shared_preferences_foundation +import url_launcher_macos import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { @@ -16,5 +17,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 6b93212..535e109 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -10,6 +10,8 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - url_launcher_macos (0.0.1): + - FlutterMacOS - window_manager (0.2.0): - FlutterMacOS @@ -19,6 +21,7 @@ DEPENDENCIES: - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) EXTERNAL SOURCES: @@ -32,6 +35,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos @@ -41,6 +46,7 @@ SPEC CHECKSUMS: path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 diff --git a/pubspec.lock b/pubspec.lock index 58be44b..c1e8e98 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -524,6 +524,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + url: "https://pub.dev" + source: hosted + version: "6.1.14" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + url: "https://pub.dev" + source: hosted + version: "6.1.0" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + url: "https://pub.dev" + source: hosted + version: "3.0.6" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + url: "https://pub.dev" + source: hosted + version: "3.0.7" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" + url: "https://pub.dev" + source: hosted + version: "2.0.20" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + url: "https://pub.dev" + source: hosted + version: "3.0.8" uuid: dependency: "direct main" description: @@ -590,4 +654,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.1.2 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 72a4a1b..bb25fa7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: lua_dardo: ^0.0.5 path_provider: ^2.1.1 package_info_plus: ^4.1.0 + url_launcher: ^6.1.14 # permission_handler: ^11.0.0 dev_dependencies: @@ -79,6 +80,7 @@ flutter: # - images/a_dot_ham.jpeg assets: - assets/images/logo/logo.png + - assets/images/logo/logo@4x.png # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index d6b86fa..fe7ec1c 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,11 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { ScreenRetrieverPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowManagerPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("WindowManagerPlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index bfa52f4..fb2dea6 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST screen_retriever + url_launcher_windows window_manager )