feat(calendar): scroll to selected date when switching from calendar to schedule view

This commit is contained in:
Jagandeep Brar
2022-09-28 01:28:16 -04:00
parent ee91085b07
commit f1226e5638
6 changed files with 71 additions and 75 deletions

View File

@@ -1,8 +1,11 @@
import 'package:lunasea/database/tables/dashboard.dart';
import 'package:lunasea/extensions/datetime.dart';
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_size.dart';
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_type.dart';
import 'package:lunasea/modules/dashboard/core/api/api.dart';
import 'package:lunasea/modules/dashboard/core/api/data/abstract.dart';
import 'package:lunasea/state/state.dart';
import 'package:lunasea/vendor.dart';
class ModuleState extends LunaModuleState {
ModuleState() {
@@ -16,11 +19,19 @@ class ModuleState extends LunaModuleState {
resetUpcoming();
}
CalendarStartingType _calendarStartingType =
CalendarStartingType _calendarType =
DashboardDatabase.CALENDAR_STARTING_TYPE.read();
CalendarStartingType get calendarStartingType => _calendarStartingType;
set calendarStartingType(CalendarStartingType calendarStartingType) {
_calendarStartingType = calendarStartingType;
CalendarStartingType get calendarType => _calendarType;
set calendarType(CalendarStartingType calendarStartingType) {
_calendarType = calendarStartingType;
notifyListeners();
}
CalendarFormat _calendarFormat =
DashboardDatabase.CALENDAR_STARTING_SIZE.read().data;
CalendarFormat get calendarFormat => _calendarFormat;
set calendarFormat(CalendarFormat calendarFormat) {
_calendarFormat = calendarFormat;
notifyListeners();
}
@@ -31,10 +42,10 @@ class ModuleState extends LunaModuleState {
notifyListeners();
}
DateTime? _today;
DateTime? get today => _today;
DateTime _today = DateTime.now().floor();
DateTime get today => _today;
void resetToday() {
_today = DateTime.now();
_today = DateTime.now().floor();
notifyListeners();
}
@@ -44,4 +55,11 @@ class ModuleState extends LunaModuleState {
if (_api != null) _upcoming = _api!.getUpcoming(DateTime.now());
notifyListeners();
}
DateTime _selected = DateTime.now().floor();
DateTime get selected => _selected;
set selected(DateTime selected) {
_selected = selected;
notifyListeners();
}
}

View File

@@ -56,7 +56,7 @@ class _State extends State<CalendarPage>
snapshot.hasData) {
final events = snapshot.data!;
return Selector<ModuleState, CalendarStartingType>(
selector: (_, s) => s.calendarStartingType,
selector: (_, s) => s.calendarType,
builder: (context, type, _) {
if (type == CalendarStartingType.CALENDAR)
return CalendarView(events: events);

View File

@@ -5,7 +5,6 @@ import 'package:lunasea/database/box.dart';
import 'package:lunasea/database/tables/dashboard.dart';
import 'package:lunasea/extensions/datetime.dart';
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_day.dart';
import 'package:lunasea/modules/dashboard/core/adapters/calendar_starting_size.dart';
import 'package:lunasea/modules/dashboard/core/api/data/abstract.dart';
import 'package:lunasea/modules/dashboard/core/api/data/lidarr.dart';
import 'package:lunasea/modules/dashboard/core/api/data/radarr.dart';
@@ -30,26 +29,11 @@ class CalendarView extends StatefulWidget {
class _State extends State<CalendarView> {
final double _calendarBulletSize = 8.0;
List<CalendarData> _selectedEvents = [];
late DateTime _selected;
late CalendarFormat _calendarFormat;
late final TextStyle dayStyle = _getTextStyle(LunaColours.white);
late final TextStyle outsideStyle = _getTextStyle(LunaColours.white70);
late final TextStyle unavailableStyle = _getTextStyle(LunaColours.white10);
late final TextStyle weekdayStyle = _getTextStyle(LunaColours.accent);
@override
void initState() {
super.initState();
final size = DashboardDatabase.CALENDAR_STARTING_SIZE.read();
_selected = context.read<ModuleState>().today!.floor();
_selectedEvents = widget.events[_selected] ?? [];
_calendarFormat = size.data;
}
TextStyle _getTextStyle(Color color) {
return TextStyle(
color: color,
@@ -60,11 +44,7 @@ class _State extends State<CalendarView> {
void _onDaySelected(DateTime selected, DateTime focused) {
HapticFeedback.selectionClick();
if (mounted)
setState(() {
_selected = selected.floor();
_selectedEvents = widget.events[selected.floor()] ?? [];
});
context.read<ModuleState>().selected = selected.floor();
}
@override
@@ -128,10 +108,10 @@ class _State extends State<CalendarView> {
DashboardDatabase.CALENDAR_STARTING_SIZE,
],
builder: (context, _) {
DateTime firstDay = context.watch<ModuleState>().today!.subtract(
DateTime firstDay = context.watch<ModuleState>().today.subtract(
Duration(days: DashboardDatabase.CALENDAR_DAYS_PAST.read()),
);
DateTime lastDay = context.watch<ModuleState>().today!.add(
DateTime lastDay = context.watch<ModuleState>().today.add(
Duration(days: DashboardDatabase.CALENDAR_DAYS_FUTURE.read()),
);
return SafeArea(
@@ -144,7 +124,7 @@ class _State extends State<CalendarView> {
),
rowHeight: 48.0,
rangeSelectionMode: RangeSelectionMode.disabled,
focusedDay: _selected,
focusedDay: context.watch<ModuleState>().selected,
firstDay: firstDay,
lastDay: lastDay,
//events: widget.events,
@@ -161,8 +141,9 @@ class _State extends State<CalendarView> {
)),
startingDayOfWeek:
DashboardDatabase.CALENDAR_STARTING_DAY.read().data,
selectedDayPredicate: (date) =>
date.floor() == _selected.floor(),
selectedDayPredicate: (date) {
return date.floor() == context.read<ModuleState>().selected;
},
calendarStyle: CalendarStyle(
markersMaxCount: 1,
isTodayHighlighted: true,
@@ -188,8 +169,9 @@ class _State extends State<CalendarView> {
markersAlignment: Alignment.bottomCenter,
todayTextStyle: dayStyle,
),
onFormatChanged: (format) =>
setState(() => _calendarFormat = format),
onFormatChanged: (format) {
context.read<ModuleState>().calendarFormat = format;
},
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: weekdayStyle,
weekdayStyle: weekdayStyle,
@@ -198,7 +180,7 @@ class _State extends State<CalendarView> {
if (widget.events.isEmpty) return [];
return widget.events[date.floor()] ?? [];
},
calendarFormat: _calendarFormat,
calendarFormat: context.watch<ModuleState>().calendarFormat,
availableCalendarFormats: const {
CalendarFormat.month: 'Month',
CalendarFormat.twoWeeks: '2 Weeks',
@@ -246,7 +228,9 @@ class _State extends State<CalendarView> {
}
Widget _calendarList() {
if (_selectedEvents.isEmpty) {
final selected = context.read<ModuleState>().selected;
final events = widget.events[selected.floor()] ?? [];
if (events.isEmpty) {
return Expanded(
child: LunaListView(
controller: HomeNavigationBar.scrollControllers[1],
@@ -262,7 +246,7 @@ class _State extends State<CalendarView> {
return Expanded(
child: LunaListView(
controller: HomeNavigationBar.scrollControllers[1],
children: _selectedEvents.map(ContentBlock.new).toList(),
children: events.map(ContentBlock.new).toList(),
padding: MediaQuery.of(context).padding.copyWith(top: 0.0, bottom: 8.0),
),
);

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:lunasea/database/tables/dashboard.dart';
import 'package:lunasea/extensions/datetime.dart';
import 'package:lunasea/extensions/scroll_controller.dart';
import 'package:lunasea/vendor.dart';
@@ -24,14 +23,6 @@ class ScheduleView extends StatefulWidget {
class _State extends State<ScheduleView> {
final _formatter = DateFormat('EEEE / MMMM dd, y');
late DateTime _today;
@override
void initState() {
super.initState();
DateTime _floored = context.read<ModuleState>().today!.floor();
_today = _floored;
}
@override
Widget build(BuildContext context) {
@@ -65,19 +56,22 @@ class _State extends State<ScheduleView> {
Tuple2<List<Widget>, double> _buildSchedule() {
double offset = 0.0;
double offsetOfToday = 0.0;
double offsetOfSelected = 0.0;
List<Widget> days = [];
List<DateTime> keys = widget.events.keys.toList();
keys.sort();
for (final key in keys) {
bool pastDays = DashboardDatabase.CALENDAR_SHOW_PAST_DAYS.read();
bool dayInFuture = key.isAfter(_today.subtract(const Duration(days: 1)));
bool hasEvents = widget.events[key]?.isNotEmpty ?? false;
bool isToday = _today.isAtSameMomentAs(key);
final selected = context.read<ModuleState>().selected;
final today = context.read<ModuleState>().today;
if (isToday) {
offsetOfToday = offset;
bool pastDays = DashboardDatabase.CALENDAR_SHOW_PAST_DAYS.read();
bool dayInFuture = key.isAfter(today.subtract(const Duration(days: 1)));
bool hasEvents = widget.events[key]?.isNotEmpty ?? false;
bool isSelected = selected.isAtSameMomentAs(key);
if (isSelected) {
offsetOfSelected = offset;
}
if ((pastDays || dayInFuture) && hasEvents) {
@@ -87,14 +81,14 @@ class _State extends State<ScheduleView> {
}
}
return Tuple2(days, offsetOfToday);
return Tuple2(days, offsetOfSelected);
}
Tuple2<List<Widget>, double> _buildDay(DateTime day) {
List<CalendarData> events = widget.events[day]!;
final extent = LunaBlock.calculateItemExtent(3);
final offset = 39.0 + events.length * extent;
final offset = 39.30 + events.length * extent;
final slivers = [
SliverToBoxAdapter(
child: LunaHeader(text: _formatter.format(day)),

View File

@@ -45,7 +45,7 @@ class _State extends State<SwitchViewAction> with LunaLoadCallbackMixin {
@override
Widget build(BuildContext context) {
return Selector<ModuleState, CalendarStartingType>(
selector: (_, state) => state.calendarStartingType,
selector: (_, state) => state.calendarType,
builder: (context, view, _) {
if (_showButton) {
return LunaIconButton.appBar(
@@ -53,9 +53,9 @@ class _State extends State<SwitchViewAction> with LunaLoadCallbackMixin {
onPressed: () {
final state = context.read<ModuleState>();
if (view == CalendarStartingType.CALENDAR)
state.calendarStartingType = CalendarStartingType.SCHEDULE;
state.calendarType = CalendarStartingType.SCHEDULE;
else
state.calendarStartingType = CalendarStartingType.CALENDAR;
state.calendarType = CalendarStartingType.CALENDAR;
},
);
}

View File

@@ -4,7 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
class LunaTextStyle {
static TextStyle bodySmall() {
return GoogleFonts.robotoFlex(
height: 16.0, // md.sys.typescale.body-small.line-height
height: 1.33, // md.sys.typescale.body-small.line-height
fontSize: 12.0, // md.sys.typescale.body-small.size
fontWeight: FontWeight.w400, // md.sys.typescale.body-small.weight
);
@@ -12,7 +12,7 @@ class LunaTextStyle {
static TextStyle bodyMedium() {
return GoogleFonts.robotoFlex(
height: 20.0, // md.sys.typescale.body-medium.line-height
height: 1.43, // md.sys.typescale.body-medium.line-height
fontSize: 14.0, // md.sys.typescale.body-medium.size
fontWeight: FontWeight.w400, // md.sys.typescale.body-medium.weight
);
@@ -20,7 +20,7 @@ class LunaTextStyle {
static TextStyle bodyLarge() {
return GoogleFonts.robotoFlex(
height: 24.0, // md.sys.typescale.body-large.line-height
height: 1.50, // md.sys.typescale.body-large.line-height
fontSize: 16.0, // md.sys.typescale.body-large.size
fontWeight: FontWeight.w400, // md.sys.typescale.body-large.weight
);
@@ -28,7 +28,7 @@ class LunaTextStyle {
static TextStyle displaySmall() {
return GoogleFonts.robotoFlex(
height: 44.0, // md.sys.typescale.display-small.line-height
height: 1.22, // md.sys.typescale.display-small.line-height
fontSize: 36.0, // md.sys.typescale.display-small.size
fontWeight: FontWeight.w400, // md.sys.typescale.display-small.weight
);
@@ -36,7 +36,7 @@ class LunaTextStyle {
static TextStyle displayMedium() {
return GoogleFonts.robotoFlex(
height: 52.0, // md.sys.typescale.display-medium.line-height
height: 1.56, // md.sys.typescale.display-medium.line-height
fontSize: 45.0, // md.sys.typescale.display-medium.size
fontWeight: FontWeight.w400, // md.sys.typescale.display-medium.weight
);
@@ -44,7 +44,7 @@ class LunaTextStyle {
static TextStyle displayLarge() {
return GoogleFonts.robotoFlex(
height: 64.0, // md.sys.typescale.display-large.line-height
height: 1.23, // md.sys.typescale.display-large.line-height
fontSize: 57.0, // md.sys.typescale.display-large.size
fontWeight: FontWeight.w400, // md.sys.typescale.display-large.weight
);
@@ -52,7 +52,7 @@ class LunaTextStyle {
static TextStyle headlineSmall() {
return GoogleFonts.robotoFlex(
height: 40.0, // md.sys.typescale.headline-small.line-height
height: 1.25, // md.sys.typescale.headline-small.line-height
fontSize: 32.0, // md.sys.typescale.headline-small.size
fontWeight: FontWeight.w400, // md.sys.typescale.headline-small.weight
);
@@ -60,7 +60,7 @@ class LunaTextStyle {
static TextStyle headlineMedium() {
return GoogleFonts.robotoFlex(
height: 36.0, // md.sys.typescale.headline-medium.line-height
height: 1.29, // md.sys.typescale.headline-medium.line-height
fontSize: 28.0, // md.sys.typescale.headline-medium.size
fontWeight: FontWeight.w400, // md.sys.typescale.headline-medium.weight
);
@@ -68,7 +68,7 @@ class LunaTextStyle {
static TextStyle headlineLarge() {
return GoogleFonts.robotoFlex(
height: 32.0, // md.sys.typescale.headline-large.line-height
height: 1.33, // md.sys.typescale.headline-large.line-height
fontSize: 24.0, // md.sys.typescale.headline-large.size
fontWeight: FontWeight.w400, // md.sys.typescale.headline-large.weight
);
@@ -76,7 +76,7 @@ class LunaTextStyle {
static TextStyle labelSmall() {
return GoogleFonts.robotoFlex(
height: 16.0, // md.sys.typescale.label-small.line-height
height: 1.45, // md.sys.typescale.label-small.line-height
fontSize: 11.0, // md.sys.typescale.label-small.size
fontWeight: FontWeight.w500, // md.sys.typescale.label-small.weight
);
@@ -84,7 +84,7 @@ class LunaTextStyle {
static TextStyle labelMedium() {
return GoogleFonts.robotoFlex(
height: 16.0, // md.sys.typescale.label-medium.line-height
height: 1.33, // md.sys.typescale.label-medium.line-height
fontSize: 12.0, // md.sys.typescale.label-medium.size
fontWeight: FontWeight.w500, // md.sys.typescale.label-medium.weight
);
@@ -92,7 +92,7 @@ class LunaTextStyle {
static TextStyle labelLarge() {
return GoogleFonts.robotoFlex(
height: 20.0, // md.sys.typescale.label-large.line-height
height: 1.43, // md.sys.typescale.label-large.line-height
fontSize: 14.0, // md.sys.typescale.label-large.size
fontWeight: FontWeight.w500, // md.sys.typescale.label-large.weight
);
@@ -100,7 +100,7 @@ class LunaTextStyle {
static TextStyle titleSmall() {
return GoogleFonts.robotoFlex(
height: 20.0, // md.sys.typescale.title-small.line-height
height: 1.43, // md.sys.typescale.title-small.line-height
fontSize: 14.0, // md.sys.typescale.title-small.size
fontWeight: FontWeight.w500, // md.sys.typescale.title-small.weight
);
@@ -108,7 +108,7 @@ class LunaTextStyle {
static TextStyle titleMedium() {
return GoogleFonts.robotoFlex(
height: 24.0, // md.sys.typescale.title-medium.line-height
height: 1.50, // md.sys.typescale.title-medium.line-height
fontSize: 16.0, // md.sys.typescale.title-medium.size
fontWeight: FontWeight.w500, // md.sys.typescale.title-medium.weight
);
@@ -116,7 +116,7 @@ class LunaTextStyle {
static TextStyle titleLarge() {
return GoogleFonts.robotoFlex(
height: 28.0, // md.sys.typescale.title-large.line-height
height: 1.27, // md.sys.typescale.title-large.line-height
fontSize: 22.0, // md.sys.typescale.title-large.size
fontWeight: FontWeight.w400, // md.sys.typescale.title-large.weight
);