mirror of
https://github.com/jagandeepbrar/lunasea.git
synced 2026-08-30 20:24:25 +00:00
feat(calendar): scroll to selected date when switching from calendar to schedule view
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user