Skip to content

Commit

Permalink
Hopefully merge branch 'main' into provider
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFreal committed Nov 8, 2024
2 parents b504a21 + 3944c75 commit bf07ee5
Show file tree
Hide file tree
Showing 19 changed files with 417 additions and 95 deletions.
7 changes: 6 additions & 1 deletion assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"onboarding_step3_body": "Ein Roller mit der Adresse {address} wurde gefunden und kann verbunden werden.",
"onboarding_step3_button": "VERBINDEN",
"onboarding_step4_heading": "Verbinde...",
"onboarding_step4_body": "Behalte ein Auge auf deine Benachrichtigungen, du solltest gleich eine Kopplungsanfrage bekommen. Den Kopplungscode findest du auf dem Rollerdisplay.",
"onboarding_step4_body": "Du solltest in deinen Benachrichtigungen gleich eine Kopplungsanfrage sehen. Den Kopplungscode findest du auf dem Rollerdisplay.",
"onboarding_step4_explainer": "\n\nWichtig: Falls du mehrere Kopplungsanfragen siehst, bestätige bitte alle!",
"onboarding_step4_error": "Verbindung fehlgeschlagen. Stell sicher, dass der Roller eingeschaltet ist und versuche es erneut.",
"onboarding_step5_heading": "Das war's!",
"onboarding_step5_body": "Dein Roller wurde gekoppelt und kann jetzt mit der App gesteuert werden. Viel Spaß!",
Expand Down Expand Up @@ -97,6 +98,9 @@
"stats_state": "Zustand",
"stats_state_description": "Zustandsbeschreibung",
"stats_scooter_id": "Roller ID",
"stats_scooter_auto_connect": "Auto-Connect",
"stats_scooter_auto_connect_on_description": "Wenn der Roller in der Nähe ist",
"stats_scooter_auto_connect_off_description": "Nur manuell verbinden",
"stats_rssi": "Signalstärke",
"stats_rssi_disconnected": "Getrennt",
"stats_title_settings": "Einstellungen",
Expand Down Expand Up @@ -155,6 +159,7 @@
"settings_privacy_policy": "Datenschutzerklärung",
"settings_osm_consent": "Letzte bekannte Adresse anzeigen",
"settings_osm_consent_description": "Onlinedienste nutzen, um die Adresse des letzten bekannten Rollerstandorts anzuzeigen",
"settings_seasonal": "Saisonale Effekte",
"stats_last_ping_title": "Zuletzt verbunden",
"stats_last_ping": "Vor {time}",
"stats_last_ping_toast": "Zuletzt aktualisiert vor {time}",
Expand Down
5 changes: 5 additions & 0 deletions assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"onboarding_step3_button": "CONNECT",
"onboarding_step4_heading": "Connecting...",
"onboarding_step4_body": "You should get a pairing request in a second, so keep an eye on your notifications. You can find the pairing code on the scooter display.",
"onboarding_step4_explainer": "\n\nImportant: If you get multiple requests, you need to confirm all of them!",
"onboarding_step4_error": "Connection failed. Make sure the scooter is powered on and nearby, then try again.",
"onboarding_step5_heading": "That's it!",
"onboarding_step5_body": "Your scooter was connected and is ready to use. Enjoy your ride!",
Expand Down Expand Up @@ -97,6 +98,9 @@
"stats_state": "State",
"stats_state_description": "State description",
"stats_scooter_id": "Scooter ID",
"stats_scooter_auto_connect": "Auto-connect",
"stats_scooter_auto_connect_on_description": "If scooter is nearby",
"stats_scooter_auto_connect_off_description": "Only connect manually",
"stats_rssi": "Signal strength",
"stats_rssi_disconnected": "Disconnected",
"stats_title_settings": "Settings",
Expand Down Expand Up @@ -155,6 +159,7 @@
"settings_privacy_policy": "Privacy policy",
"settings_osm_consent": "Show last known address",
"settings_osm_consent_description": "Use online services to resolve the last known scooter location to a street address",
"settings_seasonal": "Seasonal effects",
"stats_last_ping_title": "Last connected",
"stats_last_ping": "{time} ago",
"stats_last_ping_toast": "Last updated {time} ago",
Expand Down
8 changes: 8 additions & 0 deletions assets/i18n/pi.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"onboarding_step3_button": "CONNECT",
"onboarding_step4_heading": "Connectin'...",
"onboarding_step4_body": "Ye should get a pairin' request in a second, so keep an eye on yer notifications. Ye can find the pairin' code on the ship display, arrr!",
"onboarding_step4_explainer": "\n\nImportant: If ye get multiple pairin' requests, ye shall confirm all of 'em!",
"onboarding_step4_error": "Connection failed, arrr! Make sure the ship be powered on and nearby, then try again.",
"onboarding_step5_heading": "That be it, arrr!",
"onboarding_step5_body": "Yer ship be connected and be ready to use. Enjoy yer ride, me heartie!",
Expand Down Expand Up @@ -97,6 +98,9 @@
"stats_state": "State",
"stats_state_description": "State description",
"stats_scooter_id": "Ship ID",
"stats_scooter_auto_connect": "This is me ship!",
"stats_scooter_auto_connect_on_description": "Board ship if it's nearby",
"stats_scooter_auto_connect_off_description": "Only board manually",
"stats_rssi": "Signal strength",
"stats_rssi_disconnected": "Disconnected",
"stats_title_settings": "Settings",
Expand Down Expand Up @@ -152,6 +156,10 @@
"forget_alert_cancel": "Cancel",
"forget_alert_confirm": "Reset now",
"settings_app_version": "App version",
"settings_privacy_policy": "Privacy policy",
"settings_osm_consent": "Show last known address",
"settings_osm_consent_description": "Use online services to resolve the last known scooter location to a street address",
"settings_seasonal": "Seasonal effects",
"stats_last_ping_title": "Last seen",
"stats_last_ping": "{time} ago",
"stats_last_ping_toast": "Ship last seen {time} ago",
Expand Down
12 changes: 6 additions & 6 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### Changes:
- Fix for users with location services disabled
- Adding privacy policy link
- Adding nominatim opt-out
- Better onboarding for color selection
- Improved error reporting
- Minor bug and typo fixes
- Fixed multiple pairing errors!
- Using system language on first launch
- Added auto-connect controls for users with multiple scooters linked
- Fixed warning for open seat when attempting to lock
- Fixed an error with older scooters
- Adding seasonal effect for December
Binary file modified images/scooter/base_9.webp
Binary file not shown.
Binary file added images/scooter/seasonal/winter_off.webp
Binary file not shown.
Binary file added images/scooter/seasonal/winter_on.webp
Binary file not shown.
8 changes: 7 additions & 1 deletion lib/domain/log_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import 'dart:convert';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:logging/logging.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Expand All @@ -28,7 +30,11 @@ class LogHelper {

void initialize() {
Logger.root.onRecord.listen((record) {
print(record);
if (kDebugMode && record.level >= Level.INFO) {
Fluttertoast.showToast(
msg: record.message, fontSize: 6, toastLength: Toast.LENGTH_SHORT);
print(record);
}
// Ensure the buffer doesn't exceed the max size
if (_logBuffer.length >= maxBufferSize) {
_logBuffer.removeAt(0); // Remove the oldest log entry
Expand Down
11 changes: 11 additions & 0 deletions lib/domain/saved_scooter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class SavedScooter {
String _id;
int _color;
DateTime _lastPing;
bool _autoConnect;
int? _lastPrimarySOC;
int? _lastSecondarySOC;
int? _lastCbbSOC;
Expand All @@ -19,6 +20,7 @@ class SavedScooter {
required String id,
int? color,
DateTime? lastPing,
bool? autoConnect,
int? lastPrimarySOC,
int? lastSecondarySOC,
int? lastCbbSOC,
Expand All @@ -28,6 +30,7 @@ class SavedScooter {
_id = id,
_color = color ?? 1,
_lastPing = lastPing ?? DateTime.now(),
_autoConnect = autoConnect ?? true,
_lastPrimarySOC = lastPrimarySOC,
_lastSecondarySOC = lastSecondarySOC,
_lastCbbSOC = lastCbbSOC,
Expand All @@ -49,6 +52,11 @@ class SavedScooter {
updateSharedPreferences();
}

set autoConnect(bool autoConnect) {
_autoConnect = autoConnect;
updateSharedPreferences();
}

set lastPrimarySOC(int? lastPrimarySOC) {
_lastPrimarySOC = lastPrimarySOC;
updateSharedPreferences();
Expand Down Expand Up @@ -78,6 +86,7 @@ class SavedScooter {
String get id => _id;
int get color => _color;
DateTime get lastPing => _lastPing;
bool get autoConnect => _autoConnect;
int? get lastPrimarySOC => _lastPrimarySOC;
int? get lastSecondarySOC => _lastSecondarySOC;
int? get lastCbbSOC => _lastCbbSOC;
Expand All @@ -89,6 +98,7 @@ class SavedScooter {
'name': _name,
'color': _color,
'lastPing': _lastPing.microsecondsSinceEpoch,
'autoConnect': _autoConnect,
'lastPrimarySOC': _lastPrimarySOC,
'lastSecondarySOC': _lastSecondarySOC,
'lastCbbSOC': _lastCbbSOC,
Expand All @@ -107,6 +117,7 @@ class SavedScooter {
lastPing: map.containsKey('lastPing')
? DateTime.fromMicrosecondsSinceEpoch(map['lastPing'])
: DateTime.now(),
autoConnect: map['autoConnect'],
lastLocation: map['lastLocation'] != null
? LatLng.fromJson(map['lastLocation'])
: null,
Expand Down
111 changes: 111 additions & 0 deletions lib/helper_widgets/snowfall.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import 'package:flutter/material.dart';
import 'dart:math';

class SnowfallBackground extends StatefulWidget {
final Color backgroundColor;
final Color snowflakeColor;

const SnowfallBackground(
{super.key, required this.backgroundColor, required this.snowflakeColor});

@override
SnowfallBackgroundState createState() => SnowfallBackgroundState();
}

class SnowfallBackgroundState extends State<SnowfallBackground>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
List<Snowflake>? _snowflakes; // Make _snowflakes nullable.
final int _snowflakeCount = 100;

@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 20))
..repeat();

_controller.addListener(() {
setState(() {
_snowflakes?.forEach((flake) => flake.updatePosition());
});
});
}

void _initializeSnowflakes(Size size) {
_snowflakes = List.generate(
_snowflakeCount,
(_) => Snowflake(size.width, size.height),
);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
// Initialize snowflakes if they haven't been created yet.
if (_snowflakes == null) {
_initializeSnowflakes(MediaQuery.of(context).size);
}

return Container(
color: widget.backgroundColor,
child: CustomPaint(
size: MediaQuery.of(context).size,
painter: SnowPainter(_snowflakes ?? [], widget.snowflakeColor),
),
);
}
}

class Snowflake {
late double x, y, speed, radius;

Snowflake(double maxWidth, double maxHeight) {
final random = Random();
x = random.nextDouble() *
maxWidth; // Now using the full width of the screen.
y = random.nextDouble() *
maxHeight; // Now using the full height of the screen.
speed = 0.2 + random.nextDouble() * 0.8;
radius = 0.5 + random.nextDouble() * 3;
}

void updatePosition() {
y += speed;
}
}

class SnowPainter extends CustomPainter {
final List<Snowflake> snowflakes;
final Color snowflakeColor;

SnowPainter(this.snowflakes, this.snowflakeColor);

@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = snowflakeColor.withOpacity(0.15);

for (var flake in snowflakes) {
// Ensure positions are constrained to the current canvas size.
double flakeX = flake.x % size.width;
double flakeY = flake.y % size.height;

if (flakeY > size.height) {
// Reset flake to the top when it goes beyond screen height.
flakeY = 0;
flake.x =
Random().nextDouble() * size.width; // Randomize X position again.
}

canvas.drawCircle(Offset(flakeX, flakeY), flake.radius, paint);
}
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
48 changes: 38 additions & 10 deletions lib/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import '../scooter_service.dart';
import '../domain/scooter_state.dart';
import '../scooter_visual.dart';
import '../stats/stats_screen.dart';
import 'helper_widgets/snowfall.dart';

class HomeScreen extends StatefulWidget {
final bool? forceOpen;
Expand All @@ -33,6 +34,7 @@ class HomeScreen extends StatefulWidget {
class _HomeScreenState extends State<HomeScreen> {
final log = Logger('HomeScreen');
bool _hazards = false;
bool _snowing = false;

@override
void initState() {
Expand All @@ -41,6 +43,21 @@ class _HomeScreenState extends State<HomeScreen> {
log.fine("Redirecting or starting");
redirectOrStart();
}
_startSeasonal();
}

Future<void> _startSeasonal() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (prefs.getBool("seasonal") ?? true) {
switch (DateTime.now().month) {
case 12:
// December, snow season!
setState(() {
_snowing = true;
});
// who knows what else might be in the future?
}
}
}

void _flashHazards(int times) async {
Expand Down Expand Up @@ -79,9 +96,17 @@ class _HomeScreenState extends State<HomeScreen> {
alignment: Alignment.center,
children: [
StateCircle(
scanning: _scanning,
connected: _connected,
scooterState: _state),
connected: _connected,
scooterState: _state,
scanning: _scanning,
),
if (_snowing)
SnowfallBackground(
backgroundColor: Colors.transparent,
snowflakeColor: context.isDarkMode
? Colors.white.withOpacity(0.15)
: Colors.black.withOpacity(0.05),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(
Expand Down Expand Up @@ -184,6 +209,7 @@ class _HomeScreenState extends State<HomeScreen> {
width:
MediaQuery.of(context).size.width / 6,
child: LinearProgressIndicator(
backgroundColor: Colors.black26,
minHeight: 8,
borderRadius: BorderRadius.circular(8),
value: data.primarySOC! / 100.0,
Expand Down Expand Up @@ -241,13 +267,15 @@ class _HomeScreenState extends State<HomeScreen> {
const SizedBox(height: 16),
Expanded(
child: ScooterVisual(
color: context.select<ScooterService, int?>(
(service) => service.scooterColor) ??
1,
state: _state,
scanning: _scanning,
blinkerLeft: _hazards,
blinkerRight: _hazards),
color: context.select<ScooterService, int?>(
(service) => service.scooterColor) ??
1,
state: _state,
scanning: _scanning,
blinkerLeft: _hazards,
blinkerRight: _hazards,
winter: _snowing,
),
),
const SizedBox(height: 16),
Row(
Expand Down
Loading

0 comments on commit bf07ee5

Please sign in to comment.