Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions lib/features/data/presentation/pages/data_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/// weather observation rankings, …).
library;

import 'dart:math' as math;

import 'package:dpip/app/theme/app_radius.dart';
import 'package:dpip/app/theme/app_spacing.dart';
import 'package:dpip/l10n/gen/app_localizations.dart';
Expand Down Expand Up @@ -73,8 +75,9 @@ class DataPage extends StatelessWidget {
),
),
SectionHeader(l10n.dataSectionWeather),
GridView.count(
crossAxisCount: 2,
// Wide and short: icon left, label right, one glance per tile.
GridView(
gridDelegate: _rankingGrid(context),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.fromLTRB(
Expand All @@ -83,10 +86,6 @@ class DataPage extends StatelessWidget {
AppSpacing.lg,
AppSpacing.sm,
),
crossAxisSpacing: AppSpacing.sm,
mainAxisSpacing: AppSpacing.sm,
// Wide and short: icon left, label right, one glance per tile.
childAspectRatio: 2.4,
children: [
for (final (tab, icon) in _weatherRankingEntries)
_RankingGridTile(
Expand All @@ -105,8 +104,8 @@ class DataPage extends StatelessWidget {
],
),
SectionHeader(l10n.dataSectionAstronomy),
GridView.count(
crossAxisCount: 2,
GridView(
gridDelegate: _rankingGrid(context),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.fromLTRB(
Expand All @@ -115,9 +114,6 @@ class DataPage extends StatelessWidget {
AppSpacing.lg,
AppSpacing.sm,
),
crossAxisSpacing: AppSpacing.sm,
mainAxisSpacing: AppSpacing.sm,
childAspectRatio: 2.4,
children: [
for (final (route, icon, label, accent)
in <(String, IconData, String, Color)>[
Expand Down Expand Up @@ -240,6 +236,34 @@ class _SeismicCard extends StatelessWidget {
}
}

/// The ranking tiles' geometry, shared by both grids so 氣象 and 天文 stay the
/// same shape.
///
/// Width-driven, not count-driven: two columns on a phone, four on a tablet,
/// and a tile of the same size either way. `crossAxisCount: 2` with a
/// `childAspectRatio` tied the tile's *height* to the screen's width — on a
/// 1366 pt iPad the two columns are 668 pt wide, so every tile came out 278 pt
/// tall and its single line of label floated in the middle of a sea of tonal
/// grey.
///
/// The height is stated outright instead, and follows the text scale rather
/// than the window: the tile holds a 34 pt icon badge beside a label of at most
/// two lines, so that is what it is tall enough for at any text size. The 80
/// floor is the height a phone drew before this, kept so the phone layout is
/// untouched.
SliverGridDelegate _rankingGrid(BuildContext context) {
const twoLabelLines = 44.0;
return SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 340,
crossAxisSpacing: AppSpacing.sm,
mainAxisSpacing: AppSpacing.sm,
mainAxisExtent: math.max(
80,
AppSpacing.md * 2 + MediaQuery.textScalerOf(context).scale(twoLabelLines),
),
);
}

/// A metric card in a grid — tonal surface, leading icon badge, label, and a
/// forward affordance.
///
Expand Down
27 changes: 19 additions & 8 deletions lib/features/earthquake/presentation/pages/report_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,13 @@ class _DaySection extends StatelessWidget {
),
child: Row(
children: [
Text(
_dayLabel(day, l10n, locale),
style: theme.textTheme.titleSmall?.copyWith(
color: colors.primary,
fontWeight: FontWeight.w700,
Flexible(
child: Text(
_dayLabel(day, l10n, locale),
style: theme.textTheme.titleSmall?.copyWith(
color: colors.primary,
fontWeight: FontWeight.w700,
),
),
),
const SizedBox(width: AppSpacing.sm),
Expand Down Expand Up @@ -302,9 +304,17 @@ class _DaySection extends StatelessWidget {

static String _dayLabel(DateTime day, AppLocalizations l10n, String locale) {
final today = taipeiCalendarDay(AppTime.utc);
if (day == today) return l10n.reportListToday;
if (day == today.subtract(const Duration(days: 1))) {
return l10n.reportListYesterday;
String? relative;
if (day == today) {
relative = l10n.reportListToday;
} else if (day == today.subtract(const Duration(days: 1))) {
relative = l10n.reportListYesterday;
}
if (relative != null) {
final date = _relativeDayFormats
.putIfAbsent(locale, () => DateFormat.yMMMd(locale))
.format(day);
return '$relative ($date)';
}
// Parsing a locale's pattern is not free — memoised per locale.
return _dayFormats
Expand All @@ -313,6 +323,7 @@ class _DaySection extends StatelessWidget {
}

static final Map<String, DateFormat> _dayFormats = {};
static final Map<String, DateFormat> _relativeDayFormats = {};
}

class _ReportTile extends StatelessWidget {
Expand Down
13 changes: 11 additions & 2 deletions lib/features/earthquake/presentation/pages/report_replay_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -942,9 +942,13 @@ class _ReplayMapState extends State<_ReplayMap> {
countyFillLayerId,
FillLayerProperties(fillColor: baseFill, fillOpacity: 1),
);
// Back to the baked default. This layer is the wash and nothing else:
// with no alert up it paints nothing, so the OSM detailed ground —
// which mounts directly beneath it — keeps showing. The grey island is
// [countyFillLayerId]'s job, restored just above.
await controller.setLayerProperties(
townFillLayerId,
FillLayerProperties(fillColor: baseFill, fillOpacity: 1),
const FillLayerProperties(fillColor: '#00000000', fillOpacity: 0),
);
return;
}
Expand Down Expand Up @@ -980,7 +984,12 @@ class _ReplayMapState extends State<_ReplayMap> {
'match',
['get', 'CODE'],
...entries,
baseFill,
// Transparent, not the palette grey: a township the estimate puts
// at 0 has to leave whatever is under it showing — the OSM
// detailed ground when that layer is on, the grey `land` fill when
// it is not. Falling back to grey painted a flat sheet over the
// detailed map everywhere the shaking was 0.
'rgba(0, 0, 0, 0)',
],
fillOpacity: 1,
),
Expand Down
Loading
Loading