Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
onlycs authored Feb 21, 2025
2 parents 4892f29 + 48ff58f commit a3f2906
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 97 deletions.
216 changes: 122 additions & 94 deletions lib/widgets/nt_widgets/multi-topic/robot_preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ class RobotPreferencesModel extends MultiTopicNTWidgetModel {
final TextEditingController searchTextController = TextEditingController();

final List<String> preferenceTopicNames = [];

final Map<String, NT4Subscription> preferenceSubscriptions = {};
final Map<String, VoidCallback> subscriptionListeners = {};

final Map<String, NT4Topic> preferenceTopics = {};
final Map<String, TextEditingController> preferenceTextControllers = {};
final Map<String, Object?> previousValues = {};

@override
List<NT4Subscription> get subscriptions =>
preferenceSubscriptions.values.toList();

late Function(NT4Topic topic) topicAnnounceListener;

late Function(NT4Topic topic) topicUnannounceListener;
Expand Down Expand Up @@ -54,18 +53,9 @@ class RobotPreferencesModel extends MultiTopicNTWidgetModel {
return;
}

Object? previousValue = ntConnection.getLastAnnouncedValue(topic.name);

preferenceTopicNames.add(topic.name);
preferenceTopics.addAll({topic.name: topic});
preferenceSubscriptions.addAll({
topic.name: ntConnection.subscribe(topic.name, super.period),
});
preferenceTextControllers.addAll({
topic.name: TextEditingController()
..text = previousValue?.toString() ?? ''
});
previousValues.addAll({topic.name: previousValue});
initSubscription(topic.name);

notifyListeners();
};
Expand All @@ -78,10 +68,8 @@ class RobotPreferencesModel extends MultiTopicNTWidgetModel {
preferenceTopicNames.remove(topic.name);

preferenceTopics.remove(topic.name);
destroySubscription(topic.name);

if (preferenceSubscriptions.containsKey(topic.name)) {
ntConnection.unSubscribe(preferenceSubscriptions[topic.name]!);
}
preferenceSubscriptions.remove(topic.name);

preferenceTextControllers.remove(topic.name);
Expand All @@ -100,13 +88,69 @@ class RobotPreferencesModel extends MultiTopicNTWidgetModel {
@override
void resetSubscription() {
for (NT4Subscription subscription in preferenceSubscriptions.values) {
ntConnection.unSubscribe(subscription);
destroySubscription(subscription.topic);
}
preferenceSubscriptions.clear();

preferenceTopics.clear();
preferenceTopicNames.clear();
preferenceTextControllers.clear();

// Trigger the topics to get recalled to the listener and added to the preferences list
ntConnection.removeTopicAnnounceListener(topicAnnounceListener);
ntConnection.addTopicAnnounceListener(topicAnnounceListener);

super.resetSubscription();
}

void initSubscription(String topicName) {
Object? previousValue = ntConnection.getLastAnnouncedValue(topicName);

NT4Subscription subscription =
ntConnection.subscribe(topicName, super.period);

preferenceSubscriptions.addAll({
topicName: subscription,
});
preferenceTextControllers.addAll({
topicName: TextEditingController()..text = previousValue?.toString() ?? ''
});
previousValues.addAll({topicName: previousValue});

VoidCallback listener;

subscription.addListener(listener = () => onSubscriptionUpdate(topicName));

subscriptionListeners.addAll({topicName: listener});
}

void destroySubscription(String topicName) {
NT4Subscription? subscription = preferenceSubscriptions[topicName];
if (subscription == null) {
return;
}

ntConnection.unSubscribe(subscription);

if (subscriptionListeners.containsKey(topicName)) {
subscription.removeListener(subscriptionListeners[topicName]!);
subscriptionListeners.remove(topicName);
}
}

void onSubscriptionUpdate(String topicName) {
if (!preferenceTextControllers.containsKey(topicName) ||
!subscriptionListeners.containsKey(topicName)) {
return;
}

if (preferenceSubscriptions[topicName]?.value.toString() !=
previousValues[topicName].toString()) {
preferenceTextControllers[topicName]?.text =
preferenceSubscriptions[topicName]?.value?.toString() ?? '';

previousValues[topicName] = preferenceSubscriptions[topicName]?.value;
}
}
}

Expand All @@ -119,71 +163,55 @@ class RobotPreferences extends NTWidget {
Widget build(BuildContext context) {
RobotPreferencesModel model = cast(context.watch<NTWidgetModel>());

return ListenableBuilder(
listenable: Listenable.merge(model.subscriptions),
builder: (context, child) {
for (String topic in model.preferenceTopicNames) {
if (model.preferenceSubscriptions[topic]?.value.toString() !=
model.previousValues[topic].toString()) {
model.preferenceTextControllers[topic]?.text =
model.preferenceSubscriptions[topic]?.value?.toString() ?? '';

model.previousValues[topic] =
model.preferenceSubscriptions[topic]?.value;
}
}

return PreferenceSearch(
onSubmit: (String topic, String? data) {
NT4Topic? nt4Topic = model.preferenceTopics[topic];

if (nt4Topic == null ||
!model.ntConnection.isTopicPublished(nt4Topic)) {
return;
}

if (data == null) {
model.ntConnection.unpublishTopic(nt4Topic);
return;
}

Object? formattedData;

String dataType = model.ntStructMeta?.type ?? nt4Topic.type;
switch (dataType) {
case NT4TypeStr.kBool:
formattedData = bool.tryParse(data);
break;
case NT4TypeStr.kFloat32:
case NT4TypeStr.kFloat64:
formattedData = double.tryParse(data);
break;
case NT4TypeStr.kInt:
formattedData = int.tryParse(data);
break;
case NT4TypeStr.kString:
formattedData = data;
break;
default:
break;
}

if (formattedData == null) {
model.preferenceTextControllers[topic]?.text =
model.previousValues[topic].toString();
model.ntConnection.unpublishTopic(nt4Topic);
return;
}

model.ntConnection.updateDataFromTopic(nt4Topic, formattedData);
model.ntConnection.unpublishTopic(nt4Topic);

model.preferenceTextControllers[topic]?.text =
formattedData.toString();
},
model: model,
);
});
return PreferenceSearch(
onSubmit: (String topic, String? data) {
NT4Topic? nt4Topic = model.preferenceTopics[topic];

if (nt4Topic == null ||
!model.ntConnection.isTopicPublished(nt4Topic)) {
return;
}

if (data == null) {
model.ntConnection.unpublishTopic(nt4Topic);
return;
}

Object? formattedData;

String dataType = model.ntStructMeta?.type ?? nt4Topic.type;
switch (dataType) {
case NT4TypeStr.kBool:
formattedData = bool.tryParse(data);
break;
case NT4TypeStr.kFloat32:
case NT4TypeStr.kFloat64:
formattedData = double.tryParse(data);
break;
case NT4TypeStr.kInt:
formattedData = int.tryParse(data);
break;
case NT4TypeStr.kString:
formattedData = data;
break;
default:
break;
}

if (formattedData == null) {
model.preferenceTextControllers[topic]?.text =
model.previousValues[topic].toString();
model.ntConnection.unpublishTopic(nt4Topic);
return;
}

model.ntConnection.updateDataFromTopic(nt4Topic, formattedData);
model.ntConnection.unpublishTopic(nt4Topic);

model.preferenceTextControllers[topic]?.text = formattedData.toString();
},
model: model,
);
}
}

Expand All @@ -197,6 +225,11 @@ class PreferenceSearch extends StatelessWidget {
final RobotPreferencesModel model;
final Function(String topic, String? data) onSubmit;

List<String> filterList(String query) => model.preferenceTopicNames
.where((element) =>
element.split('/').last.toLowerCase().contains(query.toLowerCase()))
.toList();

@override
Widget build(BuildContext context) {
return SearchableList<String>(
Expand All @@ -213,17 +246,12 @@ class PreferenceSearch extends StatelessWidget {
),
searchTextController: model.searchTextController,
seperatorBuilder: (context, _) => const Divider(height: 4.0),
spaceBetweenSearchAndList: 15,
filter: (query) {
return model.preferenceTopicNames
.where((element) => element
.split('/')
.last
.toLowerCase()
.contains(query.toLowerCase()))
.toList();
},
initialList: model.preferenceTopicNames,
searchFieldPadding: const EdgeInsets.symmetric(
horizontal: 2,
vertical: 7.5,
),
filter: (query) => filterList(query),
initialList: filterList(model.searchTextController.text),
itemBuilder: (item) {
TextEditingController? textController =
model.preferenceTextControllers[item];
Expand Down
4 changes: 2 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -893,10 +893,10 @@ packages:
dependency: "direct main"
description:
name: searchable_listview
sha256: f9bc1a57dfcba49ce2d190d642567fb82309dd23849b3b0a328266e3f90054db
sha256: "83d0a7673938f729078b554e47ccb66927645f798f5a2a1c0b2f85d52f1823b7"
url: "https://pub.dev"
source: hosted
version: "2.12.0"
version: "2.16.0"
shared_preferences:
dependency: "direct main"
description:
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ dependencies:
popover: ^0.3.0
provider: ^6.0.5
screen_retriever: ^0.2.0
searchable_listview: ^2.7.0
searchable_listview: ^2.16.0
shared_preferences: ^2.1.2
syncfusion_flutter_charts: ^23.1.44
titlebar_buttons: ^1.0.0
Expand Down

0 comments on commit a3f2906

Please sign in to comment.