Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Presets #173

Merged
merged 23 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6c9074b
Added drag and drop view selection
Gold872 Sep 17, 2024
2bf19ee
Cleaned up ViewsWidget a little bit
Gold872 Sep 17, 2024
0d2e452
Augite and temp work
max-mazer Sep 17, 2024
3e73176
Save/Load/Delete View Presets
max-mazer Oct 4, 2024
9a9ebd1
Added documentation
max-mazer Oct 4, 2024
8817806
some minor changes
aidanahram Oct 5, 2024
d1c9fb9
more minor changes
aidanahram Oct 5, 2024
0b7275b
Revert "some minor changes"
max-mazer Oct 6, 2024
87df5a7
Fixed save issue and refactored views_list.dart
max-mazer Oct 9, 2024
387acc0
Moved ViewPreset to its own file
Levi-Lesches Oct 9, 2024
e5593fc
Fixed error when decoding ViewPreset json
Levi-Lesches Oct 9, 2024
0d62456
Fixed problems loading the preset
Levi-Lesches Oct 9, 2024
1390bd8
Moved PresetBuilder.delete to the actual delete dialog
Levi-Lesches Oct 9, 2024
27c3763
Restore view selector in each view
Levi-Lesches Oct 9, 2024
0a2d3f9
Moved PresetSave and PresetDelete to their own file
Levi-Lesches Oct 9, 2024
bc5b1b0
Updated PresetBuilder
Levi-Lesches Oct 9, 2024
b2108f0
Removed the need for a dialog when loading presets
Levi-Lesches Oct 9, 2024
9276b4d
Made the presets menu react to new or deleted presets
Levi-Lesches Oct 9, 2024
742d5d1
Restored view selector by video feeds
Levi-Lesches Oct 9, 2024
cbf1c2e
Shortened time to resize ratios
Levi-Lesches Oct 9, 2024
48a8a85
Upgraded to later verison of flutter_resizable_container
Levi-Lesches Oct 9, 2024
d4b442f
Made reset view sizes more obvious
Levi-Lesches Oct 9, 2024
de4d85e
Presets can be re-ordered
Levi-Lesches Oct 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/Rocks_Minerals_Images/Augite.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ export "src/data/settings.dart";
export "src/data/socket.dart";
export "src/data/taskbar_message.dart";
export "src/data/utils.dart";
export "src/data/view_preset.dart";
2 changes: 2 additions & 0 deletions lib/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export "src/models/view/builders/settings_builder.dart";
export "src/models/view/builders/throttle.dart";
export "src/models/view/builders/timer_builder.dart";
export "src/models/view/builders/video_builder.dart";
export "src/models/view/builders/preset_builder.dart";


/// A wrapper model around all other data models used by the app.
///
Expand Down
62 changes: 35 additions & 27 deletions lib/src/data/settings.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import "package:flutter/material.dart";
import "package:rover_dashboard/data.dart";

import "socket.dart";

/// A collection of functions for parsing [Settings].
/// A collection of functions for parsing [Settings].
extension SettingsParser on Json {
/// Parses a [SocketInfo] that may not be present.
SocketInfo? getSocket(String key) {
Expand All @@ -15,7 +14,7 @@ extension SettingsParser on Json {
/// Settings relating to science.
class ScienceSettings {
/// How many frames to render per second.
///
///
/// This does not affect how many frames are sent by the rover per second.
final bool scrollableGraphs;

Expand All @@ -26,7 +25,7 @@ class ScienceSettings {
const ScienceSettings({required this.scrollableGraphs, required this.numSamples});

/// Parses a [ScienceSettings] from JSON.
ScienceSettings.fromJson(Json? json) :
ScienceSettings.fromJson(Json? json) :
numSamples = json?["numSamples"] ?? 3,
scrollableGraphs = json?["scrollableGraphs"] ?? false;

Expand Down Expand Up @@ -76,7 +75,7 @@ class ArmSettings {
});

/// Parses arm settings from a JSON map.
ArmSettings.fromJson(Json? json) :
ArmSettings.fromJson(Json? json) :
shoulder = json?["shoulder"] ?? 0.005,
elbow = json?["elbow"] ?? 0.005,
swivel = json?["swivel"] ?? 0.2,
Expand All @@ -102,8 +101,8 @@ class ArmSettings {
/// Settings related to network configuration.
class NetworkSettings {
/// The amount of time, in seconds, the dashboard should wait before determining it's
/// lost connection to the rover. For reference, the rover should be sending messages
/// at least once per second.
/// lost connection to the rover. For reference, the rover should be sending messages
/// at least once per second.
final double connectionTimeout;

/// The address and port of the subsystems program.
Expand All @@ -116,7 +115,7 @@ class NetworkSettings {
final SocketInfo autonomySocket;

/// The address of the tank. The port is ignored.
///
///
/// The Tank is a model rover that has all the same programs as the rover. This field does not
/// include port numbers because ports are specific to the program, and the tank will have many
/// programs running. Instead, the IP address of all the other programs should be swapped with
Expand All @@ -133,7 +132,7 @@ class NetworkSettings {
});

/// Parses network settings from a JSON map.
NetworkSettings.fromJson(Json? json) :
NetworkSettings.fromJson(Json? json) :
subsystemsSocket = json?.getSocket("subsystemsSocket") ?? SocketInfo.raw("192.168.1.20", 8001),
videoSocket = json?.getSocket("videoSocket") ?? SocketInfo.raw("192.168.1.30", 8002),
autonomySocket = json?.getSocket("autonomySocket") ?? SocketInfo.raw("192.168.1.30", 8003),
Expand All @@ -151,7 +150,7 @@ class NetworkSettings {
}

/// Settings relating to easter eggs.
///
///
/// Implement these! Ask Levi for details.
class EasterEggsSettings {
/// Whether to do a SEGA-like intro during boot.
Expand All @@ -161,7 +160,7 @@ class EasterEggsSettings {
/// Whether clippy should appear by log messages.
final bool enableClippy;
/// Whether to render Bad Apple in the Map page.
final bool badApple;
final bool badApple;

/// A const constructor.
const EasterEggsSettings({
Expand All @@ -172,7 +171,7 @@ class EasterEggsSettings {
});

/// Parses easter eggs settings from JSON.
EasterEggsSettings.fromJson(Json? json) :
EasterEggsSettings.fromJson(Json? json) :
segaIntro = json?["segaIntro"] ?? true,
segaSound = json?["segaSound"] ?? true,
enableClippy = json?["enableClippy"] ?? true,
Expand All @@ -191,9 +190,9 @@ class EasterEggsSettings {
enum SplitMode {
/// Two views are split horizontally, one atop the other.
horizontal("Top and bottom"),
/// Two views are split vertically, side-by-side.
/// Two views are split vertically, side-by-side.
vertical("Side by side");

/// The name to show in the UI.
final String humanName;
/// A const constructor.
Expand All @@ -216,37 +215,41 @@ class DashboardSettings {
final SplitMode splitMode;

/// The precision of the GPS grid.
///
///
/// Since GPS coordinates are decimal values, we divide by this value to get the index of the cell
/// each coordinate belongs to. Smaller sizes means more blocks, but we should be careful that the
/// blocks are big enough to the margin of error of our GPS. This value must be synced with the
/// value in the autonomy program, or else the UI will not be accurate to the rover's logic.
final double mapBlockSize;

/// How many frames to render per second.
///
///
/// This does not affect how many frames are sent by the rover per second.
final int maxFps;

/// The theme of the Dashboard.
/// The theme of the Dashboard.
final ThemeMode themeMode;

/// Whether to split cameras into their own controls.
///
/// Whether to split cameras into their own controls.
///
/// When this is disabled, some other modes, like arm or drive, may move the cameras.
/// When this is enabled, only the dedicated camera control mode can move the cameras.
final bool splitCameras;

/// Whether to default to tank drive controls.
///
///
/// Tank controls offer more custom control, but modern drive controls are more intuitive.
final bool preferTankControls;

/// Whether to have version checking on protobuf messages.
final bool versionChecking;

/// A list of ViewPresets
final List<ViewPreset> presets;

/// A const constructor.
const DashboardSettings({
required this.presets,
required this.splitMode,
required this.mapBlockSize,
required this.maxFps,
Expand All @@ -256,8 +259,12 @@ class DashboardSettings {
required this.versionChecking,
});

/// Parses Dashboard settings from JSON.
DashboardSettings.fromJson(Json? json) :
/// Parses settings from JSON.
DashboardSettings.fromJson(Json? json) :
presets = [
for (final presetJson in json?["presets"] ?? [])
ViewPreset.fromJson(presetJson),
],
splitMode = SplitMode.values[json?["splitMode"] ?? SplitMode.horizontal.index],
mapBlockSize = json?["mapBlockSize"] ?? 1.0,
maxFps = (json?["maxFps"] ?? 60) as int,
Expand All @@ -268,6 +275,7 @@ class DashboardSettings {

/// Serializes these settings to JSON.
Json toJson() => {
"presets" : presets,
"splitMode": splitMode.index,
"mapBlockSize": mapBlockSize,
"maxFps": maxFps,
Expand All @@ -278,13 +286,13 @@ class DashboardSettings {
};
}

/// Contains the settings for running the dashboard and the rover.
/// Contains the settings for running the dashboard and the rover.
class Settings {
/// Settings for the network, like IP addresses and ports.
final NetworkSettings network;

/// Settings for easter eggs.
///
///
/// Please, please, please -- do not remove these (Levi Lesches, '25).
final EasterEggsSettings easterEggs;

Expand All @@ -307,15 +315,15 @@ class Settings {
});

/// Initialize settings from Json.
Settings.fromJson(Json json) :
Settings.fromJson(Json json) :
network = NetworkSettings.fromJson(json["network"]),
easterEggs = EasterEggsSettings.fromJson(json["easterEggs"]),
science = ScienceSettings.fromJson(json["science"]),
arm = ArmSettings.fromJson(json["arm"]),
dashboard = DashboardSettings.fromJson(json["dashboard"]);

/// Converts the data from the settings instance to Json.
Json toJson() => {
Json toJson() => {
"network": network.toJson(),
"easterEggs": easterEggs.toJson(),
"science": science.toJson(),
Expand Down
67 changes: 67 additions & 0 deletions lib/src/data/view_preset.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import "package:rover_dashboard/data.dart";
import "package:rover_dashboard/pages.dart";

/// Preset for the dashboard.
class ViewPreset {
/// Preset name.
final String name;

/// List of views that comes with the views name (and if it is a camera view, its camera name).
final List<DashboardView> views;

/// Ratio of the controller for the resizable row on top.
final List<double> horizontal1;

/// Ratio of the controller for resizable row on bottom.
final List<double> horizontal2;

/// Ratio of the controller for screen 2's first row.
final List<double> horizontal3;

/// Ratio of the controller for screen 2's second row.
final List<double> horizontal4;

/// Ratio of the controller for the resizable column.
final List<double> vertical1;

/// The vertical controller for screen 2.
final List<double> vertical2;

/// A const constructor.
ViewPreset({
required this.name,
required this.views,
required this.horizontal1,
required this.horizontal2,
required this.vertical1,
required this.vertical2,
required this.horizontal3,
required this.horizontal4,
});

/// Parses a view preset from JSON.
ViewPreset.fromJson(Json? json) :
name = json?["name"] ?? "No Name",
views = [
for (final viewJson in json?["views"] ?? [])
DashboardView.fromJson(viewJson) ?? DashboardView.blank,
],
horizontal1 = List<double>.from(json?["horizontal1"] ?? []),
horizontal2 = List<double>.from(json?["horizontal2"] ?? []),
horizontal3 = List<double>.from(json?["horizontal3"] ?? []),
horizontal4 = List<double>.from(json?["horizontal4"] ?? []),
vertical1 = List<double>.from(json?["vertical1"] ?? []),
vertical2 = List<double>.from(json?["vertical2"] ?? []);

/// Serializes a view preset to JSON.
Json toJson() => {
"name": name,
"views" : views,
"horizontal1" : horizontal1,
"horizontal2" : horizontal2,
"horizontal3" : horizontal3,
"horizontal4" : horizontal4,
"vertical1" : vertical1,
"vertical2" : vertical2,
};
}
6 changes: 3 additions & 3 deletions lib/src/models/data/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class SettingsModel extends Model {
}

/// Replaces the current settings with the provided ones.
Future<void> update(Settings value) async {
Future<void> update([Settings? value]) async {
try {
await services.files.writeSettings(value);
all = value;
await services.files.writeSettings(value ?? all);
if (value != null) all = value;
notifyListeners();
} catch (error) {
models.home.setMessage(severity: Severity.critical, text: "Could not save settings: $error");
Expand Down
Loading
Loading