Add new friends system, and sharing legs support
All checks were successful
Release / meta (push) Successful in 9s
Release / linux-build (push) Successful in 6m37s
Release / web-build (push) Successful in 5m29s
Release / android-build (push) Successful in 15m58s
Release / release-master (push) Successful in 20s
Release / release-dev (push) Successful in 26s

This commit is contained in:
2026-01-03 01:07:08 +00:00
parent 42af39b442
commit 89b760508d
19 changed files with 2832 additions and 712 deletions

View File

@@ -27,15 +27,20 @@ class _LegCardState extends State<LegCard> {
@override
Widget build(BuildContext context) {
final leg = widget.leg;
final isShared = leg.legShareId != null && leg.legShareId!.isNotEmpty;
final distanceUnits = context.watch<DistanceUnitService>();
final routeSegments = _parseRouteSegments(leg.route);
final textTheme = Theme.of(context).textTheme;
return Card(
child: ExpansionTile(
onExpansionChanged: (v) => setState(() => _expanded = v),
tilePadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
leading: const Icon(Icons.train),
title: LayoutBuilder(
clipBehavior: Clip.antiAlias,
elevation: 1,
child: Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
onExpansionChanged: (v) => setState(() => _expanded = v),
tilePadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
leading: const Icon(Icons.train),
title: LayoutBuilder(
builder: (context, constraints) {
final isWide = constraints.maxWidth > 520;
final beginTimeWidget = _timeWithDelay(
@@ -108,7 +113,7 @@ class _LegCardState extends State<LegCard> {
);
},
),
subtitle: LayoutBuilder(
subtitle: LayoutBuilder(
builder: (context, constraints) {
final isWide = constraints.maxWidth > 520;
final tractionWrap = !_expanded && leg.locos.isNotEmpty
@@ -168,7 +173,7 @@ class _LegCardState extends State<LegCard> {
);
},
),
trailing: Row(
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Column(
@@ -193,6 +198,17 @@ class _LegCardState extends State<LegCard> {
],
],
),
if (isShared) ...[
const SizedBox(width: 8),
Tooltip(
message: 'Shared entry',
child: Icon(
Icons.share,
size: 18,
color: Theme.of(context).colorScheme.primary,
),
),
],
if (widget.showEditButton) ...[
const SizedBox(width: 8),
IconButton(
@@ -217,44 +233,45 @@ class _LegCardState extends State<LegCard> {
],
],
],
),
children: [
Padding(
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,
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),
],
],
),
),
],
children: [
Padding(
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,
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),
],
],
),
),
],
),
),
);
}