fix(todo,ui): Today's day centred in its calendar, and the way back to today shows it
Today's tab drew its day centred at 16 of the calendar's 24 units, where Lucide's SVG has its body's middle; its font draws the calendar a unit higher (the top bar's stroke from 8 to 10, the foot's from 20 to 22, measured with the real fonts), so the digits sat a unit and a half low. halkyon_ui's new DayCalendarIcon centres them at 15, in Noto Sans set explicitly, and its tests draw it with the real fonts at 16 to 32 pixels: the digits centred in the body within half a unit, and 10, 20, 28 and 31 clear of the sides. Todo's TodayIcon keeps the midnight redraw around it. The agenda's, the 3-day grid's and the month's way back to today showed Lucide's calendar-1; it shows today's day in the same calendar now, as Todoist's. Whats-New: Today's date sits centred in its calendar icon, and the button back to today shows it too. Whats-New-De: Das heutige Datum steht mittig in seinem Kalendersymbol, und der Knopf zurück zu heute zeigt es auch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
30ee2a9ca3
commit
28e07dbf9d
6 changed files with 249 additions and 74 deletions
|
|
@ -87,7 +87,7 @@ class _MonthGridState() extends State<MonthGrid> {
|
|||
if (month != thisMonth)
|
||||
IconButton(
|
||||
tooltip: l10n.weekToday,
|
||||
icon: const Icon(LucideIcons.calendar1),
|
||||
icon: DayCalendarIcon(day: today.day),
|
||||
color: theme.colorScheme.primary,
|
||||
onPressed: () => go(today),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ class _HourGridState() extends State<HourGrid> {
|
|||
if (start != today)
|
||||
IconButton(
|
||||
tooltip: l10n.weekToday,
|
||||
icon: const Icon(LucideIcons.calendar1),
|
||||
icon: DayCalendarIcon(day: today.day),
|
||||
color: theme.colorScheme.primary,
|
||||
onPressed: () => _go(today),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,19 +1,13 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Today's tab icon (the developer's review, 3 Nov 2026, as Todoist's): a
|
||||
/// blank calendar with today's day of the month in it, as Lucide's
|
||||
/// `calendar-1` holds a 1, drawn anew at midnight.
|
||||
/// Today's icon (the developer's review, 3 Nov 2026, as Todoist's):
|
||||
/// halkyon_ui's [DayCalendarIcon] with today's day of the month in it, drawn
|
||||
/// anew at midnight; Today's tab and the way back to today show it.
|
||||
class const TodayIcon({super.key}) extends StatefulWidget {
|
||||
/// The day's size, in the calendar's 24 units.
|
||||
static const _fontSize = 9.6;
|
||||
|
||||
/// Noto Sans' digits' height, of the font's size.
|
||||
static const _digitHeight = 0.714;
|
||||
|
||||
@override
|
||||
State<TodayIcon> createState() => _TodayIconState();
|
||||
}
|
||||
|
|
@ -46,42 +40,5 @@ class _TodayIconState() extends State<TodayIcon> {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final icon = IconTheme.of(context);
|
||||
final size = icon.size ?? 24;
|
||||
return SizedBox.square(
|
||||
dimension: size,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const Icon(LucideIcons.calendar),
|
||||
// Lucide's calendar: inside its strokes from 11 to 21 of 24 units.
|
||||
// Placed by its baseline, a line box's place in it being the font's
|
||||
// to choose (the day stood on the frame, 5 Nov 2026).
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Baseline(
|
||||
baseline:
|
||||
size *
|
||||
(16 + TodayIcon._digitHeight * TodayIcon._fontSize / 2) /
|
||||
24,
|
||||
baselineType: TextBaseline.alphabetic,
|
||||
child: Text(
|
||||
'${clock.now().day}',
|
||||
textScaler: TextScaler.noScaling,
|
||||
style: TextStyle(
|
||||
color: icon.color,
|
||||
fontSize: size * TodayIcon._fontSize / 24,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget build(BuildContext context) => DayCalendarIcon(day: clock.now().day);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:halkyon_todo_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/bloc/todo_cubit.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/task.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
|
@ -146,7 +147,7 @@ class _WeekStripState() extends State<WeekStrip> {
|
|||
if (selected != today)
|
||||
IconButton(
|
||||
tooltip: l10n.weekToday,
|
||||
icon: const Icon(LucideIcons.calendar1),
|
||||
icon: DayCalendarIcon(day: today.day),
|
||||
color: scheme.primary,
|
||||
onPressed: () => widget.onSelect(today),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1637,6 +1637,13 @@ void main() {
|
|||
await tester.tap(find.byTooltip('Following month'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(MonthGrid.chipKey(id, today)), findsNothing);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byTooltip('Back to today'),
|
||||
matching: find.byType(DayCalendarIcon),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.tap(find.byTooltip('Back to today'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
|
|
@ -1759,6 +1766,13 @@ void main() {
|
|||
await tester.tap(later);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('Back to today'), findsOneWidget);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byTooltip('Back to today'),
|
||||
matching: find.byType(DayCalendarIcon),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(tester.getTopLeft(later), atToday);
|
||||
|
||||
await tester.tap(find.byTooltip('Back to today'));
|
||||
|
|
@ -5192,6 +5206,19 @@ void main() {
|
|||
await tester.tap(find.byKey(WeekStrip.dayKey(today.plus(1))));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('Back to today'), findsOneWidget);
|
||||
// Today's day in a calendar, as Today's tab shows it (the
|
||||
// developer's review, 7 Nov 2026).
|
||||
expect(
|
||||
tester
|
||||
.widget<DayCalendarIcon>(
|
||||
find.descendant(
|
||||
of: find.byTooltip('Back to today'),
|
||||
matching: find.byType(DayCalendarIcon),
|
||||
),
|
||||
)
|
||||
.day,
|
||||
today.day,
|
||||
);
|
||||
await tester.tap(find.byTooltip('Back to today'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('Back to today'), findsNothing);
|
||||
|
|
|
|||
|
|
@ -1,36 +1,27 @@
|
|||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_todo_flutter/src/tabs/today_icon.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets("the day's digits stand centred below the calendar's line, "
|
||||
"whatever the font's line box (the developer's review, 5 Nov 2026)", (
|
||||
testWidgets("today's day of the month, in halkyon_ui's calendar, whose "
|
||||
"digits halkyon_ui places (the developer's review, 7 Nov 2026)", (
|
||||
tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
const Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: IconTheme(
|
||||
data: IconThemeData(size: 24),
|
||||
await withClock(Clock.fixed(DateTime(2026, 11, 28, 9)), () async {
|
||||
await tester.pumpWidget(
|
||||
const Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Center(child: TodayIcon()),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
expect(
|
||||
tester.widget<DayCalendarIcon>(find.byType(DayCalendarIcon)).day,
|
||||
28,
|
||||
);
|
||||
|
||||
final icon = tester.getTopLeft(find.byType(TodayIcon));
|
||||
final day = find.text('${clock.now().day}');
|
||||
final measured = TextPainter(
|
||||
text: TextSpan(text: '5', style: tester.widget<Text>(day).style),
|
||||
textDirection: TextDirection.ltr,
|
||||
)..layout();
|
||||
addTearDown(measured.dispose);
|
||||
final baseline =
|
||||
tester.getTopLeft(day).dy +
|
||||
measured.computeDistanceToActualBaseline(TextBaseline.alphabetic) -
|
||||
icon.dy;
|
||||
|
||||
// The digits, 0.714 of 9.6 units high, between the strokes at 11 and 21.
|
||||
expect(baseline, moreOrLessEquals(19.43, epsilon: 0.01));
|
||||
expect(find.text('28'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue