Skip to content

Commit b245d11

Browse files
Revert "began refactoring ui" (#209)
This reverts commit 32ba5bc.
1 parent 32ba5bc commit b245d11

22 files changed

+711
-2907
lines changed
Lines changed: 29 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import 'dart:async';
22
import 'dart:math';
33
import 'package:flutter/material.dart';
4-
import 'package:community_charts_flutter/community_charts_flutter.dart'
5-
as charts;
4+
import 'package:community_charts_flutter/community_charts_flutter.dart' as charts;
65

76
class RollingChart extends StatefulWidget {
87
final Stream<(int, double)> dataSteam;
98
final int timestampExponent; // e.g., 6 for microseconds to milliseconds
10-
final int timeWindow; // in seconds
9+
final int timeWindow; // in milliseconds
1110

1211
const RollingChart({
1312
super.key,
@@ -21,9 +20,8 @@ class RollingChart extends StatefulWidget {
2120
}
2221

2322
class _RollingChartState extends State<RollingChart> {
24-
List<charts.Series<_ChartPoint, num>> _seriesList = [];
25-
final List<_RawChartPoint> _rawData = [];
26-
List<_ChartPoint> _normalizedData = [];
23+
List<charts.Series<_ChartPoint, int>> _seriesList = [];
24+
final List<_ChartPoint> _data = [];
2725
StreamSubscription? _subscription;
2826

2927
@override
@@ -44,87 +42,56 @@ class _RollingChartState extends State<RollingChart> {
4442
void _listenToStream() {
4543
_subscription = widget.dataSteam.listen((event) {
4644
final (timestamp, value) = event;
47-
45+
4846
setState(() {
49-
_rawData.add(_RawChartPoint(timestamp, value));
50-
47+
_data.add(_ChartPoint(timestamp, value));
48+
5149
// Remove old data outside time window
52-
final ticksPerSecond = pow(10, -widget.timestampExponent).toDouble();
53-
final cutoffTime =
54-
timestamp - (widget.timeWindow * ticksPerSecond).round();
55-
_rawData.removeWhere((data) => data.timestamp < cutoffTime);
56-
50+
int cutoffTime = timestamp - (widget.timeWindow * pow(10, -widget.timestampExponent) as int);
51+
_data.removeWhere((data) => data.time < cutoffTime);
52+
5753
_updateSeries();
5854
});
5955
});
6056
}
6157

6258
void _updateSeries() {
63-
if (_rawData.isEmpty) {
64-
_normalizedData = [];
65-
_seriesList = [];
66-
return;
67-
}
68-
69-
final firstTimestamp = _rawData.first.timestamp;
70-
final secondsPerTick = pow(10, widget.timestampExponent).toDouble();
71-
72-
_normalizedData = _rawData
73-
.map(
74-
(point) => _ChartPoint(
75-
(point.timestamp - firstTimestamp) * secondsPerTick,
76-
point.value,
77-
),
78-
)
79-
.toList(growable: false);
80-
8159
_seriesList = [
82-
charts.Series<_ChartPoint, num>(
83-
id: 'Live Data',
84-
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
85-
domainFn: (_ChartPoint point, _) => point.timeSeconds,
86-
measureFn: (_ChartPoint point, _) => point.value,
87-
data: _normalizedData,
60+
charts.Series<_ChartPoint, int>(
61+
id: 'Live Data',
62+
colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
63+
domainFn: (_ChartPoint point, _) => point.time,
64+
measureFn: (_ChartPoint point, _) => point.value,
65+
data: List.of(_data),
8866
),
8967
];
9068
}
9169

9270
@override
9371
Widget build(BuildContext context) {
94-
final filteredPoints = _normalizedData;
72+
final filteredPoints = _data;
9573

96-
final xValues = filteredPoints.map((e) => e.timeSeconds).toList();
74+
final xValues = filteredPoints.map((e) => e.time).toList();
9775
final yValues = filteredPoints.map((e) => e.value).toList();
9876

99-
final double xMin = 0;
100-
final double xMax = max(
101-
widget.timeWindow.toDouble(),
102-
xValues.isNotEmpty ? xValues.reduce((a, b) => a > b ? a : b) : 0,
103-
);
77+
final int? xMin = xValues.isNotEmpty ? xValues.reduce((a, b) => a < b ? a : b) : null;
78+
final int? xMax = xValues.isNotEmpty ? xValues.reduce((a, b) => a > b ? a : b) : null;
10479

105-
final double? yMin =
106-
yValues.isNotEmpty ? yValues.reduce((a, b) => a < b ? a : b) : null;
107-
final double? yMax =
108-
yValues.isNotEmpty ? yValues.reduce((a, b) => a > b ? a : b) : null;
80+
final double? yMin = yValues.isNotEmpty ? yValues.reduce((a, b) => a < b ? a : b) : null;
81+
final double? yMax = yValues.isNotEmpty ? yValues.reduce((a, b) => a > b ? a : b) : null;
10982

11083
return charts.LineChart(
11184
_seriesList,
11285
animate: false,
11386
domainAxis: charts.NumericAxisSpec(
114-
viewport: charts.NumericExtents(xMin, xMax),
115-
tickFormatterSpec: charts.BasicNumericTickFormatterSpec((num? value) {
116-
if (value == null) return '';
117-
final rounded = value.roundToDouble();
118-
if ((value - rounded).abs() < 0.05) {
119-
return '${rounded.toInt()}s';
120-
}
121-
return '${value.toStringAsFixed(1)}s';
122-
}),
87+
viewport: xMin != null && xMax != null
88+
? charts.NumericExtents(xMin, xMax)
89+
: null,
12390
),
12491
primaryMeasureAxis: charts.NumericAxisSpec(
12592
viewport: yMin != null && yMax != null
126-
? charts.NumericExtents(yMin, yMax)
127-
: null,
93+
? charts.NumericExtents(yMin, yMax)
94+
: null,
12895
),
12996
);
13097
}
@@ -136,16 +103,9 @@ class _RollingChartState extends State<RollingChart> {
136103
}
137104
}
138105

139-
class _RawChartPoint {
140-
final int timestamp;
141-
final double value;
142-
143-
_RawChartPoint(this.timestamp, this.value);
144-
}
145-
146106
class _ChartPoint {
147-
final double timeSeconds;
107+
final int time;
148108
final double value;
149109

150-
_ChartPoint(this.timeSeconds, this.value);
110+
_ChartPoint(this.time, this.value);
151111
}

open_wearable/lib/apps/widgets/app_compatibility.dart

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 16 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
3-
import 'package:open_wearable/apps/widgets/app_compatibility.dart';
43
import 'package:open_wearable/apps/widgets/apps_page.dart';
5-
import 'package:open_wearable/view_models/wearables_provider.dart';
6-
import 'package:provider/provider.dart';
74

85
class AppTile extends StatelessWidget {
96
final AppInfo app;
@@ -12,183 +9,26 @@ class AppTile extends StatelessWidget {
129

1310
@override
1411
Widget build(BuildContext context) {
15-
final connectedWearableNames = context
16-
.watch<WearablesProvider>()
17-
.wearables
18-
.map((wearable) => wearable.name)
19-
.toList(growable: false);
20-
final titleStyle = Theme.of(context).textTheme.titleMedium?.copyWith(
21-
fontWeight: FontWeight.w700,
22-
);
23-
24-
return Card(
25-
margin: const EdgeInsets.only(bottom: 10),
26-
clipBehavior: Clip.antiAlias,
27-
child: InkWell(
12+
return PlatformListTile(
13+
title: PlatformText(app.title),
14+
subtitle: PlatformText(app.description),
15+
leading: SizedBox(
16+
height: 50.0,
17+
width: 50.0,
18+
child: ClipRRect(
19+
borderRadius: BorderRadius.circular(8.0),
20+
child: Image.asset(
21+
app.logoPath,
22+
fit: BoxFit.cover,
23+
),
24+
),
25+
),
2826
onTap: () {
2927
Navigator.push(
3028
context,
31-
platformPageRoute(
32-
context: context,
33-
builder: (context) => app.widget,
34-
),
29+
platformPageRoute(context: context, builder: (context) => app.widget),
3530
);
3631
},
37-
child: Padding(
38-
padding: const EdgeInsets.all(12),
39-
child: Row(
40-
children: [
41-
Container(
42-
height: 62.0,
43-
width: 62.0,
44-
decoration: BoxDecoration(
45-
borderRadius: BorderRadius.circular(14),
46-
border: Border.all(
47-
color: app.accentColor.withValues(alpha: 0.28),
48-
),
49-
),
50-
child: ClipRRect(
51-
borderRadius: BorderRadius.circular(13.0),
52-
child: Image.asset(
53-
app.logoPath,
54-
fit: BoxFit.cover,
55-
),
56-
),
57-
),
58-
const SizedBox(width: 12),
59-
Expanded(
60-
child: Column(
61-
crossAxisAlignment: CrossAxisAlignment.start,
62-
children: [
63-
Row(
64-
children: [
65-
Expanded(
66-
child: Text(
67-
app.title,
68-
style: titleStyle,
69-
maxLines: 1,
70-
overflow: TextOverflow.ellipsis,
71-
),
72-
),
73-
_LaunchAffordance(accentColor: app.accentColor),
74-
],
75-
),
76-
const SizedBox(height: 3),
77-
Text(
78-
app.description,
79-
maxLines: 2,
80-
overflow: TextOverflow.ellipsis,
81-
style: Theme.of(context).textTheme.bodyMedium,
82-
),
83-
const SizedBox(height: 8),
84-
Text(
85-
'Supported devices',
86-
style: Theme.of(context).textTheme.labelSmall?.copyWith(
87-
color: Theme.of(context)
88-
.textTheme
89-
.bodySmall
90-
?.color
91-
?.withValues(alpha: 0.72),
92-
fontWeight: FontWeight.w700,
93-
),
94-
),
95-
const SizedBox(height: 6),
96-
Wrap(
97-
spacing: 6,
98-
runSpacing: 6,
99-
children: app.supportedDevices
100-
.map(
101-
(device) => _SupportedDeviceChip(
102-
text: device,
103-
accentColor: app.accentColor,
104-
isConnected: hasConnectedWearableForPrefix(
105-
devicePrefix: device,
106-
connectedWearableNames: connectedWearableNames,
107-
),
108-
),
109-
)
110-
.toList(),
111-
),
112-
],
113-
),
114-
),
115-
],
116-
),
117-
),
118-
),
119-
);
120-
}
121-
}
122-
123-
class _LaunchAffordance extends StatelessWidget {
124-
final Color accentColor;
125-
126-
const _LaunchAffordance({
127-
required this.accentColor,
128-
});
129-
130-
@override
131-
Widget build(BuildContext context) {
132-
return Container(
133-
margin: const EdgeInsets.only(left: 8),
134-
height: 30,
135-
width: 30,
136-
decoration: BoxDecoration(
137-
color: accentColor.withValues(alpha: 0.12),
138-
borderRadius: BorderRadius.circular(999),
139-
),
140-
child: Icon(
141-
Icons.arrow_forward_rounded,
142-
size: 18,
143-
color: accentColor.withValues(alpha: 0.9),
144-
),
145-
);
146-
}
147-
}
148-
149-
class _SupportedDeviceChip extends StatelessWidget {
150-
final String text;
151-
final Color accentColor;
152-
final bool isConnected;
153-
154-
const _SupportedDeviceChip({
155-
required this.text,
156-
required this.accentColor,
157-
required this.isConnected,
158-
});
159-
160-
@override
161-
Widget build(BuildContext context) {
162-
const connectedDotColor = Color(0xFF2F8F5B);
163-
return Container(
164-
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
165-
decoration: BoxDecoration(
166-
color: accentColor.withValues(alpha: 0.1),
167-
borderRadius: BorderRadius.circular(999),
168-
),
169-
child: Row(
170-
mainAxisSize: MainAxisSize.min,
171-
children: [
172-
Text(
173-
text,
174-
style: Theme.of(context).textTheme.labelSmall?.copyWith(
175-
color: accentColor.withValues(alpha: 0.92),
176-
fontWeight: FontWeight.w600,
177-
),
178-
),
179-
if (isConnected) ...[
180-
const SizedBox(width: 6),
181-
Container(
182-
width: 7,
183-
height: 7,
184-
decoration: const BoxDecoration(
185-
color: connectedDotColor,
186-
shape: BoxShape.circle,
187-
),
188-
),
189-
],
190-
],
191-
),
192-
);
32+
);
19333
}
19434
}

0 commit comments

Comments
 (0)