aves/lib/widgets/map/address_row.dart
Thibault Deckers 7b9213e82e fixes, upgrades
2023-10-22 23:51:05 +03:00

111 lines
3.5 KiB
Dart

import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/entry/extensions/location.dart';
import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/services/geocoding_service.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/theme/styles.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
import 'info_row.dart';
class MapAddressRow extends StatefulWidget {
final AvesEntry? entry;
const MapAddressRow({
super.key,
required this.entry,
});
@override
State<MapAddressRow> createState() => _MapAddressRowState();
}
class _MapAddressRowState extends State<MapAddressRow> {
final ValueNotifier<String?> _addressLineNotifier = ValueNotifier(null);
@override
void initState() {
super.initState();
_updateAddress();
}
@override
void didUpdateWidget(covariant MapAddressRow oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.entry != widget.entry) {
_updateAddress();
}
}
@override
void dispose() {
_addressLineNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
return Container(
alignment: AlignmentDirectional.centerStart,
// addresses can include non-latin scripts with inconsistent line height,
// which is especially an issue for relayout/painting of heavy Google map,
// so we give extra height to give breathing room to the text and stabilize layout
height: Theme.of(context).textTheme.bodyMedium!.fontSize! * textScaleFactor * 2,
child: ValueListenableBuilder<String?>(
valueListenable: _addressLineNotifier,
builder: (context, addressLine, child) {
final entry = widget.entry;
final location = addressLine ??
(entry == null
? AText.valueNotAvailable
: entry.hasAddress
? entry.shortAddress
: settings.coordinateFormat.format(context.l10n, entry.latLng!));
return Text.rich(
TextSpan(
children: [
WidgetSpan(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: MapInfoRow.iconPadding),
child: Icon(AIcons.location, size: MapInfoRow.getIconSize(context)),
),
alignment: PlaceholderAlignment.middle,
),
TextSpan(text: location),
],
),
strutStyle: AStyles.overflowStrut,
softWrap: false,
overflow: TextOverflow.fade,
maxLines: 1,
);
},
),
);
}
Future<void> _updateAddress() async {
final entry = widget.entry;
final addressLine = await _getAddressLine(entry);
if (!mounted) return;
if (entry == widget.entry) {
_addressLineNotifier.value = addressLine;
}
}
Future<String?> _getAddressLine(AvesEntry? entry) async {
if (entry != null && await availability.canLocatePlaces) {
final addresses = await GeocodingService.getAddress(entry.latLng!, settings.appliedLocale);
if (addresses.isNotEmpty) {
final address = addresses.first;
return address.addressLine;
}
}
return null;
}
}