fix saving draft with shared user, display user shared to/from in expanded leg card
All checks were successful
Release / meta (push) Successful in 6s
Release / linux-build (push) Successful in 58s
Release / web-build (push) Successful in 2m0s
Release / android-build (push) Successful in 9m58s
Release / release-master (push) Successful in 37s
Release / release-dev (push) Successful in 44s

This commit is contained in:
2026-01-03 23:26:33 +00:00
parent 1689869ce5
commit af37e25692
5 changed files with 83 additions and 47 deletions

View File

@@ -234,34 +234,62 @@ class _LegCardState extends State<LegCard> {
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),
],
],
),
),

View File

@@ -707,7 +707,7 @@ class _NewEntryPageState extends State<NewEntryPage> {
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<NewEntryPage> {
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<NewEntryPage> {
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<NewEntryPage> {
border: OutlineInputBorder(),
),
),
const Divider(height: 24),
_trainLocationBlock(
label: 'Origin',
controller: _originController,
@@ -1384,6 +1385,7 @@ class _NewEntryPageState extends State<NewEntryPage> {
singleColumn: true,
),
),
const Divider(height: 24),
_trainLocationBlock(
label: 'Destination',
controller: _destinationController,
@@ -1403,6 +1405,7 @@ class _NewEntryPageState extends State<NewEntryPage> {
singleColumn: true,
),
),
const Divider(height: 24),
TextFormField(
controller: _networkController,
textCapitalization: TextCapitalization.characters,

View File

@@ -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';

View File

@@ -569,6 +569,7 @@ class _TractionPageState extends State<TractionPage> {
}
Widget _buildHeaderActions(BuildContext context, bool isMobile) {
final isElevated = context.read<AuthService>().isElevated;
final refreshButton = IconButton(
tooltip: 'Refresh',
onPressed: _refreshTraction,
@@ -587,32 +588,34 @@ class _TractionPageState extends State<TractionPage> {
),
);
final newTractionButton = FilledButton.icon(
onPressed: () async {
final createdClass = await context.push<String>(
'/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<String>(
'/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,
];