timetable performance optimization
This commit is contained in:
@@ -1,16 +1,14 @@
|
||||
part of '../custom_workweek_calendar.dart';
|
||||
|
||||
class _OutsideHoursStrip extends StatelessWidget {
|
||||
final DateTime weekStart;
|
||||
final List<Appointment> appointments;
|
||||
final List<List<Appointment>> outside;
|
||||
final double rulerWidth;
|
||||
final void Function(Appointment) onAppointmentTap;
|
||||
final bool Function(Appointment) isCrossedOut;
|
||||
|
||||
const _OutsideHoursStrip({
|
||||
super.key,
|
||||
required this.weekStart,
|
||||
required this.appointments,
|
||||
required this.outside,
|
||||
required this.rulerWidth,
|
||||
required this.onAppointmentTap,
|
||||
required this.isCrossedOut,
|
||||
@@ -18,10 +16,6 @@ class _OutsideHoursStrip extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final outside = partitionAppointmentsForWeek(
|
||||
appointments,
|
||||
weekStart,
|
||||
).outside;
|
||||
if (outside.every((day) => day.isEmpty)) return const SizedBox.shrink();
|
||||
|
||||
final theme = Theme.of(context);
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
part of '../custom_workweek_calendar.dart';
|
||||
|
||||
/// Per-week derived data, computed once per appointment/region set instead of
|
||||
/// on every rebuild of a week page.
|
||||
class _WeekData {
|
||||
final List<List<Appointment>> inside;
|
||||
final List<List<Appointment>> outside;
|
||||
final List<List<BoundRegion>> regions;
|
||||
|
||||
_WeekData._(this.inside, this.outside, this.regions);
|
||||
|
||||
factory _WeekData.compute(
|
||||
DateTime weekStart,
|
||||
List<Appointment> appointments,
|
||||
List<TimeRegion> timeRegions,
|
||||
) {
|
||||
final partitioned = partitionAppointmentsForWeek(appointments, weekStart);
|
||||
return _WeekData._(partitioned.inside, partitioned.outside, [
|
||||
for (var d = 0; d < 5; d++)
|
||||
expandRegionsForDay(timeRegions, weekStart.addDays(d)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
class _WeekGrid extends StatelessWidget {
|
||||
final DateTime weekStart;
|
||||
final LessonPeriodSchedule schedule;
|
||||
final List<Appointment> appointments;
|
||||
final List<TimeRegion> timeRegions;
|
||||
final _WeekData data;
|
||||
final void Function(Appointment) onAppointmentTap;
|
||||
final bool Function(Appointment) isCrossedOut;
|
||||
final void Function(DateTime start, DateTime end)? onCreateEvent;
|
||||
@@ -16,8 +37,7 @@ class _WeekGrid extends StatelessWidget {
|
||||
const _WeekGrid({
|
||||
required this.weekStart,
|
||||
required this.schedule,
|
||||
required this.appointments,
|
||||
required this.timeRegions,
|
||||
required this.data,
|
||||
required this.onAppointmentTap,
|
||||
required this.isCrossedOut,
|
||||
required this.onCreateEvent,
|
||||
@@ -29,8 +49,6 @@ class _WeekGrid extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final partitioned = partitionAppointmentsForWeek(appointments, weekStart);
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
@@ -48,8 +66,8 @@ class _WeekGrid extends StatelessWidget {
|
||||
child: _DayColumn(
|
||||
date: weekStart.addDays(d),
|
||||
schedule: schedule,
|
||||
appointments: partitioned.inside[d],
|
||||
timeRegions: timeRegions,
|
||||
appointments: data.inside[d],
|
||||
regions: data.regions[d],
|
||||
layout: layout,
|
||||
today: today,
|
||||
nowNotifier: nowNotifier,
|
||||
@@ -195,7 +213,7 @@ class _DayColumn extends StatelessWidget {
|
||||
final DateTime date;
|
||||
final LessonPeriodSchedule schedule;
|
||||
final List<Appointment> appointments;
|
||||
final List<TimeRegion> timeRegions;
|
||||
final List<BoundRegion> regions;
|
||||
final PeriodLayout layout;
|
||||
final DateTime today;
|
||||
final ValueListenable<DateTime> nowNotifier;
|
||||
@@ -207,7 +225,7 @@ class _DayColumn extends StatelessWidget {
|
||||
required this.date,
|
||||
required this.schedule,
|
||||
required this.appointments,
|
||||
required this.timeRegions,
|
||||
required this.regions,
|
||||
required this.layout,
|
||||
required this.today,
|
||||
required this.nowNotifier,
|
||||
@@ -280,12 +298,10 @@ class _DayColumn extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final dayAppointments = appointments;
|
||||
final dayRegions = expandRegionsForDay(timeRegions, date);
|
||||
final isToday = date.isSameDay(today);
|
||||
|
||||
final isTablet = MediaQuery.of(context).size.shortestSide >= 600;
|
||||
final laidOut = assignLanes(dayAppointments, maxLanes: isTablet ? 3 : 2);
|
||||
final isTablet = MediaQuery.sizeOf(context).shortestSide >= 600;
|
||||
final laidOut = assignLanes(appointments, maxLanes: isTablet ? 3 : 2);
|
||||
|
||||
final dayName = DateFormat(
|
||||
'EEEE',
|
||||
@@ -304,8 +320,7 @@ class _DayColumn extends StatelessWidget {
|
||||
sortKey: OrdinalSortKey(date.weekday.toDouble()),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onLongPressStart: (details) =>
|
||||
_handleLongPress(details, dayAppointments),
|
||||
onLongPressStart: (details) => _handleLongPress(details, appointments),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: isToday ? theme.colorScheme.primary.withAlpha(14) : null,
|
||||
@@ -342,7 +357,7 @@ class _DayColumn extends StatelessWidget {
|
||||
color: theme.dividerColor.withAlpha(60),
|
||||
),
|
||||
),
|
||||
for (final region in dayRegions)
|
||||
for (final region in regions)
|
||||
Positioned(
|
||||
top: layout.yOfDateTime(region.start),
|
||||
height:
|
||||
@@ -379,6 +394,7 @@ class _DayColumn extends StatelessWidget {
|
||||
onTap: () => onAppointmentTap(appointment),
|
||||
child: AppointmentTile(
|
||||
appointment: appointment,
|
||||
now: nowNotifier,
|
||||
crossedOut: isCrossedOut(appointment),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user