From af37e25692bca7027b4b2031ebe8c2da141a8b5b Mon Sep 17 00:00:00 2001 From: Pete Gregory Date: Sat, 3 Jan 2026 23:26:33 +0000 Subject: [PATCH] fix saving draft with shared user, display user shared to/from in expanded leg card --- .gitea/workflows/release.yml | 1 + lib/components/legs/leg_card.dart | 74 +++++++++++++------ .../pages/new_entry/new_entry_page.dart | 13 ++-- lib/components/pages/traction/traction.dart | 1 + .../pages/traction/traction_page.dart | 41 +++++----- 5 files changed, 83 insertions(+), 47 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 42ddc4b..191b44e 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -294,6 +294,7 @@ jobs: tags: | type=sha,prefix= type=raw,value=${{ needs.meta.outputs.base_version }}${{ needs.meta.outputs.dev_suffix }} + type=raw,value=dev - name: Login to the docker registry uses: docker/login-action@v3 diff --git a/lib/components/legs/leg_card.dart b/lib/components/legs/leg_card.dart index 4227753..55257ad 100644 --- a/lib/components/legs/leg_card.dart +++ b/lib/components/legs/leg_card.dart @@ -234,34 +234,62 @@ class _LegCardState extends State { padding: const EdgeInsets.fromLTRB(16, 0, 16, 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (leg.notes.isNotEmpty) ...[ - Text('Notes', style: textTheme.titleSmall), - const SizedBox(height: 4), - Text(leg.notes), - const SizedBox(height: 12), - ], - if (leg.locos.isNotEmpty) ...[ - Text('Locos', style: textTheme.titleSmall), - const SizedBox(height: 6), - Wrap( - spacing: 8, + children: [ + if (leg.notes.isNotEmpty) ...[ + Text('Notes', style: textTheme.titleSmall), + const SizedBox(height: 4), + Text(leg.notes), + const SizedBox(height: 12), + ], + if (leg.locos.isNotEmpty) ...[ + Text('Locos', style: textTheme.titleSmall), + const SizedBox(height: 6), + Wrap( + spacing: 8, runSpacing: 8, children: _buildLocoChips(context, leg), ), const SizedBox(height: 12), ], - if (_hasTrainDetails(leg)) ...[ - Text('Train', style: textTheme.titleSmall), - const SizedBox(height: 6), - ..._buildTrainDetails(leg, textTheme), - const SizedBox(height: 12), - ], - if (routeSegments.isNotEmpty) ...[ - Text('Route', style: textTheme.titleSmall), - const SizedBox(height: 6), - _buildRouteList(routeSegments), - ], + if (_hasTrainDetails(leg)) ...[ + Text('Train', style: textTheme.titleSmall), + const SizedBox(height: 6), + ..._buildTrainDetails(leg, textTheme), + const SizedBox(height: 12), + ], + if (sharedFrom != null) + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text( + 'Shared from ${sharedFrom.sharedFromDisplay.isNotEmpty ? sharedFrom.sharedFromDisplay : 'another user'}.', + style: textTheme.bodyMedium, + ), + ), + if (sharedTo.isNotEmpty) ...[ + Text( + 'Shared to:', + style: textTheme.bodyMedium, + ), + const SizedBox(height: 4), + Wrap( + spacing: 8, + runSpacing: 4, + children: sharedTo + .map((s) => Chip( + label: Text(s.sharedToDisplay.isNotEmpty + ? s.sharedToDisplay + : s.sharedToUserId), + visualDensity: VisualDensity.compact, + )) + .toList(), + ), + const SizedBox(height: 12), + ], + if (routeSegments.isNotEmpty) ...[ + Text('Route', style: textTheme.titleSmall), + const SizedBox(height: 6), + _buildRouteList(routeSegments), + ], ], ), ), diff --git a/lib/components/pages/new_entry/new_entry_page.dart b/lib/components/pages/new_entry/new_entry_page.dart index 3957731..0ce84f0 100644 --- a/lib/components/pages/new_entry/new_entry_page.dart +++ b/lib/components/pages/new_entry/new_entry_page.dart @@ -707,7 +707,7 @@ class _NewEntryPageState extends State { final enabled = value ?? false; setState(() { _matchDestinationToEntry = enabled; - if (enabled) _hasDestinationTime = true; + if (enabled && _hasEndTime) _hasDestinationTime = true; }); _scheduleMatchUpdate(); _saveDraft(); @@ -1127,7 +1127,7 @@ class _NewEntryPageState extends State { if (_destinationController.text != endVal) { _destinationController.text = endVal; } - if (_hasDestinationTime) { + if (_hasDestinationTime && _hasEndTime) { final endTime = _legEndDateTime ?? _legDateTime; _selectedDestinationDate = DateTime( endTime.year, @@ -1283,9 +1283,9 @@ class _NewEntryPageState extends State { const SizedBox(height: 8), _buildSharedBanner(), ], - _buildTripSelector(context), - const SizedBox(height: 12), - if (_activeLegShare == null) _buildShareSection(context), + _buildTripSelector(context), + const SizedBox(height: 8), + if (_activeLegShare == null) _buildShareSection(context), _dateTimeGroup( context, title: 'Departure time', @@ -1366,6 +1366,7 @@ class _NewEntryPageState extends State { border: OutlineInputBorder(), ), ), + const Divider(height: 24), _trainLocationBlock( label: 'Origin', controller: _originController, @@ -1384,6 +1385,7 @@ class _NewEntryPageState extends State { singleColumn: true, ), ), + const Divider(height: 24), _trainLocationBlock( label: 'Destination', controller: _destinationController, @@ -1403,6 +1405,7 @@ class _NewEntryPageState extends State { singleColumn: true, ), ), + const Divider(height: 24), TextFormField( controller: _networkController, textCapitalization: TextCapitalization.characters, diff --git a/lib/components/pages/traction/traction.dart b/lib/components/pages/traction/traction.dart index 939ce6f..955d720 100644 --- a/lib/components/pages/traction/traction.dart +++ b/lib/components/pages/traction/traction.dart @@ -7,6 +7,7 @@ import 'package:mileograph_flutter/components/traction/traction_card.dart'; import 'package:mileograph_flutter/objects/objects.dart'; import 'package:mileograph_flutter/services/data_service.dart'; import 'package:mileograph_flutter/services/distance_unit_service.dart'; +import 'package:mileograph_flutter/services/authservice.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/lib/components/pages/traction/traction_page.dart b/lib/components/pages/traction/traction_page.dart index bc35275..0d149f3 100644 --- a/lib/components/pages/traction/traction_page.dart +++ b/lib/components/pages/traction/traction_page.dart @@ -569,6 +569,7 @@ class _TractionPageState extends State { } Widget _buildHeaderActions(BuildContext context, bool isMobile) { + final isElevated = context.read().isElevated; final refreshButton = IconButton( tooltip: 'Refresh', onPressed: _refreshTraction, @@ -587,32 +588,34 @@ class _TractionPageState extends State { ), ); - final newTractionButton = FilledButton.icon( - onPressed: () async { - final createdClass = await context.push( - '/traction/new', - ); - if (!mounted) return; - if (createdClass != null && createdClass.isNotEmpty) { - _classController.text = createdClass; - _selectedClass = createdClass; - _refreshTraction(); - } else if (createdClass == '') { - _refreshTraction(); - } - }, - icon: const Icon(Icons.add), - label: const Text('New Traction'), - ); + final newTractionButton = !isElevated + ? null + : FilledButton.icon( + onPressed: () async { + final createdClass = await context.push( + '/traction/new', + ); + if (!mounted) return; + if (createdClass != null && createdClass.isNotEmpty) { + _classController.text = createdClass; + _selectedClass = createdClass; + _refreshTraction(); + } else if (createdClass == '') { + _refreshTraction(); + } + }, + icon: const Icon(Icons.add), + label: const Text('New Traction'), + ); final desktopActions = [ refreshButton, if (classStatsButton != null) classStatsButton, - newTractionButton, + if (newTractionButton != null) newTractionButton, ]; final mobileActions = [ - newTractionButton, + if (newTractionButton != null) newTractionButton, if (classStatsButton != null) classStatsButton, refreshButton, ];