mirror of
https://github.com/chenasraf/mudblock.git
synced 2026-05-17 17:48:05 +00:00
refactor: extract feature loaders to plugins
This commit is contained in:
@@ -14,10 +14,15 @@ enum MUDActionTarget {
|
||||
|
||||
class MUDAction {
|
||||
String content;
|
||||
Automation? parent;
|
||||
MUDActionTarget target;
|
||||
MUDAction(this.content, {this.target = MUDActionTarget.execute});
|
||||
MUDAction(
|
||||
this.content, {
|
||||
this.target = MUDActionTarget.execute,
|
||||
this.parent,
|
||||
});
|
||||
|
||||
void invoke(GameStore store, Automation parent, List<String> matches) {
|
||||
void invoke(GameStore store, List<String> matches) {
|
||||
debugPrint('MUDAction.invoke: ${this.content}, $matches');
|
||||
var content = this.content;
|
||||
for (var i = 0; i < matches.length; i++) {
|
||||
@@ -30,14 +35,14 @@ class MUDAction {
|
||||
case MUDActionTarget.world:
|
||||
debugPrint('ActionSendTo.world: $content');
|
||||
store.send(content);
|
||||
if (!parent.isRemovedFromBuffer) {
|
||||
if (parent != null && !parent!.isRemovedFromBuffer) {
|
||||
store.echoOwn(content);
|
||||
}
|
||||
break;
|
||||
case MUDActionTarget.execute:
|
||||
debugPrint('ActionSendTo.execute: $content');
|
||||
store.execute(content);
|
||||
if (!parent.isRemovedFromBuffer) {
|
||||
if (parent != null && !parent!.isRemovedFromBuffer) {
|
||||
store.echoOwn(content);
|
||||
}
|
||||
break;
|
||||
@@ -84,7 +89,7 @@ class MUDAction {
|
||||
|
||||
// variables from the store
|
||||
// TODO allow disabling this
|
||||
for (final vari in store.variables.values) {
|
||||
for (final vari in store.currentProfile.variables.values) {
|
||||
content = content.replaceAll('%${vari.name}', vari.value);
|
||||
}
|
||||
return content;
|
||||
@@ -95,11 +100,12 @@ class NativeMUDAction extends MUDAction {
|
||||
NativeMUDAction(this.customInvoke)
|
||||
: super('-- native code --', target: MUDActionTarget.script);
|
||||
|
||||
final void Function(GameStore store, Automation parent, List<String> matches)
|
||||
final void Function(GameStore store, List<String> matches)
|
||||
customInvoke;
|
||||
|
||||
@override
|
||||
void invoke(GameStore store, Automation parent, List<String> matches) {
|
||||
customInvoke(store, parent, matches);
|
||||
void invoke(GameStore store, List<String> matches) {
|
||||
customInvoke(store, matches);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ final builtInAliases = <Alias>[
|
||||
id: _key('help'),
|
||||
pattern: 'mudhelp',
|
||||
action: NativeMUDAction(
|
||||
(store, parent, matches) {
|
||||
(store, matches) {
|
||||
store.echo(BuiltinCommand.help());
|
||||
},
|
||||
),
|
||||
|
||||
@@ -102,7 +102,7 @@ class Automation {
|
||||
|
||||
void invokeEffect(GameStore store, String line) {
|
||||
invokeCount++;
|
||||
action.invoke(store, this, allMatches(line));
|
||||
action.invoke(store, allMatches(line));
|
||||
}
|
||||
|
||||
List<String> allMatches(String str) {
|
||||
|
||||
@@ -420,7 +420,7 @@ class _GameButtonState extends State<GameButton> with GameStoreStateMixin {
|
||||
|
||||
void _callAction(MUDAction? action) {
|
||||
final act = action ?? data.getActionOrDefault(GameButtonInteraction.press);
|
||||
act.invoke(store, parentAutomation, []);
|
||||
act.invoke(store, []);
|
||||
}
|
||||
|
||||
void _callCurrentDirection() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'store.dart';
|
||||
import '../store.dart';
|
||||
|
||||
class KeyboardIntent extends Intent {
|
||||
const KeyboardIntent(this.key);
|
||||
@@ -76,7 +76,7 @@ class LuaBindings {
|
||||
final name = ls.checkString(1)!;
|
||||
ls.pop(1);
|
||||
debugPrint("lua.getVariable $name");
|
||||
final vari = store.variables[name];
|
||||
final vari = store.currentProfile.variables[name];
|
||||
if (vari != null) {
|
||||
ls.pushString(vari.value);
|
||||
} else {
|
||||
@@ -90,12 +90,15 @@ class LuaBindings {
|
||||
final value = ls.checkString(2)!;
|
||||
ls.pop(2);
|
||||
debugPrint("lua.setVariable $name, $value");
|
||||
if (store.variables[name] == null) {
|
||||
store.variables[name] = Variable(name, value);
|
||||
final profile = store.currentProfile;
|
||||
if (profile.variables[name] == null) {
|
||||
profile.variables[name] = Variable(name, value);
|
||||
}
|
||||
store.variables[name]!.value = value;
|
||||
store.currentProfile
|
||||
.saveVariable(store.variables.values.toList(), store.variables[name]!);
|
||||
profile.variables[name]!.value = value;
|
||||
profile.saveVariable(
|
||||
profile.variables.values.toList(),
|
||||
profile.variables[name]!,
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -110,11 +113,11 @@ class LuaAliasBindings extends LuaAutomationBindings<Alias> {
|
||||
|
||||
@override
|
||||
List<Alias> getGroup(String group) =>
|
||||
store.aliases.where((alias) => alias.group == group).toList();
|
||||
store.currentProfile.aliases.where((alias) => alias.group == group).toList();
|
||||
|
||||
@override
|
||||
Alias getSingle(String label) =>
|
||||
store.aliases.firstWhere((alias) => alias.label == label);
|
||||
store.currentProfile.aliases.firstWhere((alias) => alias.label == label);
|
||||
|
||||
@override
|
||||
Future<void> saveGroup(List<Alias> items, bool state) async {
|
||||
@@ -122,14 +125,14 @@ class LuaAliasBindings extends LuaAutomationBindings<Alias> {
|
||||
i.enabled = state;
|
||||
return store.currentProfile.saveAlias(i);
|
||||
}));
|
||||
return store.loadAliases();
|
||||
return store.currentProfile.getAliases();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveSingle(Alias item, bool state) async {
|
||||
item.enabled = state;
|
||||
await store.currentProfile.saveAlias(item);
|
||||
return store.loadAliases();
|
||||
return store.currentProfile.getAliases();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,11 +146,11 @@ class LuaTriggerBindings extends LuaAutomationBindings<Trigger> {
|
||||
|
||||
@override
|
||||
List<Trigger> getGroup(String group) =>
|
||||
store.triggers.where((alias) => alias.group == group).toList();
|
||||
store.currentProfile.triggers.where((alias) => alias.group == group).toList();
|
||||
|
||||
@override
|
||||
Trigger getSingle(String label) =>
|
||||
store.triggers.firstWhere((alias) => alias.label == label);
|
||||
store.currentProfile.triggers.firstWhere((alias) => alias.label == label);
|
||||
|
||||
@override
|
||||
Future<void> saveGroup(List<Trigger> items, bool state) async {
|
||||
@@ -155,14 +158,14 @@ class LuaTriggerBindings extends LuaAutomationBindings<Trigger> {
|
||||
i.enabled = state;
|
||||
return store.currentProfile.saveTrigger(i);
|
||||
}));
|
||||
return store.loadTriggers();
|
||||
return store.currentProfile.getTriggers();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveSingle(Trigger item, bool state) async {
|
||||
item.enabled = state;
|
||||
await store.currentProfile.saveTrigger(item);
|
||||
return store.loadTriggers();
|
||||
return store.currentProfile.getTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,11 +179,11 @@ class LuaButtonSetBindings extends LuaAutomationBindings<GameButtonSetData> {
|
||||
|
||||
@override
|
||||
List<GameButtonSetData> getGroup(String group) =>
|
||||
store.buttonSets.where((alias) => alias.group == group).toList();
|
||||
store.currentProfile.buttonSets.where((alias) => alias.group == group).toList();
|
||||
|
||||
@override
|
||||
GameButtonSetData getSingle(String label) =>
|
||||
store.buttonSets.firstWhere((alias) => alias.label == label);
|
||||
store.currentProfile.buttonSets.firstWhere((alias) => alias.label == label);
|
||||
|
||||
@override
|
||||
Future<void> saveGroup(List<GameButtonSetData> items, bool state) async {
|
||||
@@ -188,14 +191,14 @@ class LuaButtonSetBindings extends LuaAutomationBindings<GameButtonSetData> {
|
||||
i.enabled = state;
|
||||
return store.currentProfile.saveButtonSet(i);
|
||||
}));
|
||||
return store.loadTriggers();
|
||||
return store.currentProfile.getTriggers();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveSingle(GameButtonSetData item, bool state) async {
|
||||
item.enabled = state;
|
||||
await store.currentProfile.saveButtonSet(item);
|
||||
return store.loadTriggers();
|
||||
return store.currentProfile.getTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
213
lib/core/features/plugin.dart
Normal file
213
lib/core/features/plugin.dart
Normal file
@@ -0,0 +1,213 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../storage.dart';
|
||||
import 'alias.dart';
|
||||
import 'game_button_set.dart';
|
||||
import 'settings.dart';
|
||||
import 'trigger.dart';
|
||||
import 'variable.dart';
|
||||
|
||||
class PluginBase extends ChangeNotifier {
|
||||
final String id;
|
||||
|
||||
final List<Trigger> triggers = [];
|
||||
final List<Alias> aliases = [];
|
||||
final Map<String, Variable> variables = {};
|
||||
final List<GameButtonSetData> buttonSets = [];
|
||||
|
||||
PluginBase(this.id);
|
||||
|
||||
Future<void> load() async {
|
||||
await Future.wait([
|
||||
getAliases(),
|
||||
getTriggers(),
|
||||
getVariables(),
|
||||
getButtonSets(),
|
||||
]);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<List<Trigger>> loadTriggers() async {
|
||||
debugPrint('MUDProfile.loadTriggers: $id');
|
||||
final triggers = await ProfileStorage.listProfileFiles(id, 'triggers');
|
||||
final triggerFiles = <Map<String, dynamic>>[];
|
||||
for (final trigger in triggers) {
|
||||
debugPrint('MUDProfile.loadTriggers: $id/triggers/$trigger');
|
||||
final triggerFile =
|
||||
await ProfileStorage.readProfileFile(id, 'triggers/$trigger');
|
||||
if (triggerFile != null) {
|
||||
triggerFiles.add(triggerFile);
|
||||
}
|
||||
}
|
||||
return triggerFiles.map((e) => Trigger.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Alias>> loadAliases() async {
|
||||
debugPrint('MUDProfile.loadAliases: $id');
|
||||
final aliases = await ProfileStorage.listProfileFiles(id, 'aliases');
|
||||
final aliasFiles = <Map<String, dynamic>>[];
|
||||
for (final alias in aliases) {
|
||||
debugPrint('MUDProfile.loadAliases: $id/aliases/$alias');
|
||||
final aliasFile =
|
||||
await ProfileStorage.readProfileFile(id, 'aliases/$alias');
|
||||
if (aliasFile != null) {
|
||||
aliasFiles.add(aliasFile);
|
||||
}
|
||||
}
|
||||
return aliasFiles.map((e) => Alias.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Variable>> loadVariables() async {
|
||||
debugPrint('MUDProfile.loadVariables: $id');
|
||||
final vars = await ProfileStorage.readProfileFile(id, 'vars');
|
||||
if (vars == null) {
|
||||
return [];
|
||||
}
|
||||
return (vars['vars'] as List<dynamic>)
|
||||
.map((e) => Variable.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<GameButtonSetData>> loadButtonSets() async {
|
||||
debugPrint('MUDProfile.loadButtonSets: $id');
|
||||
final buttonSets = await ProfileStorage.listProfileFiles(id, 'button_sets');
|
||||
final buttonSetFiles = <Map<String, dynamic>>[];
|
||||
for (final buttonSet in buttonSets) {
|
||||
debugPrint('MUDProfile.loadButtonSets: $id/buttonSets/$buttonSet');
|
||||
final buttonSetFile =
|
||||
await ProfileStorage.readProfileFile(id, 'button_sets/$buttonSet');
|
||||
if (buttonSetFile != null) {
|
||||
buttonSetFiles.add(buttonSetFile);
|
||||
}
|
||||
}
|
||||
return buttonSetFiles.map((e) => GameButtonSetData.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
|
||||
Future<Settings> loadSettings() async {
|
||||
debugPrint('MUDProfile.loadSettings: $id');
|
||||
final settings = await ProfileStorage.readProfileFile(id, 'settings');
|
||||
if (settings == null) {
|
||||
return Settings.empty();
|
||||
}
|
||||
return Settings.fromJson(settings);
|
||||
}
|
||||
|
||||
Future<void> saveAlias(Alias alias) async {
|
||||
debugPrint('MUDProfile.saveAlias: $id/aliases/${alias.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'aliases/${alias.id}', alias.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteAlias(Alias alias) async {
|
||||
debugPrint('MUDProfile.deleteAlias: $id/aliases/${alias.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'aliases/${alias.id}');
|
||||
}
|
||||
|
||||
Future<void> saveTrigger(Trigger trigger) async {
|
||||
debugPrint('MUDProfile.saveTrigger: $id/triggers/${trigger.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'triggers/${trigger.id}', trigger.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteTrigger(Trigger trigger) async {
|
||||
debugPrint('MUDProfile.deleteTrigger: $id/triggers/${trigger.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'triggers/${trigger.id}');
|
||||
}
|
||||
|
||||
Future<void> saveButtonSet(GameButtonSetData buttonSet) async {
|
||||
debugPrint('MUDProfile.saveButtonSet: $id/button_sets/${buttonSet.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'button_sets/${buttonSet.id}', buttonSet.toJson());
|
||||
}
|
||||
|
||||
Future<void> saveSettings(Settings settings) async {
|
||||
debugPrint('MUDProfile.saveSettings: $id');
|
||||
return ProfileStorage.writeProfileFile(id, 'settings', settings.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteButtonSet(GameButtonSetData buttonSet) async {
|
||||
debugPrint('MUDProfile.deleteButtonSet: $id/button_sets/${buttonSet.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'button_sets/${buttonSet.id}');
|
||||
}
|
||||
|
||||
Future<void> saveVariable(List<Variable> current, Variable update) async {
|
||||
debugPrint('MUDProfile.saveVariable: $id/vars');
|
||||
final existing = current.indexWhere(
|
||||
(v) => v.name == update.name,
|
||||
);
|
||||
if (existing >= 0) {
|
||||
current[existing] = update;
|
||||
} else {
|
||||
current.add(update);
|
||||
}
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id,
|
||||
'vars',
|
||||
{'vars': current.map((v) => v.toJson()).toList()},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteVariable(List<Variable> current, Variable update) async {
|
||||
debugPrint('MUDProfile.deleteVariable: $id/vars');
|
||||
final existing = current.indexWhere(
|
||||
(v) => v.name == update.name,
|
||||
);
|
||||
if (existing >= 0) {
|
||||
current.removeAt(existing);
|
||||
}
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id,
|
||||
'vars',
|
||||
{'vars': current.map((v) => v.toJson()).toList()},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getTriggers() async {
|
||||
debugPrint('loadTriggers');
|
||||
final list = await loadTriggers();
|
||||
triggers.clear();
|
||||
triggers.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('Triggers: ${triggers.length}');
|
||||
}
|
||||
|
||||
Future<void> getAliases() async {
|
||||
final list = await loadAliases();
|
||||
aliases.clear();
|
||||
aliases.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('Aliases: ${aliases.length}');
|
||||
}
|
||||
|
||||
Future<void> getVariables() async {
|
||||
final list = await loadVariables();
|
||||
variables.clear();
|
||||
variables.addAll(Map.fromEntries(list.map((e) => MapEntry(e.name, e))));
|
||||
notifyListeners();
|
||||
debugPrint('Variables: ${variables.length}');
|
||||
}
|
||||
|
||||
Future<void> getButtonSets() async {
|
||||
final list = await loadButtonSets();
|
||||
buttonSets.clear();
|
||||
buttonSets.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('ButtonSets: ${buttonSets.length}');
|
||||
}
|
||||
}
|
||||
|
||||
class Plugin extends PluginBase {
|
||||
final String profileId;
|
||||
|
||||
@override
|
||||
String get id => _id;
|
||||
|
||||
final String _id;
|
||||
|
||||
Plugin(this.profileId, String id)
|
||||
: _id = id,
|
||||
super('$profileId/$id');
|
||||
}
|
||||
|
||||
@@ -2,18 +2,12 @@ import 'package:encrypt/encrypt.dart' as enc;
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../consts.dart';
|
||||
import '../keyboard_shortcuts.dart';
|
||||
import '../secrets.dart';
|
||||
import '../storage.dart';
|
||||
import '../string_utils.dart';
|
||||
import 'alias.dart';
|
||||
import 'game_button_set.dart';
|
||||
import 'settings.dart';
|
||||
import 'trigger.dart';
|
||||
import 'variable.dart';
|
||||
import 'plugin.dart';
|
||||
|
||||
class MUDProfile {
|
||||
String id;
|
||||
class MUDProfile extends PluginBase {
|
||||
String name;
|
||||
String host;
|
||||
int port;
|
||||
@@ -23,7 +17,7 @@ class MUDProfile {
|
||||
AuthMethod authMethod;
|
||||
|
||||
MUDProfile({
|
||||
required this.id,
|
||||
required String id,
|
||||
required this.name,
|
||||
required this.host,
|
||||
required this.port,
|
||||
@@ -31,7 +25,7 @@ class MUDProfile {
|
||||
this.username = '',
|
||||
this.password = '',
|
||||
this.authMethod = AuthMethod.none,
|
||||
});
|
||||
}) : super(id);
|
||||
|
||||
factory MUDProfile.empty() => MUDProfile(
|
||||
id: uuid(),
|
||||
@@ -95,156 +89,6 @@ class MUDProfile {
|
||||
profile.id, profile.id, (profile.toJson()));
|
||||
}
|
||||
|
||||
Future<List<Trigger>> loadTriggers() async {
|
||||
debugPrint('MUDProfile.loadTriggers: $id');
|
||||
final triggers = await ProfileStorage.listProfileFiles(id, 'triggers');
|
||||
final triggerFiles = <Map<String, dynamic>>[];
|
||||
for (final trigger in triggers) {
|
||||
debugPrint('MUDProfile.loadTriggers: $id/triggers/$trigger');
|
||||
final triggerFile =
|
||||
await ProfileStorage.readProfileFile(id, 'triggers/$trigger');
|
||||
if (triggerFile != null) {
|
||||
triggerFiles.add(triggerFile);
|
||||
}
|
||||
}
|
||||
return triggerFiles.map((e) => Trigger.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Alias>> loadAliases() async {
|
||||
debugPrint('MUDProfile.loadAliases: $id');
|
||||
final aliases = await ProfileStorage.listProfileFiles(id, 'aliases');
|
||||
final aliasFiles = <Map<String, dynamic>>[];
|
||||
for (final alias in aliases) {
|
||||
debugPrint('MUDProfile.loadAliases: $id/aliases/$alias');
|
||||
final aliasFile =
|
||||
await ProfileStorage.readProfileFile(id, 'aliases/$alias');
|
||||
if (aliasFile != null) {
|
||||
aliasFiles.add(aliasFile);
|
||||
}
|
||||
}
|
||||
return aliasFiles.map((e) => Alias.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<List<Variable>> loadVariables() async {
|
||||
debugPrint('MUDProfile.loadVariables: $id');
|
||||
final vars = await ProfileStorage.readProfileFile(id, 'vars');
|
||||
if (vars == null) {
|
||||
return [];
|
||||
}
|
||||
return (vars['vars'] as List<dynamic>)
|
||||
.map((e) => Variable.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<GameButtonSetData>> loadButtonSets() async {
|
||||
debugPrint('MUDProfile.loadButtonSets: $id');
|
||||
final buttonSets = await ProfileStorage.listProfileFiles(id, 'button_sets');
|
||||
final buttonSetFiles = <Map<String, dynamic>>[];
|
||||
for (final buttonSet in buttonSets) {
|
||||
debugPrint('MUDProfile.loadButtonSets: $id/buttonSets/$buttonSet');
|
||||
final buttonSetFile =
|
||||
await ProfileStorage.readProfileFile(id, 'button_sets/$buttonSet');
|
||||
if (buttonSetFile != null) {
|
||||
buttonSetFiles.add(buttonSetFile);
|
||||
}
|
||||
}
|
||||
return buttonSetFiles.map((e) => GameButtonSetData.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<KeyboardShortcuts> loadKeyboardShortcuts() async {
|
||||
debugPrint('MUDProfile.loadKeyboardShortcuts: $id');
|
||||
final shortcuts =
|
||||
await ProfileStorage.readProfileFile(id, 'keyboard_shortcuts');
|
||||
if (shortcuts == null) {
|
||||
return KeyboardShortcuts.empty();
|
||||
}
|
||||
return KeyboardShortcuts.fromJson(shortcuts);
|
||||
}
|
||||
|
||||
Future<Settings> loadSettings() async {
|
||||
debugPrint('MUDProfile.loadSettings: $id');
|
||||
final settings = await ProfileStorage.readProfileFile(id, 'settings');
|
||||
if (settings == null) {
|
||||
return Settings.empty();
|
||||
}
|
||||
return Settings.fromJson(settings);
|
||||
}
|
||||
|
||||
Future<void> saveAlias(Alias alias) async {
|
||||
debugPrint('MUDProfile.saveAlias: $id/aliases/${alias.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'aliases/${alias.id}', alias.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteAlias(Alias alias) async {
|
||||
debugPrint('MUDProfile.deleteAlias: $id/aliases/${alias.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'aliases/${alias.id}');
|
||||
}
|
||||
|
||||
Future<void> saveTrigger(Trigger trigger) async {
|
||||
debugPrint('MUDProfile.saveTrigger: $id/triggers/${trigger.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'triggers/${trigger.id}', trigger.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteTrigger(Trigger trigger) async {
|
||||
debugPrint('MUDProfile.deleteTrigger: $id/triggers/${trigger.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'triggers/${trigger.id}');
|
||||
}
|
||||
|
||||
Future<void> saveButtonSet(GameButtonSetData buttonSet) async {
|
||||
debugPrint('MUDProfile.saveButtonSet: $id/button_sets/${buttonSet.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'button_sets/${buttonSet.id}', buttonSet.toJson());
|
||||
}
|
||||
|
||||
Future<void> saveKeyboardShortcuts(KeyboardShortcuts shortcuts) async {
|
||||
debugPrint('MUDProfile.saveKeyboardShortcuts: $id');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id, 'keyboard_shortcuts', shortcuts.toJson());
|
||||
}
|
||||
|
||||
Future<void> saveSettings(Settings settings) async {
|
||||
debugPrint('MUDProfile.saveSettings: $id');
|
||||
return ProfileStorage.writeProfileFile(id, 'settings', settings.toJson());
|
||||
}
|
||||
|
||||
Future<void> deleteButtonSet(GameButtonSetData buttonSet) async {
|
||||
debugPrint('MUDProfile.deleteButtonSet: $id/button_sets/${buttonSet.id}');
|
||||
return ProfileStorage.deleteProfileFile(id, 'button_sets/${buttonSet.id}');
|
||||
}
|
||||
|
||||
Future<void> saveVariable(List<Variable> current, Variable update) async {
|
||||
debugPrint('MUDProfile.saveVariable: $id/vars');
|
||||
final existing = current.indexWhere(
|
||||
(v) => v.name == update.name,
|
||||
);
|
||||
if (existing >= 0) {
|
||||
current[existing] = update;
|
||||
} else {
|
||||
current.add(update);
|
||||
}
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id,
|
||||
'vars',
|
||||
{'vars': current.map((v) => v.toJson()).toList()},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteVariable(List<Variable> current, Variable update) async {
|
||||
debugPrint('MUDProfile.deleteVariable: $id/vars');
|
||||
final existing = current.indexWhere(
|
||||
(v) => v.name == update.name,
|
||||
);
|
||||
if (existing >= 0) {
|
||||
current.removeAt(existing);
|
||||
}
|
||||
return ProfileStorage.writeProfileFile(
|
||||
id,
|
||||
'vars',
|
||||
{'vars': current.map((v) => v.toJson()).toList()},
|
||||
);
|
||||
}
|
||||
|
||||
static final encKey = enc.Key.fromUtf8(pwdKey);
|
||||
static final encrypter = enc.Encrypter(enc.AES(encKey, padding: null));
|
||||
|
||||
@@ -94,7 +94,7 @@ final routes = <String, Widget Function(BuildContext)>{
|
||||
shortcuts: store.keyboardShortcuts,
|
||||
onSave: (shortcuts) {
|
||||
store.keyboardShortcuts = shortcuts;
|
||||
store.currentProfile.saveKeyboardShortcuts(shortcuts);
|
||||
store.saveKeyboardShortcuts(shortcuts);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -13,12 +13,9 @@ import 'color_utils.dart';
|
||||
import 'consts.dart';
|
||||
import 'features/action.dart';
|
||||
import 'features/alias.dart';
|
||||
import 'features/game_button_set.dart';
|
||||
import 'features/keyboard_shortcuts.dart';
|
||||
import 'features/profile.dart';
|
||||
import 'features/settings.dart';
|
||||
import 'features/trigger.dart';
|
||||
import 'features/variable.dart';
|
||||
import 'keyboard_shortcuts.dart';
|
||||
|
||||
const maxLines = 2000;
|
||||
|
||||
@@ -45,13 +42,8 @@ class GameStore extends ChangeNotifier {
|
||||
RegExp("(?<!$commandSeparator)$commandSeparator(?!$commandSeparator)");
|
||||
|
||||
// features
|
||||
// TODO - move to MUDProfile and make that reactive
|
||||
Settings settings = Settings.empty();
|
||||
final List<Trigger> triggers = [];
|
||||
final List<Alias> aliases = [];
|
||||
final Map<String, Variable> variables = {};
|
||||
final List<GameButtonSetData> buttonSets = [];
|
||||
KeyboardShortcuts keyboardShortcuts = KeyboardShortcuts.empty();
|
||||
Settings settings = Settings.empty();
|
||||
|
||||
MUDProfile get currentProfile => _currentProfile!;
|
||||
|
||||
@@ -82,56 +74,30 @@ class GameStore extends ChangeNotifier {
|
||||
onData: onData,
|
||||
onError: onError,
|
||||
);
|
||||
await Future.wait([
|
||||
loadTriggers(),
|
||||
loadAliases(),
|
||||
loadVariables(),
|
||||
loadButtonSets(),
|
||||
await Future.wait(<Future<dynamic>>[
|
||||
currentProfile.load(),
|
||||
loadKeyboardShortcuts(),
|
||||
|
||||
loadSettings(),
|
||||
]);
|
||||
_client.connect();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> loadTriggers() async {
|
||||
debugPrint('loadTriggers');
|
||||
final list = await currentProfile.loadTriggers();
|
||||
triggers.clear();
|
||||
triggers.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('Triggers: ${triggers.length}');
|
||||
Future<KeyboardShortcuts> getKeyboardShortcuts() async {
|
||||
debugPrint('MUDProfile.loadKeyboardShortcuts: ${currentProfile.id}');
|
||||
// TODO use global storage (not profile specific)
|
||||
final shortcuts = await ProfileStorage.readProfileFile(
|
||||
currentProfile.id, 'keyboard_shortcuts');
|
||||
if (shortcuts == null) {
|
||||
return KeyboardShortcuts.empty();
|
||||
}
|
||||
return KeyboardShortcuts.fromJson(shortcuts);
|
||||
}
|
||||
|
||||
Future<void> loadAliases() async {
|
||||
final list = await currentProfile.loadAliases();
|
||||
aliases.clear();
|
||||
aliases.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('Aliases: ${aliases.length}');
|
||||
}
|
||||
|
||||
Future<void> loadVariables() async {
|
||||
final list = await currentProfile.loadVariables();
|
||||
variables.clear();
|
||||
variables.addAll(Map.fromEntries(list.map((e) => MapEntry(e.name, e))));
|
||||
notifyListeners();
|
||||
debugPrint('Variables: ${variables.length}');
|
||||
}
|
||||
|
||||
Future<void> loadButtonSets() async {
|
||||
final list = await currentProfile.loadButtonSets();
|
||||
buttonSets.clear();
|
||||
buttonSets.addAll(list);
|
||||
notifyListeners();
|
||||
debugPrint('ButtonSets: ${buttonSets.length}');
|
||||
}
|
||||
|
||||
Future<void> loadKeyboardShortcuts() async {
|
||||
final shortcuts = await currentProfile.loadKeyboardShortcuts();
|
||||
keyboardShortcuts = shortcuts;
|
||||
notifyListeners();
|
||||
debugPrint('KeyboardShortcuts loaded');
|
||||
Future<void> saveKeyboardShortcuts(KeyboardShortcuts shortcuts) async {
|
||||
debugPrint('MUDProfile.saveKeyboardShortcuts: ${currentProfile.id}');
|
||||
return ProfileStorage.writeProfileFile(
|
||||
currentProfile.id, 'keyboard_shortcuts', shortcuts.toJson());
|
||||
}
|
||||
|
||||
Future<void> loadSettings() async {
|
||||
@@ -141,10 +107,17 @@ class GameStore extends ChangeNotifier {
|
||||
debugPrint('Settings loaded');
|
||||
}
|
||||
|
||||
Future<void> loadKeyboardShortcuts() async {
|
||||
final shortcuts = await getKeyboardShortcuts();
|
||||
keyboardShortcuts = shortcuts;
|
||||
notifyListeners();
|
||||
debugPrint('KeyboardShortcuts loaded');
|
||||
}
|
||||
|
||||
bool processTriggers(String line) {
|
||||
bool showLine = true;
|
||||
final str = ColorUtils.stripColor(line);
|
||||
for (final trigger in triggers) {
|
||||
for (final trigger in currentProfile.triggers) {
|
||||
if (!trigger.isAvailable) {
|
||||
continue;
|
||||
}
|
||||
@@ -164,7 +137,7 @@ class GameStore extends ChangeNotifier {
|
||||
bool processAliases(String line) {
|
||||
bool sendLine = true;
|
||||
final str = line;
|
||||
for (final alias in [...builtInAliases, ...aliases]) {
|
||||
for (final alias in [...builtInAliases, ...currentProfile.aliases]) {
|
||||
if (!alias.isAvailable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class AliasListPage extends StatelessWidget with GameStoreMixin {
|
||||
return GenericListPage(
|
||||
title: const Text('Aliases'),
|
||||
save: save,
|
||||
items: storeOf(context).aliases,
|
||||
items: storeOf(context).currentProfile.aliases,
|
||||
detailsPath: Paths.alias,
|
||||
displayName: (alias) => alias.pattern,
|
||||
searchTags: (alias) => [
|
||||
@@ -45,7 +45,7 @@ class AliasListPage extends StatelessWidget with GameStoreMixin {
|
||||
switch (value) {
|
||||
case 'delete':
|
||||
store.currentProfile.deleteAlias(alias);
|
||||
store.loadAliases();
|
||||
store.currentProfile.loadAliases();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -68,6 +68,6 @@ class AliasListPage extends StatelessWidget with GameStoreMixin {
|
||||
Future<void> save(GameStore store, Alias updated) async {
|
||||
await store.currentProfile.saveAlias(updated);
|
||||
// TODO - stop re-loading all aliases, only replace the one that changed
|
||||
await store.loadAliases();
|
||||
await store.currentProfile.loadAliases();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class ButtonSetListPage extends StatelessWidget with GameStoreMixin {
|
||||
return GenericListPage(
|
||||
title: const Text('Button Sets'),
|
||||
save: save,
|
||||
items: storeOf(context).buttonSets,
|
||||
items: storeOf(context).currentProfile.buttonSets,
|
||||
detailsPath: Paths.buttonSet,
|
||||
displayName: (buttonSet) => buttonSet.name,
|
||||
searchTags: (buttonSet) => [
|
||||
@@ -40,7 +40,7 @@ class ButtonSetListPage extends StatelessWidget with GameStoreMixin {
|
||||
);
|
||||
if (data != null) {
|
||||
store.currentProfile.saveButtonSet(data as GameButtonSetData);
|
||||
store.loadButtonSets();
|
||||
store.currentProfile.loadButtonSets();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ class ButtonSetListPage extends StatelessWidget with GameStoreMixin {
|
||||
switch (value) {
|
||||
case 'delete':
|
||||
store.currentProfile.deleteButtonSet(buttonSet);
|
||||
store.loadButtonSets();
|
||||
store.currentProfile.loadButtonSets();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -95,7 +95,7 @@ class ButtonSetListPage extends StatelessWidget with GameStoreMixin {
|
||||
Future<void> save(GameStore store, GameButtonSetData updated) async {
|
||||
await store.currentProfile.saveButtonSet(updated);
|
||||
// TODO - stop re-loading all triggers, only replace the one that changed
|
||||
await store.loadButtonSets();
|
||||
await store.currentProfile.loadButtonSets();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../core/consts.dart';
|
||||
import '../core/features/game_button_set.dart';
|
||||
import '../core/keyboard_shortcuts.dart';
|
||||
import '../core/features/keyboard_shortcuts.dart';
|
||||
import '../core/store.dart';
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
@@ -85,9 +85,10 @@ class HomePageState extends State<HomePage>
|
||||
TextSpan(
|
||||
text: segment.text,
|
||||
style: consoleStyle.copyWith(
|
||||
color: Color(segment.themedFgColor),
|
||||
backgroundColor:
|
||||
Color(segment.themedBgColor),
|
||||
color: Color(
|
||||
segment.themedFgColor),
|
||||
backgroundColor: Color(
|
||||
segment.themedBgColor),
|
||||
fontWeight: segment.bold
|
||||
? FontWeight.w800
|
||||
: null,
|
||||
@@ -114,12 +115,14 @@ class HomePageState extends State<HomePage>
|
||||
),
|
||||
),
|
||||
),
|
||||
for (final buttonSet
|
||||
in store.buttonSets.where((b) => b.enabled))
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GameButtonSet(data: buttonSet),
|
||||
)
|
||||
if (store.connected)
|
||||
for (final buttonSet in store
|
||||
.currentProfile.buttonSets
|
||||
.where((b) => b.enabled))
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GameButtonSet(data: buttonSet),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../core/keyboard_shortcuts.dart';
|
||||
import '../core/features/keyboard_shortcuts.dart';
|
||||
|
||||
|
||||
class KeyboardShortcutsPage extends StatefulWidget {
|
||||
const KeyboardShortcutsPage({super.key, required this.shortcuts, required this.onSave});
|
||||
|
||||
@@ -13,7 +13,7 @@ class TriggerListPage extends StatelessWidget with GameStoreMixin {
|
||||
return GenericListPage(
|
||||
title: const Text('Triggers'),
|
||||
save: save,
|
||||
items: storeOf(context).triggers,
|
||||
items: storeOf(context).currentProfile.triggers,
|
||||
detailsPath: Paths.trigger,
|
||||
displayName: (trigger) => trigger.pattern,
|
||||
searchTags: (trigger) => [
|
||||
@@ -45,8 +45,9 @@ class TriggerListPage extends StatelessWidget with GameStoreMixin {
|
||||
onSelected: (value) {
|
||||
switch (value) {
|
||||
case 'delete':
|
||||
// TODO extract this to props
|
||||
store.currentProfile.deleteTrigger(trigger);
|
||||
store.loadTriggers();
|
||||
store.currentProfile.loadTriggers();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -66,10 +67,11 @@ class TriggerListPage extends StatelessWidget with GameStoreMixin {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO extract this to props
|
||||
Future<void> save(GameStore store, Trigger updated) async {
|
||||
await store.currentProfile.saveTrigger(updated);
|
||||
// TODO - stop re-loading all triggers, only replace the one that changed
|
||||
await store.loadTriggers();
|
||||
await store.currentProfile.loadTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,11 @@ 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.variables.values;
|
||||
final variables = store.currentProfile.variables.values;
|
||||
return ListView.builder(
|
||||
itemCount: variables.length,
|
||||
itemBuilder: (context, item) {
|
||||
@@ -53,9 +54,11 @@ class VariableListPage extends StatelessWidget with GameStoreMixin {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO extract this to props
|
||||
Future<void> save(GameStore store, Variable updated) async {
|
||||
await store.currentProfile
|
||||
.saveVariable(store.variables.values.toList(), updated);
|
||||
await store.loadVariables();
|
||||
.saveVariable(store.currentProfile.variables.values.toList(), updated);
|
||||
await store.currentProfile.loadVariables();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user