Skip to content

Commit dbd1d27

Browse files
authored
Settings changes (#133)
- Re-arranged settings in the settings page and data/file - Moved throttle from the gamepad to a settings page popup - Made views resizable - Migrated all ProviderConsumers to ReactiveWidgets - Removed unused packages - Bumped version - Implemented Manual, Idle, and Autonomy modes - Simplified drive code - Added Android controls - Added reset button for resizable views
1 parent 30855cc commit dbd1d27

39 files changed

+1339
-1167
lines changed

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
2626
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
2727

2828
android {
29-
compileSdkVersion flutter.compileSdkVersion
29+
compileSdkVersion 34
3030
ndkVersion flutter.ndkVersion
3131

3232
compileOptions {

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ subprojects {
2626
project.evaluationDependsOn(':app')
2727
}
2828

29-
task clean(type: Delete) {
29+
tasks.register("clean", Delete) {
3030
delete rootProject.buildDir
3131
}

build.yaml

Lines changed: 0 additions & 19 deletions
This file was deleted.

lib/app.dart

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
library app;
88

99
import "package:flutter/material.dart";
10-
import "package:provider/provider.dart";
11-
12-
import "package:rover_dashboard/models.dart";
1310
import "package:rover_dashboard/pages.dart";
1411

1512
/// The classic Binghamton green.
@@ -18,43 +15,31 @@ const binghamtonGreen = Color(0xff005943);
1815
/// The main class for the app.
1916
class RoverControlDashboard extends StatelessWidget {
2017
@override
21-
Widget build(BuildContext context) => MultiProvider(
22-
providers: [
23-
ChangeNotifierProvider.value(value: models),
24-
ChangeNotifierProvider.value(value: models.video),
25-
ChangeNotifierProvider.value(value: models.home),
26-
ChangeNotifierProvider.value(value: models.rover),
27-
ChangeNotifierProvider.value(value: models.serial),
28-
ChangeNotifierProvider.value(value: models.settings),
29-
],
30-
child: Consumer<Models>(
31-
builder: (context, models, _) => MaterialApp(
32-
title: "Binghamton University Rover Team",
33-
home: SplashPage(),
34-
debugShowCheckedModeBanner: false,
35-
theme: ThemeData(
36-
useMaterial3: false,
37-
colorScheme: const ColorScheme.light(
38-
primary: binghamtonGreen,
39-
secondary: binghamtonGreen,
40-
),
41-
appBarTheme: const AppBarTheme(
42-
backgroundColor: binghamtonGreen,
43-
// titleTextStyle: TextStyle(color: Colors.white),
44-
foregroundColor: Colors.white,
45-
),
46-
),
47-
darkTheme: ThemeData.from(
48-
colorScheme: const ColorScheme.dark(
49-
primary: binghamtonGreen,
50-
secondary: binghamtonGreen,
51-
),
52-
),
53-
routes: {
54-
Routes.home: (_) => HomePage(),
55-
Routes.settings: (_) => SettingsPage(),
56-
},
57-
),
58-
),
18+
Widget build(BuildContext context) => MaterialApp(
19+
title: "Binghamton University Rover Team",
20+
home: SplashPage(),
21+
debugShowCheckedModeBanner: false,
22+
theme: ThemeData(
23+
useMaterial3: false,
24+
colorScheme: const ColorScheme.light(
25+
primary: binghamtonGreen,
26+
secondary: binghamtonGreen,
27+
),
28+
appBarTheme: const AppBarTheme(
29+
backgroundColor: binghamtonGreen,
30+
// titleTextStyle: TextStyle(color: Colors.white),
31+
foregroundColor: Colors.white,
32+
),
33+
),
34+
darkTheme: ThemeData.from(
35+
colorScheme: const ColorScheme.dark(
36+
primary: binghamtonGreen,
37+
secondary: binghamtonGreen,
38+
),
39+
),
40+
routes: {
41+
Routes.home: (_) => HomePage(),
42+
Routes.settings: (_) => SettingsPage(),
43+
},
5944
);
6045
}

lib/data.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/// The data library.
44
///
5-
/// This library defines any data types needed by the rest of the app. While the dataclasses may
5+
/// This library defines any data types needed by the rest of the app. While the data classes may
66
/// have methods, the logic within should be simple, and any broad logic that changes state should
77
/// happen in the models library.
88
///
@@ -21,7 +21,6 @@ export "src/data/metrics/mars.dart";
2121
export "src/data/metrics/metrics.dart";
2222
export "src/data/metrics/science.dart";
2323

24-
export "src/data/constants.dart";
2524
export "src/data/modes.dart";
2625
export "src/data/protobuf.dart";
2726
export "src/data/science.dart";

lib/models.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export "src/models/view/builders/science_command.dart";
5252
export "src/models/view/builders/builder.dart";
5353
export "src/models/view/builders/color_builder.dart";
5454
export "src/models/view/builders/settings_builder.dart";
55+
export "src/models/view/builders/throttle.dart";
5556
export "src/models/view/builders/timer_builder.dart";
5657
export "src/models/view/builders/video_builder.dart";
5758

lib/src/data/constants.dart

Lines changed: 0 additions & 22 deletions
This file was deleted.

lib/src/data/settings.dart

Lines changed: 58 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,6 @@ extension SettingsParser on Json {
1010
}
1111
}
1212

13-
/// Settings relating to video.
14-
class VideoSettings {
15-
/// How many frames to render per second.
16-
///
17-
/// This does not affect how many frames are sent by the rover per second.
18-
final int fps;
19-
20-
/// A const constructor.
21-
const VideoSettings({required this.fps});
22-
23-
/// Parses a [VideoSettings] from JSON.
24-
VideoSettings.fromJson(Json? json) :
25-
fps = (json?["fps"] ?? 60) as int;
26-
27-
/// Serializes these settings in JSON format.
28-
Json toJson() => {
29-
"fps": fps,
30-
};
31-
}
32-
3313
/// Settings relating to science.
3414
class ScienceSettings {
3515
/// How many frames to render per second.
@@ -140,16 +120,12 @@ class NetworkSettings {
140120
/// the tank when it's being used.
141121
final SocketInfo tankSocket;
142122

143-
/// The address and port of the Rover's GPS
144-
final SocketInfo marsSocket;
145-
146123
/// Creates a new network settings object.
147124
NetworkSettings({
148125
required this.subsystemsSocket,
149126
required this.videoSocket,
150127
required this.autonomySocket,
151128
required this.tankSocket,
152-
required this.marsSocket,
153129
required this.connectionTimeout,
154130
});
155131

@@ -159,7 +135,6 @@ class NetworkSettings {
159135
videoSocket = json?.getSocket("videoSocket") ?? SocketInfo.raw("192.168.1.30", 8002),
160136
autonomySocket = json?.getSocket("autonomySocket") ?? SocketInfo.raw("192.168.1.30", 8003),
161137
tankSocket = json?.getSocket("tankSocket") ?? SocketInfo.raw("192.168.1.40", 8000),
162-
marsSocket = json?.getSocket("marsSocket") ?? SocketInfo.raw("192.168.1.50", 8006),
163138
connectionTimeout = json?["connectionTimeout"] ?? 5;
164139

165140
/// Serializes these settings to JSON.
@@ -168,34 +143,10 @@ class NetworkSettings {
168143
"videoSocket": videoSocket.toJson(),
169144
"autonomySocket": autonomySocket.toJson(),
170145
"tankSocket": tankSocket.toJson(),
171-
"marsSocket": marsSocket.toJson(),
172146
"connectionTimeout": connectionTimeout,
173147
};
174148
}
175149

176-
/// Settings relating to autonomy.
177-
class AutonomySettings {
178-
/// The precision of the GPS grid.
179-
///
180-
/// Since GPS coordinates are decimal values, we divide by this value to get the index of the cell
181-
/// each coordinate belongs to. Smaller sizes means more blocks, but we should be careful that the
182-
/// blocks are big enough to the margin of error of our GPS. This value must be synced with the
183-
/// value in the autonomy program, or else the UI will not be accurate to the rover's logic.
184-
final double blockSize;
185-
186-
/// A const constructor.
187-
const AutonomySettings({required this.blockSize});
188-
189-
/// Parses autonomy settings from a JSON map.
190-
AutonomySettings.fromJson(Json? json) :
191-
blockSize = json?["blockSize"] ?? 1.0;
192-
193-
/// Serializes these settings to JSON.
194-
Json toJson() => {
195-
"blockSize": blockSize,
196-
};
197-
}
198-
199150
/// Settings relating to easter eggs.
200151
///
201152
/// Implement these! Ask Levi for details.
@@ -223,14 +174,63 @@ class EasterEggsSettings {
223174
};
224175
}
225176

177+
/// Controls the way the Dashboard views split.
178+
enum SplitMode {
179+
/// Two views are split horizontally, one atop the other.
180+
horizontal("Top and bottom"),
181+
/// Two views are split vertically, side-by-side.
182+
vertical("Side by side");
183+
184+
/// The name to show in the UI.
185+
final String humanName;
186+
/// A const constructor.
187+
const SplitMode(this.humanName);
188+
}
189+
190+
/// Settings related to the dashboard itself, not the rover.
191+
class DashboardSettings {
192+
/// How the Dashboard should split when only two views are present.
193+
final SplitMode splitMode;
194+
195+
/// The precision of the GPS grid.
196+
///
197+
/// Since GPS coordinates are decimal values, we divide by this value to get the index of the cell
198+
/// each coordinate belongs to. Smaller sizes means more blocks, but we should be careful that the
199+
/// blocks are big enough to the margin of error of our GPS. This value must be synced with the
200+
/// value in the autonomy program, or else the UI will not be accurate to the rover's logic.
201+
final double mapBlockSize;
202+
203+
/// How many frames to render per second.
204+
///
205+
/// This does not affect how many frames are sent by the rover per second.
206+
final int maxFps;
207+
208+
/// A const constructor.
209+
const DashboardSettings({
210+
required this.splitMode,
211+
required this.mapBlockSize,
212+
required this.maxFps,
213+
});
214+
215+
/// Parses Dashboard settings from JSON.
216+
DashboardSettings.fromJson(Json? json) :
217+
splitMode = SplitMode.values[json?["splitMode"] ?? SplitMode.horizontal.index],
218+
mapBlockSize = json?["mapBlockSize"] ?? 1.0,
219+
maxFps = (json?["maxFps"] ?? 60) as int;
220+
221+
/// Serializes these settings to JSON.
222+
Json toJson() => {
223+
"splitMode": splitMode.index,
224+
"mapBlockSize": mapBlockSize,
225+
"maxFps": maxFps,
226+
};
227+
}
228+
226229
/// Contains the settings for running the dashboard and the rover.
227230
class Settings {
228231
/// Settings for the network, like IP addresses and ports.
229232
final NetworkSettings network;
230233

231-
/// Settings for video display.
232-
final VideoSettings video;
233-
234234
/// Settings for easter eggs.
235235
///
236236
/// Please, please, please -- do not remove these (Levi Lesches, '25).
@@ -242,35 +242,32 @@ class Settings {
242242
/// Settings for the science analysis.
243243
final ScienceSettings science;
244244

245-
/// Settings for the autonomy display.
246-
final AutonomySettings autonomy;
245+
/// Settings related to the dashboard itself.
246+
final DashboardSettings dashboard;
247247

248248
/// A const constructor.
249249
const Settings({
250250
required this.network,
251-
required this.video,
252251
required this.easterEggs,
253252
required this.science,
254253
required this.arm,
255-
required this.autonomy,
254+
required this.dashboard,
256255
});
257256

258257
/// Initialize settings from Json.
259258
Settings.fromJson(Json json) :
260-
autonomy = AutonomySettings.fromJson(json["autonomy"]),
261259
network = NetworkSettings.fromJson(json["network"]),
262-
video = VideoSettings.fromJson(json["video"]),
263260
easterEggs = EasterEggsSettings.fromJson(json["easterEggs"]),
264261
science = ScienceSettings.fromJson(json["science"]),
265-
arm = ArmSettings.fromJson(json["arm"]);
262+
arm = ArmSettings.fromJson(json["arm"]),
263+
dashboard = DashboardSettings.fromJson(json["dashboard"]);
266264

267265
/// Converts the data from the settings instance to Json.
268266
Json toJson() => {
269-
"autonomy": autonomy.toJson(),
270267
"network": network.toJson(),
271-
"video": video.toJson(),
272268
"easterEggs": easterEggs.toJson(),
273269
"science": science.toJson(),
274270
"arm": arm.toJson(),
271+
"dashboard": dashboard.toJson(),
275272
};
276273
}

lib/src/models/data/home.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class HomeModel extends Model {
3636
_messageTimer?.cancel(); // the new message might be cleared if the old one were about to
3737
message = TaskbarMessage(severity: severity, text: text);
3838
notifyListeners();
39-
if (permanent) _hasError = true;
39+
_hasError = permanent;
4040
_messageTimer = Timer(const Duration(seconds: 3), clear);
4141
}
4242

lib/src/models/data/settings.dart

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,15 @@ class SettingsModel extends Model {
1313
/// The user's arm settings.
1414
ArmSettings get arm => all.arm;
1515

16-
/// The user's video settings.
17-
VideoSettings get video => all.video;
18-
1916
/// The user's science settings.
2017
ScienceSettings get science => all.science;
2118

22-
/// The user's autonomy settings.
23-
AutonomySettings get autonomy => all.autonomy;
24-
2519
/// The user's easter egg settings.
2620
EasterEggsSettings get easterEggs => all.easterEggs;
2721

22+
/// The user's dashboard settings.
23+
DashboardSettings get dashboard => all.dashboard;
24+
2825
@override
2926
Future<void> init() async {
3027
all = await services.files.readSettings();

0 commit comments

Comments
 (0)