feat: ui updates

This commit is contained in:
2023-10-15 01:45:02 +03:00
parent aaf7610e22
commit d570f6a3cc
22 changed files with 406 additions and 111 deletions

View File

@@ -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,
};

View File

@@ -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<GameButton> 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<GameButton> 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<GameButton> 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<GameButton> 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<GameButton> with GameStoreStateMixin {
void _onPointerUp(PointerUpEvent event) {
_callCurrentDirection();
setState(() {
isClicking = false;
_direction = GameButtonInteraction.press;
});
}
@@ -374,6 +442,7 @@ class _GameButtonState extends State<GameButton> with GameStoreStateMixin {
void _onPointerDown(PointerDownEvent event) {
_dragStart = event.position;
setState(() {
isClicking = true;
_direction = GameButtonInteraction.press;
});
}
@@ -516,3 +585,4 @@ enum GameButtonInteraction {
dragLeft,
dragRight,
}

View File

@@ -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),
);
},
),

View File

@@ -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<Alias> {
i.enabled = state;
return store.currentProfile.saveAlias(i);
}));
return store.currentProfile.getAliases();
}
@override
Future<void> 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<Trigger> {
i.enabled = state;
return store.currentProfile.saveTrigger(i);
}));
return store.currentProfile.getTriggers();
}
@override
Future<void> 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<GameButtonSetData> {
i.enabled = state;
return store.currentProfile.saveButtonSet(i);
}));
return store.currentProfile.getTriggers();
}
@override
Future<void> saveSingle(GameButtonSetData item, bool state) async {
item.enabled = state;
await store.currentProfile.saveButtonSet(item);
return store.currentProfile.getTriggers();
}
}

View File

@@ -29,7 +29,7 @@ class PluginBase extends ChangeNotifier {
List<Future<void>> additionalLoaders() => [];
Future<List<Trigger>> loadTriggers() async {
Future<List<Trigger>> _loadTriggers() async {
debugPrint('$this loadTriggers');
final triggers = await storage.readDirectory('triggers');
final triggerFiles = <Map<String, dynamic>>[];
@@ -42,7 +42,7 @@ class PluginBase extends ChangeNotifier {
return triggerFiles.map((e) => Trigger.fromJson(e)).toList();
}
Future<List<Alias>> loadAliases() async {
Future<List<Alias>> _loadAliases() async {
debugPrint('$this loadAliases');
final aliases = await storage.readDirectory('aliases');
final aliasFiles = <Map<String, dynamic>>[];
@@ -145,41 +145,29 @@ class PluginBase extends ChangeNotifier {
return storage.deleteFile('button_sets/${buttonSet.id}');
}
Future<void> saveVariable(List<Variable> current, Variable update) async {
Future<void> 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<void> deleteVariable(List<Variable> current, Variable update) async {
Future<void> 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<void> 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<void> getAliases() async {
final list = await loadAliases();
final list = await _loadAliases();
aliases.clear();
aliases.addAll(list);
notifyListeners();

View File

@@ -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 = <String, Widget Function(BuildContext)>{
@@ -89,7 +91,12 @@ final routes = <String, Widget Function(BuildContext)>{
// 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 = <String, Widget Function(BuildContext)>{
);
},
// about
Paths.about: (context) => const AboutPage(),
// home
Paths.home: (context) => HomeScaffold(
builder: (context, _) {

View File

@@ -12,8 +12,17 @@ List<String> 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();
}
}

View File

@@ -60,7 +60,7 @@ class _ButtonEditorDialogState extends State<ButtonEditorDialog> {
initialValue:
data.getAction(interaction)?.content ?? '',
decoration: InputDecoration(
label: Text(capitalize(interaction.name)),
label: Text(interaction.name.capitalize()),
),
onChanged: (value) {
setState(() {

View File

@@ -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(

90
lib/pages/about_page.dart Normal file
View File

@@ -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')),
),
],
),
),
),
);
}
}

View File

@@ -27,6 +27,7 @@ class _GameButtonSetPageState extends State<GameButtonSetPage> {
@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<GameButtonSetPage> {
.map(
(e) => DropdownMenuEntry(
value: e,
label: capitalize(e.name),
label: e.name.capitalize(),
),
)
.toList(),
@@ -105,7 +106,7 @@ class _GameButtonSetPageState extends State<GameButtonSetPage> {
.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<GameButtonSetPage> {
},
),
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);
});
},
),

View File

@@ -47,6 +47,7 @@ class HomeScaffold extends StatelessWidget with GameStoreMixin {
return Text('v$version');
},
),
onTap: () => Navigator.pushNamed(context, Paths.about),
),
const Divider(),
GameStore.consumer(

View File

@@ -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<Variable> variables;
final Future<void> 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<void> save(GameStore store, Variable updated) async {
await store.currentProfile
.saveVariable(store.currentProfile.variables.values.toList(), updated);
await store.currentProfile.loadVariables();
}
}

View File

@@ -32,19 +32,30 @@ class _ButtonSetEditorState extends State<ButtonSetEditor> {
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<ButtonSetEditor> {
: 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<ButtonSetEditor> {
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<ButtonSetEditor> {
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<FakeGameButtonMenuItem> emptySpaceControls;
final bool isEmpty;

View File

@@ -7,12 +7,16 @@
#include "generated_plugin_registrant.h"
#include <screen_retriever/screen_retriever_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
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);

View File

@@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
screen_retriever
url_launcher_linux
window_manager
)

View File

@@ -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"))
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -7,11 +7,14 @@
#include "generated_plugin_registrant.h"
#include <screen_retriever/screen_retriever_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WindowManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
}

View File

@@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
screen_retriever
url_launcher_windows
window_manager
)