From b27c46bb473628eae1bc9ba4a25eef4b9824b533 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 21:54:35 +0300 Subject: [PATCH 01/21] Migration to new api --- lib/api/cube_api.dart | 2 +- .../timetable_page/managers/lesson_convertor.dart | 6 +++--- .../managers/timetable_lessons_manager.dart | 15 +++++++-------- .../managers/timetable_search_page_manager.dart | 7 +++---- lib/main.dart | 8 ++++---- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/lib/api/cube_api.dart b/lib/api/cube_api.dart index df1d375..9e62c3a 100644 --- a/lib/api/cube_api.dart +++ b/lib/api/cube_api.dart @@ -3,6 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; final cubeApi = Provider((ref) { return CubeApi.create( - baseUrl: Uri.tryParse('https://api.cube.nlabs.su/'), + baseUrl: Uri.tryParse('http://2qkhm0fz-test.api.cube.nlabs.su'), ); }); diff --git a/lib/features/timetable_page/managers/lesson_convertor.dart b/lib/features/timetable_page/managers/lesson_convertor.dart index 6af5143..2cae775 100644 --- a/lib/features/timetable_page/managers/lesson_convertor.dart +++ b/lib/features/timetable_page/managers/lesson_convertor.dart @@ -24,7 +24,7 @@ class LessonConvertor { }); Lesson lessonByLessonFullNamesInDb({ - required LessonFullNamesInDb lesson, + required LessonFullInDb lesson, int emptyLessonsBefore = 0, }) { final number = lesson.number; @@ -84,8 +84,8 @@ class LessonConvertor { typeShortName: lesson.type.shortName, disciplineName: lesson.discipline?.name, place: lesson.place?.name, - groupNames: lesson.groupNames, - teacherNames: lesson.teacherNames, + groupNames: lesson.groups.map((e) => e.name).toList(), + teacherNames: lesson.teachers?.map((e) => e.shortName).toList() ?? [], isElective: lesson.isElective, isRemotely: lesson.isRemotely, isEvent: isEvent, diff --git a/lib/features/timetable_page/managers/timetable_lessons_manager.dart b/lib/features/timetable_page/managers/timetable_lessons_manager.dart index 58e85c4..7e68bdd 100644 --- a/lib/features/timetable_page/managers/timetable_lessons_manager.dart +++ b/lib/features/timetable_page/managers/timetable_lessons_manager.dart @@ -73,7 +73,7 @@ class TimetableLessonsManager { events.change(SplayTreeMap()); } - Future> _getLessons({ + Future> _getLessons({ required DateTime startDate, required DateTime endDate, }) async { @@ -83,19 +83,18 @@ class TimetableLessonsManager { if (timetable == null) return []; - final lessonResponse = await api.apiLessonsGet( - fullData: true, - groups: timetable.type == TimetableType.group ? [timetable.id] : null, - teachers: timetable.type == TimetableType.teacher ? [timetable.id] : null, - places: timetable.type == TimetableType.place ? [timetable.id] : null, + final lessonResponse = await api.apiTimetableLessonsViewerGet( + group: timetable.type == TimetableType.group ? [timetable.id] : null, + teacher: timetable.type == TimetableType.teacher ? [timetable.id] : null, + place: timetable.type == TimetableType.place ? [timetable.id] : null, startDate: format.format(startDate), endDate: format.format(endDate), ); - return lessonResponse.body!; + return lessonResponse.body!.data; } - void _setLessons(List lessons) { + void _setLessons(List lessons) { TimetableLessons timetableMap = SplayTreeMap.of(timetableLessons.state.cast()); diff --git a/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart b/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart index 8ef4ad3..5de02ed 100644 --- a/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart +++ b/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart @@ -102,10 +102,11 @@ class TimetableSearchPageManager { return; } - final Response response; + final TimetableAutocomplete res; try { - response = await api.apiLessonsAutocompleteGet(q: query); + final response = await api.apiTimetableEntitiesGet(q: query); + res = response.body!; } catch (e) { event.state = TimetableSearchEventType.error; return; @@ -116,8 +117,6 @@ class TimetableSearchPageManager { return; } - final res = response.body!; - final List timetablesList = []; for (final group in res.groups) { diff --git a/lib/main.dart b/lib/main.dart index 8d9dac7..3f7a7c2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,10 +25,10 @@ void main() async { await dotenv.load(); await Future.wait([ - if (kIsMobile) - AppMetrica.activate( - AppMetricaConfig(dotenv.env['APP_METRICA_API_KEY']!), - ), + // if (kIsMobile && !kDebugMode) + AppMetrica.activate( + AppMetricaConfig(dotenv.env['APP_METRICA_API_KEY']!), + ), HiveInitializer.init(), Future.delayed(const Duration(milliseconds: 2500)) ]); From cea55720684d93f5b6ea249af8089642029421e7 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 22:34:23 +0300 Subject: [PATCH 02/21] Removing some options LessonCardLessonTypePosition --- .../models/app_settings/app_settings.g.dart | 7 ++-- .../lesson_card_lesson_type_position.dart | 28 +++++---------- .../lesson_card_lesson_type_position.g.dart | 35 ++++++------------- ...page_lesson_card_lesson_type_position.dart | 25 ++++--------- .../ui/widgets/lesson_card_footer.dart | 9 ++--- .../ui/widgets/lesson_card_header.dart | 19 ---------- 6 files changed, 29 insertions(+), 94 deletions(-) diff --git a/lib/features/settings/models/app_settings/app_settings.g.dart b/lib/features/settings/models/app_settings/app_settings.g.dart index 82f8cea..4272770 100644 --- a/lib/features/settings/models/app_settings/app_settings.g.dart +++ b/lib/features/settings/models/app_settings/app_settings.g.dart @@ -103,13 +103,10 @@ const _$AppLessonColorsModeEnumMap = { }; const _$LessonCardLessonTypePositionEnumMap = { - LessonCardLessonTypePosition.afterBottomLeftBlock: 'afterBottomLeftBlock', - LessonCardLessonTypePosition.afterTopLeftBlock: 'afterTopLeftBlock', - LessonCardLessonTypePosition.bottomLeft: 'bottomLeft', - LessonCardLessonTypePosition.topRight: 'topRight', + LessonCardLessonTypePosition.onIndicator: 'onIndicator', LessonCardLessonTypePosition.bottomRight: 'bottomRight', + LessonCardLessonTypePosition.afterBottomLeftBlock: 'afterBottomLeftBlock', LessonCardLessonTypePosition.beforeBottomRightBlock: 'beforeBottomRightBlock', - LessonCardLessonTypePosition.onIndicator: 'onIndicator', LessonCardLessonTypePosition.none: 'none', }; diff --git a/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.dart b/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.dart index dea9a0f..d0bbc0c 100644 --- a/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.dart +++ b/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.dart @@ -6,36 +6,24 @@ part 'lesson_card_lesson_type_position.g.dart'; @HiveType(typeId: 10) enum LessonCardLessonTypePosition { @HiveField(0) - @JsonValue('afterBottomLeftBlock') - afterBottomLeftBlock, + @JsonValue('onIndicator') + onIndicator, @HiveField(1) - @JsonValue('afterTopLeftBlock') - afterTopLeftBlock, - @HiveField(2) - @JsonValue('bottomLeft') - bottomLeft, - @HiveField(3) - @JsonValue('topRight') - topRight, - @HiveField(4) @JsonValue('bottomRight') bottomRight, - @HiveField(5) + @HiveField(2) + @JsonValue('afterBottomLeftBlock') + afterBottomLeftBlock, + @HiveField(3) @JsonValue('beforeBottomRightBlock') beforeBottomRightBlock, - @HiveField(6) - @JsonValue('onIndicator') - onIndicator, - @HiveField(7) + @HiveField(4) @JsonValue('none') none; bool get isAfterBottomLeftBlock => this == LessonCardLessonTypePosition.afterBottomLeftBlock; - bool get isAfterTopLeftBlock => - this == LessonCardLessonTypePosition.afterTopLeftBlock; - bool get isBottomLeft => this == LessonCardLessonTypePosition.bottomLeft; - bool get isTopRight => this == LessonCardLessonTypePosition.topRight; + bool get isBottomRight => this == LessonCardLessonTypePosition.bottomRight; bool get isBeforeBottomRightBlock => this == LessonCardLessonTypePosition.beforeBottomRightBlock; diff --git a/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.g.dart b/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.g.dart index 1783e96..c75ef71 100644 --- a/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.g.dart +++ b/lib/features/settings/models/lesson_card_lesson_type_position/lesson_card_lesson_type_position.g.dart @@ -17,52 +17,37 @@ class LessonCardLessonTypePositionAdapter LessonCardLessonTypePosition read(BinaryReader reader) { switch (reader.readByte()) { case 0: - return LessonCardLessonTypePosition.afterBottomLeftBlock; + return LessonCardLessonTypePosition.onIndicator; case 1: - return LessonCardLessonTypePosition.afterTopLeftBlock; + return LessonCardLessonTypePosition.bottomRight; case 2: - return LessonCardLessonTypePosition.bottomLeft; + return LessonCardLessonTypePosition.afterBottomLeftBlock; case 3: - return LessonCardLessonTypePosition.topRight; - case 4: - return LessonCardLessonTypePosition.bottomRight; - case 5: return LessonCardLessonTypePosition.beforeBottomRightBlock; - case 6: - return LessonCardLessonTypePosition.onIndicator; - case 7: + case 4: return LessonCardLessonTypePosition.none; default: - return LessonCardLessonTypePosition.afterBottomLeftBlock; + return LessonCardLessonTypePosition.onIndicator; } } @override void write(BinaryWriter writer, LessonCardLessonTypePosition obj) { switch (obj) { - case LessonCardLessonTypePosition.afterBottomLeftBlock: + case LessonCardLessonTypePosition.onIndicator: writer.writeByte(0); break; - case LessonCardLessonTypePosition.afterTopLeftBlock: + case LessonCardLessonTypePosition.bottomRight: writer.writeByte(1); break; - case LessonCardLessonTypePosition.bottomLeft: + case LessonCardLessonTypePosition.afterBottomLeftBlock: writer.writeByte(2); break; - case LessonCardLessonTypePosition.topRight: - writer.writeByte(3); - break; - case LessonCardLessonTypePosition.bottomRight: - writer.writeByte(4); - break; case LessonCardLessonTypePosition.beforeBottomRightBlock: - writer.writeByte(5); - break; - case LessonCardLessonTypePosition.onIndicator: - writer.writeByte(6); + writer.writeByte(3); break; case LessonCardLessonTypePosition.none: - writer.writeByte(7); + writer.writeByte(4); break; } } diff --git a/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart b/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart index 8bd607d..97f06e3 100644 --- a/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart +++ b/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart @@ -21,13 +21,15 @@ class _SettingsPageLessonCardLessonTypePosition extends ConsumerWidget { settingsNotifier.editLessonCardLessonTypePosition(value), items: const [ AppRadioSelectorItem( - title: Text('Снизу справа'), - description: Text('Выбор по умолчанию'), - value: LessonCardLessonTypePosition.bottomRight, + title: Text('На идикаторе'), + description: + Text('Выбор по умолчанию. Вертикальное расположение слева.'), + value: LessonCardLessonTypePosition.onIndicator, ), AppRadioSelectorItem( - title: Text('Снизу слева'), - value: LessonCardLessonTypePosition.bottomLeft, + title: Text('Снизу справа'), + description: Text('Вроде норм'), + value: LessonCardLessonTypePosition.bottomRight, ), AppRadioSelectorItem( title: Text('После нижнего левого блока'), @@ -37,19 +39,6 @@ class _SettingsPageLessonCardLessonTypePosition extends ConsumerWidget { title: Text('Перед нижним правым блоком'), value: LessonCardLessonTypePosition.beforeBottomRightBlock, ), - AppRadioSelectorItem( - title: Text('Сверху справа'), - value: LessonCardLessonTypePosition.topRight, - ), - AppRadioSelectorItem( - title: Text('После верхнего левого блока'), - value: LessonCardLessonTypePosition.afterTopLeftBlock, - ), - AppRadioSelectorItem( - title: Text('На идикаторе'), - description: Text('Вертикальное расположение слева'), - value: LessonCardLessonTypePosition.onIndicator, - ), AppRadioSelectorItem( title: Text('Отсутствует'), description: Text('Впрочем, действительно, можно и без него'), diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart index ffe2c49..008b3b3 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart @@ -57,11 +57,6 @@ class LessonCardFooter extends ConsumerWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (lessonTypePosition.isBottomLeft) - const Padding( - padding: EdgeInsets.only(left: 8), - child: LessonCardLessonTypeChip(), - ), if (teachersIsNotEmpty) Flexible( child: Padding( @@ -99,7 +94,7 @@ class LessonCardFooter extends ConsumerWidget { constraints: const BoxConstraints( maxWidth: 160, ), - padding: const EdgeInsets.only(top: 4, left: 8), + padding: const EdgeInsets.only(top: 4, left: 8, right: 6), child: Text( rigthText, style: context.textStyles.smallLabel.copyWith( @@ -112,7 +107,7 @@ class LessonCardFooter extends ConsumerWidget { ), if (lessonTypePosition.isBottomRight) const Padding( - padding: EdgeInsets.only(right: 4, left: 8), + padding: EdgeInsets.only(right: 4, left: 4), child: LessonCardLessonTypeChip(), ), ], diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart index 6d304b2..f3678f4 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart @@ -18,11 +18,6 @@ class LessonCardHeader extends ConsumerWidget { final color = ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - final lessonTypePosition = ref.watch( - appSettingsStateHolder - .select((value) => value.lessonCardLessonTypePosition), - ); - return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, @@ -53,22 +48,8 @@ class LessonCardHeader extends ConsumerWidget { color: context.colors.subduedText, ), ), - if (lessonTypePosition.isAfterTopLeftBlock) - const Padding( - padding: EdgeInsets.only( - left: 8, - ), - child: LessonCardLessonTypeChip(), - ), ], ), - if (lessonTypePosition.isTopRight) - const Padding( - padding: EdgeInsets.only( - left: 8, - ), - child: LessonCardLessonTypeChip(), - ), ], ); } From b5288c6f121c090fad4e30daf4293299b01c9704 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 22:35:55 +0300 Subject: [PATCH 03/21] Remove InkWell effect from LessonCard and Header time --- .../timetable_page/features/lesson_card/ui/lesson_card.dart | 1 - .../timetable_page/ui/widgets/timetable_page_header.dart | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart index 58a4ae2..d89283d 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart @@ -84,7 +84,6 @@ class LessonCard extends ConsumerWidget { const LessonCardIndicator(), Expanded( child: InkWell( - onTap: manager.findLastCurrentNextLesson, child: Column( children: [ Padding( diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart index 82ad544..ab21f30 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart @@ -106,7 +106,6 @@ class TimetablePageHeader extends ConsumerWidget { child: Padding( padding: const EdgeInsets.only(left: 4, top: 4, right: 4), child: InkWell( - onTap: () {}, borderRadius: const BorderRadius.all(Radius.circular(12)), child: Column( mainAxisAlignment: MainAxisAlignment.center, From 2852807ca894ef4c6e3902ad7a1b8dbd898c7e8e Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 22:42:07 +0300 Subject: [PATCH 04/21] Disable appmetrica in debug mode --- lib/features/analytics/analytical_logger_mixin.dart | 4 ++-- lib/features/analytics/logger.dart | 8 +++++--- .../settings_page_lesson_card_lesson_type_position.dart | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/features/analytics/analytical_logger_mixin.dart b/lib/features/analytics/analytical_logger_mixin.dart index 687e9c9..f5dc696 100644 --- a/lib/features/analytics/analytical_logger_mixin.dart +++ b/lib/features/analytics/analytical_logger_mixin.dart @@ -6,11 +6,11 @@ import 'package:proxima_logger/proxima_logger.dart' as pr; import 'package:cube_system/features/analytics/log_type.dart'; -import 'package:cube_system/core/utils.dart'; +import 'package:cube_system/features/analytics/logger.dart'; mixin AnalyticalLoggerMixin on pr.ProximaLogger { Future event(String name, [Map? attributes]) async { - if (kIsMobile) { + if (shouldReportEvent) { await AppMetrica.reportEventWithMap(name, attributes); } } diff --git a/lib/features/analytics/logger.dart b/lib/features/analytics/logger.dart index 1df3365..ffb7635 100644 --- a/lib/features/analytics/logger.dart +++ b/lib/features/analytics/logger.dart @@ -1,6 +1,6 @@ import 'package:appmetrica_plugin/appmetrica_plugin.dart'; import 'package:cube_system/core/utils.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:proxima_logger/proxima_logger.dart' as pr; import 'package:cube_system/features/analytics/analytical_logger_mixin.dart'; @@ -9,6 +9,8 @@ import 'package:cube_system/features/analytics/log_type.dart'; final logger = AppLogger(); +final shouldReportEvent = kIsMobile && !kDebugMode; + class AppLogger extends pr.ProximaLogger with AnalyticalLoggerMixin { AppLogger() : super( @@ -27,7 +29,7 @@ class AppLogger extends pr.ProximaLogger with AnalyticalLoggerMixin { ); void error(Object error, StackTrace stackTrace) { - if (kIsMobile) { + if (shouldReportEvent) { AppMetrica.reportError( errorDescription: AppMetricaErrorDescription.fromObjectAndStackTrace( error, @@ -44,7 +46,7 @@ class AppLogger extends pr.ProximaLogger with AnalyticalLoggerMixin { } void flutterError(FlutterErrorDetails details) { - if (kIsMobile) { + if (shouldReportEvent) { AppMetrica.reportError( message: null, errorDescription: diff --git a/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart b/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart index 97f06e3..d395f39 100644 --- a/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart +++ b/lib/features/settings/ui/widgets/settings_page_lesson_card_lesson_type_position.dart @@ -22,13 +22,13 @@ class _SettingsPageLessonCardLessonTypePosition extends ConsumerWidget { items: const [ AppRadioSelectorItem( title: Text('На идикаторе'), - description: - Text('Выбор по умолчанию. Вертикальное расположение слева.'), + description: Text( + 'Выбор по умолчанию. Вертикальный текст на левом индикаторе.', + ), value: LessonCardLessonTypePosition.onIndicator, ), AppRadioSelectorItem( title: Text('Снизу справа'), - description: Text('Вроде норм'), value: LessonCardLessonTypePosition.bottomRight, ), AppRadioSelectorItem( From ef0a1d8a0d23f2f6dbc0cd9a7e4993ad805ce827 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 23:00:49 +0300 Subject: [PATCH 05/21] Restructuring TimetablePageHeader --- .../ui/widgets/timetable_page_header.dart | 131 ++---------------- .../timetable_page_header_back_button.dart | 39 ++++++ .../widgets/timetable_page_header_date.dart | 55 ++++++++ .../timetable_page_header_timetable_info.dart | 67 +++++++++ lib/models/timetable/timetable_type.dart | 4 + 5 files changed, 176 insertions(+), 120 deletions(-) create mode 100644 lib/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart create mode 100644 lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart create mode 100644 lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart index ab21f30..d9a9f76 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart @@ -1,20 +1,15 @@ import 'package:cube_system/features/timetable_page/features/week_timeline/state_holders/week_timeline_shown_week_date.dart'; import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; import 'package:cube_system/features/date_time_contol/state_holders/current_date_time_state_holders.dart'; -import 'package:cube_system/features/timetable_page/state_holders/selected_timetable.dart'; -import 'package:cube_system/models/timetable/timetable_type.dart'; +import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart'; +import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_date.dart'; +import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart'; import 'package:cube_system/core/extensions.dart'; -import 'package:cube_system/styles/app_theme_context_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -import 'package:intl/intl.dart'; import 'package:cube_system/features/timetable_page/features/week_timeline/providers/week_timeline_offset_back_button_direction_provider.dart'; -import 'package:cube_system/features/timetable_page/features/week_timeline/models/week_timeline_offset_back_button_direction.dart'; - class TimetablePageHeader extends ConsumerWidget { const TimetablePageHeader({super.key}); @@ -22,19 +17,12 @@ class TimetablePageHeader extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final manager = ref.watch(timetablePageManager); - final timetable = ref.watch(selectedTimetableStateHolder); - final date = ref.watch(currentDate); final weekDate = ref.watch(weekTimelineShownWeekDate); final weekOffsetButton = ref.watch(weekTimelineOffsetBackButtonDirectionProvider); - final labelTextStyle = - timetable == null || timetable.type == TimetableType.teacher - ? context.textStyles.label - : context.textStyles.largeTitle; - final String weekLabel; if (weekDate.weekNumber % 2 == 1) { @@ -47,125 +35,28 @@ class TimetablePageHeader extends ConsumerWidget { height: 62, child: Row( crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: const [ Expanded( flex: 10, child: Padding( - padding: const EdgeInsets.only(left: 8, top: 4), - child: InkWell( - onTap: () { - context.go('/timetable/search'); - }, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Padding( - padding: const EdgeInsets.only(left: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - children: [ - Text( - timetable?.label ?? 'Расписание', - style: labelTextStyle, - ), - SizedBox( - height: 16, - child: Text( - String.fromCharCode( - Icons.arrow_drop_down_rounded.codePoint, - ), - style: labelTextStyle.copyWith( - fontFamily: - Icons.arrow_drop_down_rounded.fontFamily, - package: - Icons.arrow_drop_down_rounded.fontPackage, - fontSize: 20, - height: 0.95, - ), - ), - ), - ], - ), - const SizedBox(height: 1), - Text( - timetable?.type.label ?? 'Не выбрано', - style: context.textStyles.smallSubTitle.copyWith( - fontSize: 10, - color: context.colors.subduedText, - ), - ), - ], - ), - ), - ), + padding: EdgeInsets.only(left: 8, top: 4), + child: TimetablePageHeaderTimetableInfo(), ), ), Expanded( flex: 7, child: Padding( - padding: const EdgeInsets.only(left: 4, top: 4, right: 4), - child: InkWell( - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - DateFormat('MMMM', 'ru').format(weekDate).capitalize(), - style: context.textStyles.label, - textAlign: TextAlign.center, - ), - const SizedBox(height: 1), - if (date.year != weekDate.year) - Text( - DateFormat('yyyy', 'ru').format(weekDate).capitalize(), - style: context.textStyles.label.copyWith(), - textAlign: TextAlign.center, - ), - Text( - weekLabel, - style: context.textStyles.smallSubTitle.copyWith( - fontSize: 10, - color: context.colors.subduedText, - ), - textAlign: TextAlign.center, - ), - ], - ), - ), + padding: EdgeInsets.only(left: 4, top: 4, right: 4), + child: TimetablePageHeaderDate(), ), ), Expanded( flex: 10, child: Align( alignment: Alignment.centerRight, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only(right: 8), - child: weekOffsetButton != - WeekTimelineOffsetBackButtonDirection.stay - ? InkWell( - onTap: () => - manager.selectDate(date.add(Duration.zero)), - borderRadius: - const BorderRadius.all(Radius.circular(99)), - child: Container( - padding: const EdgeInsets.all(8), - child: Icon( - weekOffsetButton == - WeekTimelineOffsetBackButtonDirection - .forward - ? Icons.arrow_forward_ios_rounded - : Icons.arrow_back_ios_new_rounded, - size: 20, - ), - ), - ) - : null, - ), - ], + child: Padding( + padding: EdgeInsets.only(right: 8), + child: TimetablePageHeaderBackButton(), ), ), ) diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart new file mode 100644 index 0000000..d9902ec --- /dev/null +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:cube_system/features/date_time_contol/state_holders/current_date_time_state_holders.dart'; + +import 'package:cube_system/features/timetable_page/features/week_timeline/models/week_timeline_offset_back_button_direction.dart'; +import 'package:cube_system/features/timetable_page/features/week_timeline/providers/week_timeline_offset_back_button_direction_provider.dart'; +import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; + +class TimetablePageHeaderBackButton extends ConsumerWidget { + const TimetablePageHeaderBackButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final manager = ref.watch(timetablePageManager); + + final date = ref.watch(currentDate); + + final weekOffsetButton = + ref.watch(weekTimelineOffsetBackButtonDirectionProvider); + + return weekOffsetButton != WeekTimelineOffsetBackButtonDirection.stay + ? InkWell( + onTap: () => manager.selectDate(date.add(Duration.zero)), + borderRadius: const BorderRadius.all(Radius.circular(99)), + child: Container( + padding: const EdgeInsets.all(8), + child: Icon( + weekOffsetButton == + WeekTimelineOffsetBackButtonDirection.forward + ? Icons.arrow_forward_ios_rounded + : Icons.arrow_back_ios_new_rounded, + size: 20, + ), + ), + ) + : const SizedBox(); + } +} diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart new file mode 100644 index 0000000..7947498 --- /dev/null +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart @@ -0,0 +1,55 @@ +import 'package:cube_system/core/extensions.dart'; +import 'package:cube_system/styles/app_theme_context_extension.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:intl/intl.dart'; + +import 'package:cube_system/features/date_time_contol/state_holders/current_date_time_state_holders.dart'; +import 'package:cube_system/features/timetable_page/features/week_timeline/state_holders/week_timeline_shown_week_date.dart'; + +class TimetablePageHeaderDate extends ConsumerWidget { + const TimetablePageHeaderDate({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final date = ref.watch(currentDate); + final weekDate = ref.watch(weekTimelineShownWeekDate); + + final String weekLabel; + + if (weekDate.weekNumber % 2 == 1) { + weekLabel = 'Числитель'; + } else { + weekLabel = 'Знаменатель'; + } + + return InkWell( + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + DateFormat('MMMM', 'ru').format(weekDate).capitalize(), + style: context.textStyles.label, + textAlign: TextAlign.center, + ), + const SizedBox(height: 1), + if (date.year != weekDate.year) + Text( + DateFormat('yyyy', 'ru').format(weekDate).capitalize(), + style: context.textStyles.label.copyWith(), + textAlign: TextAlign.center, + ), + Text( + weekLabel, + style: context.textStyles.smallSubTitle.copyWith( + fontSize: 10, + color: context.colors.subduedText, + ), + textAlign: TextAlign.center, + ), + ], + ), + ); + } +} diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart new file mode 100644 index 0000000..a63b317 --- /dev/null +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart @@ -0,0 +1,67 @@ +import 'package:cube_system/styles/app_theme_context_extension.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; + +import 'package:cube_system/models/timetable/timetable_type.dart'; +import 'package:cube_system/features/timetable_page/state_holders/selected_timetable.dart'; + +class TimetablePageHeaderTimetableInfo extends ConsumerWidget { + const TimetablePageHeaderTimetableInfo({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final timetable = ref.watch(selectedTimetableStateHolder); + + final labelTextStyle = + timetable == null || timetable.type == TimetableType.teacher + ? context.textStyles.label + : context.textStyles.largeTitle; + + return InkWell( + onTap: () { + context.go('/timetable/search'); + }, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Padding( + padding: const EdgeInsets.only(left: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Text( + timetable?.label ?? 'Расписание', + style: labelTextStyle, + ), + SizedBox( + height: 16, + child: Text( + String.fromCharCode( + Icons.arrow_drop_down_rounded.codePoint, + ), + style: labelTextStyle.copyWith( + fontFamily: Icons.arrow_drop_down_rounded.fontFamily, + package: Icons.arrow_drop_down_rounded.fontPackage, + fontSize: 20, + height: 0.95, + ), + ), + ), + ], + ), + const SizedBox(height: 1), + Text( + timetable?.type.label ?? 'Не выбрано', + style: context.textStyles.smallSubTitle.copyWith( + fontSize: 10, + color: context.colors.subduedText, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/models/timetable/timetable_type.dart b/lib/models/timetable/timetable_type.dart index 7a3d63e..542dd16 100644 --- a/lib/models/timetable/timetable_type.dart +++ b/lib/models/timetable/timetable_type.dart @@ -20,4 +20,8 @@ enum TimetableType { } return null; } + + bool get isGroup => this == TimetableType.group; + bool get isTeacher => this == TimetableType.teacher; + bool get isPlace => this == TimetableType.place; } From f9762061e72b62a89d12243c298eaf5e3b1cdb8f Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 23:34:59 +0300 Subject: [PATCH 06/21] LessonCardIconsIcon --- .../features/lesson_card/ui/lesson_card.dart | 7 +-- .../ui/widgets/lesson_card_icons.dart | 52 ++++--------------- .../ui/widgets/lesson_card_icons_icon.dart | 46 ++++++++++++++++ .../managers/timetable_lessons_manager.dart | 11 ++-- .../ui/widgets/timetable_page_day.dart | 2 +- 5 files changed, 69 insertions(+), 49 deletions(-) create mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart diff --git a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart index d89283d..09ef494 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart @@ -27,6 +27,7 @@ import 'package:cube_system/features/timetable_page/state_holders/lessons/next_l part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_body.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart'; +part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_indicator.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart'; @@ -54,15 +55,15 @@ class LessonCard extends ConsumerWidget { child: Column( children: [ const LessonCardRecess( - margin: EdgeInsets.only(bottom: 12, top: 8), + margin: EdgeInsets.only(bottom: 12, top: 9), ), const LessonCardTimeToStart( - margin: EdgeInsets.only(bottom: 8, top: 4), + margin: EdgeInsets.only(bottom: 9, top: 4), ), Stack( children: [ Container( - margin: const EdgeInsets.only(top: 8), + margin: const EdgeInsets.only(top: 9), decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), color: context.colors.background, diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart index 1e51182..31dd140 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart @@ -7,8 +7,8 @@ class LessonCardIcons extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final isRemotely = - ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); + // final isRemotely = + // ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); final isActiveLessons = ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); @@ -16,63 +16,33 @@ class LessonCardIcons extends ConsumerWidget { final color = ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - // final isRemotely = _random.nextInt(100) < 0; + final isRemotely = _random.nextInt(100) < 25; - final presentImportantNote = _random.nextInt(100) < 0; + final presentImportantNote = _random.nextInt(100) < 25; - final numberOfNotes = _random.nextInt(100) < 0 ? _random.nextInt(7) : 0; + final numberOfNotes = _random.nextInt(100) < 25 ? _random.nextInt(7) : 0; return Row( children: [ if (isRemotely) - Container( - margin: const EdgeInsets.only(right: 4), - width: 16, - height: 16, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), - child: const Icon( + const LessonCardIconsIcon.icon( + icon: Icon( Icons.wifi_rounded, size: 12, color: Colors.white, ), ), if (presentImportantNote) - Container( - margin: const EdgeInsets.only(right: 4), - width: 16, - height: 16, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), - child: const Icon( + const LessonCardIconsIcon.icon( + icon: Icon( Icons.priority_high_rounded, size: 12, color: Colors.white, ), ), if (numberOfNotes > 0) - Container( - margin: const EdgeInsets.only(right: 4), - width: 16, - height: 16, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), - child: Center( - child: Padding( - padding: const EdgeInsets.only(left: 0.5), - child: Text( - numberOfNotes.toString(), - style: context.textStyles.chipLabel - .copyWith(color: context.colors.white), - ), - ), - ), + LessonCardIconsIcon.number( + number: numberOfNotes, ), if (isActiveLessons) Consumer( diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart new file mode 100644 index 0000000..de50fec --- /dev/null +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart @@ -0,0 +1,46 @@ +part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; + +class LessonCardIconsIcon extends ConsumerWidget { + final int? number; + final Widget? icon; + + const LessonCardIconsIcon.number({ + super.key, + required this.number, + }) : icon = null; + + const LessonCardIconsIcon.icon({ + super.key, + required this.icon, + }) : number = null; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final color = + ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + + return Container( + margin: const EdgeInsets.only(right: 4), + width: 18, + height: 18, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + ), + child: Center( + child: number != null + ? Padding( + padding: const EdgeInsets.only(left: 0.5), + child: Text( + number!.toString(), + style: context.textStyles.chipLabel + .copyWith(color: context.colors.white), + ), + ) + : icon != null + ? icon! + : null, + ), + ); + } +} diff --git a/lib/features/timetable_page/managers/timetable_lessons_manager.dart b/lib/features/timetable_page/managers/timetable_lessons_manager.dart index 7e68bdd..3207914 100644 --- a/lib/features/timetable_page/managers/timetable_lessons_manager.dart +++ b/lib/features/timetable_page/managers/timetable_lessons_manager.dart @@ -77,18 +77,21 @@ class TimetableLessonsManager { required DateTime startDate, required DateTime endDate, }) async { - final format = DateFormat('yyyy-MM-dd'); - final timetable = selectedTimetable.state; if (timetable == null) return []; + final format = DateFormat('yyyy-MM-dd'); + + final startDateStr = format.format(startDate); + final endDateStr = format.format(endDate); + final lessonResponse = await api.apiTimetableLessonsViewerGet( group: timetable.type == TimetableType.group ? [timetable.id] : null, teacher: timetable.type == TimetableType.teacher ? [timetable.id] : null, place: timetable.type == TimetableType.place ? [timetable.id] : null, - startDate: format.format(startDate), - endDate: format.format(endDate), + startDate: startDateStr, + endDate: endDateStr, ); return lessonResponse.body!.data; diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart index c39f60d..6cc2481 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart @@ -78,7 +78,7 @@ class TimetablePageDay extends ConsumerWidget { ), itemCount: lessons.length, itemBuilder: (context, index) => LessonCard(lessons[index]), - separatorBuilder: (context, index) => const SizedBox(height: 12), + separatorBuilder: (context, index) => const SizedBox(height: 11), ); } } From 05811f18ccd9fb0e66eab404f21043f6aa0743bb Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 2 May 2023 23:55:04 +0300 Subject: [PATCH 07/21] Cancel and collision icons in LessonCardIcons --- .../ui/widgets/lesson_card_icons.dart | 26 ++++++++++++------- .../ui/widgets/lesson_card_icons_icon.dart | 25 +++++++++++++++--- lib/styles/app_colors/app_colors.dart | 1 + lib/styles/app_colors/app_colors.tailor.dart | 9 +++++++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart index 31dd140..5d21173 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart @@ -16,6 +16,10 @@ class LessonCardIcons extends ConsumerWidget { final color = ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + final isCancelled = _random.nextInt(100) < 25; + + final isCollision = _random.nextInt(100) < 25; + final isRemotely = _random.nextInt(100) < 25; final presentImportantNote = _random.nextInt(100) < 25; @@ -24,21 +28,23 @@ class LessonCardIcons extends ConsumerWidget { return Row( children: [ + if (isCancelled) + const LessonCardIconsIcon.icon( + icon: Icon(Icons.cancel), + isDestructive: true, + ), + if (isCollision) + const LessonCardIconsIcon.icon( + icon: Icon(Icons.error), + isDestructive: true, + ), if (isRemotely) const LessonCardIconsIcon.icon( - icon: Icon( - Icons.wifi_rounded, - size: 12, - color: Colors.white, - ), + icon: Icon(Icons.home), ), if (presentImportantNote) const LessonCardIconsIcon.icon( - icon: Icon( - Icons.priority_high_rounded, - size: 12, - color: Colors.white, - ), + icon: Icon(Icons.priority_high_rounded), ), if (numberOfNotes > 0) LessonCardIconsIcon.number( diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart index de50fec..3e7131f 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart @@ -3,28 +3,36 @@ part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/les class LessonCardIconsIcon extends ConsumerWidget { final int? number; final Widget? icon; + final bool isDestructive; + final Color? color; const LessonCardIconsIcon.number({ super.key, required this.number, + this.isDestructive = false, + this.color, }) : icon = null; const LessonCardIconsIcon.icon({ super.key, required this.icon, + this.isDestructive = false, + this.color, }) : number = null; @override Widget build(BuildContext context, WidgetRef ref) { - final color = - ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + final backgroundColor = isDestructive + ? context.colors.destructive + : color ?? + ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); return Container( margin: const EdgeInsets.only(right: 4), width: 18, height: 18, decoration: BoxDecoration( - color: color, + color: backgroundColor, shape: BoxShape.circle, ), child: Center( @@ -38,7 +46,16 @@ class LessonCardIconsIcon extends ConsumerWidget { ), ) : icon != null - ? icon! + ? IconTheme( + data: Theme.of(context).iconTheme.copyWith( + size: 13.5, + color: context.colors.white, + ), + child: Padding( + padding: const EdgeInsets.only(bottom: 1, right: 0.2), + child: icon!, + ), + ) : null, ), ); diff --git a/lib/styles/app_colors/app_colors.dart b/lib/styles/app_colors/app_colors.dart index 865ace8..579c045 100644 --- a/lib/styles/app_colors/app_colors.dart +++ b/lib/styles/app_colors/app_colors.dart @@ -11,6 +11,7 @@ part 'app_colors.tailor.dart'; class _$AppColors { static List primary = [const Color(0xFF38a1ff)]; static List background = [const Color(0xFFF6F7FF)]; + static List destructive = [Colors.red]; static List text = [const Color(0xFF2B2B2B)]; static List hintText = [const Color.fromARGB(255, 161, 161, 161)]; diff --git a/lib/styles/app_colors/app_colors.tailor.dart b/lib/styles/app_colors/app_colors.tailor.dart index 906291c..4cd6d14 100644 --- a/lib/styles/app_colors/app_colors.tailor.dart +++ b/lib/styles/app_colors/app_colors.tailor.dart @@ -12,6 +12,7 @@ class AppColors extends ThemeExtension { const AppColors({ required this.primary, required this.background, + required this.destructive, required this.text, required this.hintText, required this.subduedText, @@ -24,6 +25,7 @@ class AppColors extends ThemeExtension { final Color primary; final Color background; + final Color destructive; final Color text; final Color hintText; final Color subduedText; @@ -36,6 +38,7 @@ class AppColors extends ThemeExtension { static final AppColors light = AppColors( primary: _$AppColors.primary[0], background: _$AppColors.background[0], + destructive: _$AppColors.destructive[0], text: _$AppColors.text[0], hintText: _$AppColors.hintText[0], subduedText: _$AppColors.subduedText[0], @@ -54,6 +57,7 @@ class AppColors extends ThemeExtension { AppColors copyWith({ Color? primary, Color? background, + Color? destructive, Color? text, Color? hintText, Color? subduedText, @@ -66,6 +70,7 @@ class AppColors extends ThemeExtension { return AppColors( primary: primary ?? this.primary, background: background ?? this.background, + destructive: destructive ?? this.destructive, text: text ?? this.text, hintText: hintText ?? this.hintText, subduedText: subduedText ?? this.subduedText, @@ -83,6 +88,7 @@ class AppColors extends ThemeExtension { return AppColors( primary: Color.lerp(primary, other.primary, t)!, background: Color.lerp(background, other.background, t)!, + destructive: Color.lerp(destructive, other.destructive, t)!, text: Color.lerp(text, other.text, t)!, hintText: Color.lerp(hintText, other.hintText, t)!, subduedText: Color.lerp(subduedText, other.subduedText, t)!, @@ -102,6 +108,8 @@ class AppColors extends ThemeExtension { const DeepCollectionEquality().equals(primary, other.primary) && const DeepCollectionEquality() .equals(background, other.background) && + const DeepCollectionEquality() + .equals(destructive, other.destructive) && const DeepCollectionEquality().equals(text, other.text) && const DeepCollectionEquality().equals(hintText, other.hintText) && const DeepCollectionEquality() @@ -121,6 +129,7 @@ class AppColors extends ThemeExtension { runtimeType, const DeepCollectionEquality().hash(primary), const DeepCollectionEquality().hash(background), + const DeepCollectionEquality().hash(destructive), const DeepCollectionEquality().hash(text), const DeepCollectionEquality().hash(hintText), const DeepCollectionEquality().hash(subduedText), From 7d0c334d02f113b8e5361a0d8aa30f322b20b82f Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 00:23:31 +0300 Subject: [PATCH 08/21] Check lesson collision --- .../ui/widgets/lesson_card_icons.dart | 10 ++++--- .../managers/lesson_convertor.dart | 2 ++ .../managers/timetable_lessons_manager.dart | 25 ++++++++++++++++- lib/main.dart | 1 - lib/models/lesson/lesson.dart | 1 + lib/models/lesson/lesson.freezed.dart | 27 ++++++++++++++++++- lib/models/lesson/lesson.g.dart | 5 +++- 7 files changed, 63 insertions(+), 8 deletions(-) diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart index 5d21173..b8f400e 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart @@ -7,18 +7,20 @@ class LessonCardIcons extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final color = + ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + // final isRemotely = // ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); + final isCollision = + ref.watch(_lessonInLessonCard.select((value) => value.isCollision)); final isActiveLessons = ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); - final color = - ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - final isCancelled = _random.nextInt(100) < 25; - final isCollision = _random.nextInt(100) < 25; + // final isCollision = _random.nextInt(100) < 25; final isRemotely = _random.nextInt(100) < 25; diff --git a/lib/features/timetable_page/managers/lesson_convertor.dart b/lib/features/timetable_page/managers/lesson_convertor.dart index 2cae775..aa3d2d7 100644 --- a/lib/features/timetable_page/managers/lesson_convertor.dart +++ b/lib/features/timetable_page/managers/lesson_convertor.dart @@ -26,6 +26,7 @@ class LessonConvertor { Lesson lessonByLessonFullNamesInDb({ required LessonFullInDb lesson, int emptyLessonsBefore = 0, + bool isCollision = false, }) { final number = lesson.number; @@ -91,6 +92,7 @@ class LessonConvertor { isEvent: isEvent, defaultColor: color, emptyLessonsBefore: emptyLessonsBefore, + isCollision: isCollision, ); return newLesson; diff --git a/lib/features/timetable_page/managers/timetable_lessons_manager.dart b/lib/features/timetable_page/managers/timetable_lessons_manager.dart index 3207914..38848ad 100644 --- a/lib/features/timetable_page/managers/timetable_lessons_manager.dart +++ b/lib/features/timetable_page/managers/timetable_lessons_manager.dart @@ -105,15 +105,38 @@ class TimetableLessonsManager { timetableMap[lesson.date] = []; } + // for (int i = 0; i < lessons.length; i++) { + // if (lessons[i].date.day == DateTime.now().day) { + // lessons.insert( + // i + 1, + // lessons[i].copyWith( + // place: lessons[i].place?.copyWith( + // name: 'fwefweof', + // ), + // ), + // ); + // break; + // } + // } + for (int i = 0; i < lessons.length; i++) { final lesson = lessons[i]; int emptyLessonsBefore = 0; - if (i > 0 && lessons[i - 1].date == lesson.date) { + + final equalPrevious = i > 0 && lessons[i - 1].number == lesson.number; + final equalNext = + i < lessons.length - 1 && lessons[i + 1].number == lesson.number; + + final isCollision = equalPrevious || equalNext; + + if (i > 0 && lessons[i - 1].date == lesson.date && !isCollision) { emptyLessonsBefore = lesson.number - lessons[i - 1].number - 1; } + final l = lessonConvertor.lessonByLessonFullNamesInDb( lesson: lesson, emptyLessonsBefore: emptyLessonsBefore, + isCollision: isCollision, ); timetableMap[lesson.date]!.add(l); diff --git a/lib/main.dart b/lib/main.dart index 3f7a7c2..5f6f609 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,7 +25,6 @@ void main() async { await dotenv.load(); await Future.wait([ - // if (kIsMobile && !kDebugMode) AppMetrica.activate( AppMetricaConfig(dotenv.env['APP_METRICA_API_KEY']!), ), diff --git a/lib/models/lesson/lesson.dart b/lib/models/lesson/lesson.dart index bdfbd1d..d7e5256 100644 --- a/lib/models/lesson/lesson.dart +++ b/lib/models/lesson/lesson.dart @@ -25,6 +25,7 @@ class Lesson with _$Lesson { @HiveField(9) required bool isRemotely, @HiveField(10) required bool isElective, @HiveField(11) required bool isEvent, + @HiveField(14, defaultValue: false) required bool isCollision, @HiveField(12) required Color defaultColor, @HiveField(13) required int emptyLessonsBefore, }) = _Lesson; diff --git a/lib/models/lesson/lesson.freezed.dart b/lib/models/lesson/lesson.freezed.dart index 1aeb7fb..72f0f92 100644 --- a/lib/models/lesson/lesson.freezed.dart +++ b/lib/models/lesson/lesson.freezed.dart @@ -40,6 +40,8 @@ mixin _$Lesson { bool get isElective => throw _privateConstructorUsedError; @HiveField(11) bool get isEvent => throw _privateConstructorUsedError; + @HiveField(14, defaultValue: false) + bool get isCollision => throw _privateConstructorUsedError; @HiveField(12) Color get defaultColor => throw _privateConstructorUsedError; @HiveField(13) @@ -67,6 +69,7 @@ abstract class $LessonCopyWith<$Res> { @HiveField(9) bool isRemotely, @HiveField(10) bool isElective, @HiveField(11) bool isEvent, + @HiveField(14, defaultValue: false) bool isCollision, @HiveField(12) Color defaultColor, @HiveField(13) int emptyLessonsBefore}); @@ -99,6 +102,7 @@ class _$LessonCopyWithImpl<$Res, $Val extends Lesson> Object? isRemotely = null, Object? isElective = null, Object? isEvent = null, + Object? isCollision = null, Object? defaultColor = null, Object? emptyLessonsBefore = null, }) { @@ -151,6 +155,10 @@ class _$LessonCopyWithImpl<$Res, $Val extends Lesson> ? _value.isEvent : isEvent // ignore: cast_nullable_to_non_nullable as bool, + isCollision: null == isCollision + ? _value.isCollision + : isCollision // ignore: cast_nullable_to_non_nullable + as bool, defaultColor: null == defaultColor ? _value.defaultColor : defaultColor // ignore: cast_nullable_to_non_nullable @@ -198,6 +206,7 @@ abstract class _$$_LessonCopyWith<$Res> implements $LessonCopyWith<$Res> { @HiveField(9) bool isRemotely, @HiveField(10) bool isElective, @HiveField(11) bool isEvent, + @HiveField(14, defaultValue: false) bool isCollision, @HiveField(12) Color defaultColor, @HiveField(13) int emptyLessonsBefore}); @@ -229,6 +238,7 @@ class __$$_LessonCopyWithImpl<$Res> Object? isRemotely = null, Object? isElective = null, Object? isEvent = null, + Object? isCollision = null, Object? defaultColor = null, Object? emptyLessonsBefore = null, }) { @@ -281,6 +291,10 @@ class __$$_LessonCopyWithImpl<$Res> ? _value.isEvent : isEvent // ignore: cast_nullable_to_non_nullable as bool, + isCollision: null == isCollision + ? _value.isCollision + : isCollision // ignore: cast_nullable_to_non_nullable + as bool, defaultColor: null == defaultColor ? _value.defaultColor : defaultColor // ignore: cast_nullable_to_non_nullable @@ -310,6 +324,7 @@ class _$_Lesson implements _Lesson { @HiveField(9) required this.isRemotely, @HiveField(10) required this.isElective, @HiveField(11) required this.isEvent, + @HiveField(14, defaultValue: false) required this.isCollision, @HiveField(12) required this.defaultColor, @HiveField(13) required this.emptyLessonsBefore}) : _groupNames = groupNames, @@ -364,6 +379,9 @@ class _$_Lesson implements _Lesson { @HiveField(11) final bool isEvent; @override + @HiveField(14, defaultValue: false) + final bool isCollision; + @override @HiveField(12) final Color defaultColor; @override @@ -372,7 +390,7 @@ class _$_Lesson implements _Lesson { @override String toString() { - return 'Lesson(number: $number, timings: $timings, dateTimings: $dateTimings, type: $type, typeShortName: $typeShortName, disciplineName: $disciplineName, place: $place, groupNames: $groupNames, teacherNames: $teacherNames, isRemotely: $isRemotely, isElective: $isElective, isEvent: $isEvent, defaultColor: $defaultColor, emptyLessonsBefore: $emptyLessonsBefore)'; + return 'Lesson(number: $number, timings: $timings, dateTimings: $dateTimings, type: $type, typeShortName: $typeShortName, disciplineName: $disciplineName, place: $place, groupNames: $groupNames, teacherNames: $teacherNames, isRemotely: $isRemotely, isElective: $isElective, isEvent: $isEvent, isCollision: $isCollision, defaultColor: $defaultColor, emptyLessonsBefore: $emptyLessonsBefore)'; } @override @@ -399,6 +417,8 @@ class _$_Lesson implements _Lesson { (identical(other.isElective, isElective) || other.isElective == isElective) && (identical(other.isEvent, isEvent) || other.isEvent == isEvent) && + (identical(other.isCollision, isCollision) || + other.isCollision == isCollision) && (identical(other.defaultColor, defaultColor) || other.defaultColor == defaultColor) && (identical(other.emptyLessonsBefore, emptyLessonsBefore) || @@ -420,6 +440,7 @@ class _$_Lesson implements _Lesson { isRemotely, isElective, isEvent, + isCollision, defaultColor, emptyLessonsBefore); @@ -444,6 +465,7 @@ abstract class _Lesson implements Lesson { @HiveField(9) required final bool isRemotely, @HiveField(10) required final bool isElective, @HiveField(11) required final bool isEvent, + @HiveField(14, defaultValue: false) required final bool isCollision, @HiveField(12) required final Color defaultColor, @HiveField(13) required final int emptyLessonsBefore}) = _$_Lesson; @@ -484,6 +506,9 @@ abstract class _Lesson implements Lesson { @HiveField(11) bool get isEvent; @override + @HiveField(14, defaultValue: false) + bool get isCollision; + @override @HiveField(12) Color get defaultColor; @override diff --git a/lib/models/lesson/lesson.g.dart b/lib/models/lesson/lesson.g.dart index 56613c3..3511a78 100644 --- a/lib/models/lesson/lesson.g.dart +++ b/lib/models/lesson/lesson.g.dart @@ -31,6 +31,7 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { isRemotely: fields[9] as bool, isElective: fields[10] as bool, isEvent: fields[11] as bool, + isCollision: fields[14] == null ? false : fields[14] as bool, defaultColor: fields[12] as Color, emptyLessonsBefore: fields[13] as int, ); @@ -39,7 +40,7 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { @override void write(BinaryWriter writer, _$_Lesson obj) { writer - ..writeByte(14) + ..writeByte(15) ..writeByte(0) ..write(obj.number) ..writeByte(1) @@ -60,6 +61,8 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { ..write(obj.isElective) ..writeByte(11) ..write(obj.isEvent) + ..writeByte(14) + ..write(obj.isCollision) ..writeByte(12) ..write(obj.defaultColor) ..writeByte(13) From 029a81bb2ea63561fcaa12ff974f748bef7e0ca1 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 00:25:39 +0300 Subject: [PATCH 09/21] True conditions in LessonCardIcons --- .../lesson_card/ui/widgets/lesson_card_icons.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart index b8f400e..7dcd0de 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart @@ -10,23 +10,24 @@ class LessonCardIcons extends ConsumerWidget { final color = ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - // final isRemotely = - // ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); + final isRemotely = + ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); + final isCollision = ref.watch(_lessonInLessonCard.select((value) => value.isCollision)); final isActiveLessons = ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); - final isCancelled = _random.nextInt(100) < 25; - // final isCollision = _random.nextInt(100) < 25; - final isRemotely = _random.nextInt(100) < 25; + // final isRemotely = _random.nextInt(100) < 25; + + final isCancelled = _random.nextInt(100) < 0; - final presentImportantNote = _random.nextInt(100) < 25; + final presentImportantNote = _random.nextInt(100) < 0; - final numberOfNotes = _random.nextInt(100) < 25 ? _random.nextInt(7) : 0; + final numberOfNotes = _random.nextInt(100) < 0 ? _random.nextInt(7) : 0; return Row( children: [ From ee064f31a815e7386d25dba144b528d283e470ef Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 01:17:24 +0300 Subject: [PATCH 10/21] Group info in search page --- .../timetable_page_header_timetable_info.dart | 8 +- .../timetable_search_page_manager.dart | 46 ++-- .../models/timetable_search_group_info.dart | 13 ++ .../timetable_search_group_info.freezed.dart | 197 +++++++++++++++++ .../models/timetable_search_info.dart | 15 ++ .../models/timetable_search_info.freezed.dart | 199 ++++++++++++++++++ .../timetable_search_page_timetables.dart | 5 +- .../ui/timetable_search_page.dart | 10 +- .../ui/widgets/timetable_card.dart | 111 ---------- .../widgets/timetable_search_info_card.dart | 152 +++++++++++++ .../widgets/timetable_search_page_body.dart | 4 +- 11 files changed, 627 insertions(+), 133 deletions(-) create mode 100644 lib/features/timetable_search_page/models/timetable_search_group_info.dart create mode 100644 lib/features/timetable_search_page/models/timetable_search_group_info.freezed.dart create mode 100644 lib/features/timetable_search_page/models/timetable_search_info.dart create mode 100644 lib/features/timetable_search_page/models/timetable_search_info.freezed.dart delete mode 100644 lib/features/timetable_search_page/ui/widgets/timetable_card.dart create mode 100644 lib/features/timetable_search_page/ui/widgets/timetable_search_info_card.dart diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart index a63b317..45ae383 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart @@ -31,9 +31,11 @@ class TimetablePageHeaderTimetableInfo extends ConsumerWidget { children: [ Row( children: [ - Text( - timetable?.label ?? 'Расписание', - style: labelTextStyle, + Flexible( + child: Text( + timetable?.label ?? 'Расписание', + style: labelTextStyle, + ), ), SizedBox( height: 16, diff --git a/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart b/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart index 5de02ed..c691590 100644 --- a/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart +++ b/lib/features/timetable_search_page/managers/timetable_search_page_manager.dart @@ -4,6 +4,7 @@ import 'package:chopper/chopper.dart'; import 'package:cube_system/api/cube_api.dart'; import 'package:cube_system/features/analytics/logger.dart'; import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; +import 'package:cube_system/features/timetable_search_page/models/timetable_search_group_info.dart'; import 'package:cube_system/features/timetable_search_page/state_holders/timetable_search_page_search_controller.dart'; import 'package:cube_system/features/timetable_search_page/state_holders/timetable_search_page_search_focus.dart'; import 'package:cube_system/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart'; @@ -17,6 +18,8 @@ import 'package:cube_system/features/timetable_search_page/state_holders/timetab import 'package:cube_system/features/timetable_search_page/state_holders/timetable_search_page_timer.dart'; +import 'package:cube_system/features/timetable_search_page/models/timetable_search_info.dart'; + final timetableSearchPageManager = Provider((ref) { return TimetableSearchPageManager( api: ref.watch(cubeApi), @@ -33,7 +36,7 @@ class TimetableSearchPageManager { final CubeApi api; final TimetablePageManager timetablePageManager; - final StateController> timetables; + final StateController> timetables; final StateController searchContoller; final StateController searchFocus; final StateController event; @@ -69,8 +72,8 @@ class TimetableSearchPageManager { } } - Future selectTimetable(TimetableInfo timetable) async { - await timetablePageManager.selectTimetable(timetable); + Future selectTimetable(TimetableSearchInfo timetable) async { + await timetablePageManager.selectTimetable(timetable.info); } Future instantSearch() => @@ -117,34 +120,47 @@ class TimetableSearchPageManager { return; } - final List timetablesList = []; + final List timetablesList = []; for (final group in res.groups) { timetablesList.add( - TimetableInfo( - id: group.id, - label: group.name, - type: TimetableType.group, + TimetableSearchInfo( + info: TimetableInfo( + id: group.id, + label: group.name, + type: TimetableType.group, + ), + groupInfo: TimetableSearchGroupInfo( + course: group.course, + faculty: group.faculty.shortName, + directionCipher: group.direction.cipher, + degreeStudy: group.direction.degreeStudy.value ?? '', + ), ), ); } for (final teacher in res.teachers) { timetablesList.add( - TimetableInfo( - id: teacher.id, + TimetableSearchInfo( label: teacher.fullName, - type: TimetableType.teacher, + info: TimetableInfo( + id: teacher.id, + label: teacher.shortName, + type: TimetableType.teacher, + ), ), ); } for (final place in res.places) { timetablesList.add( - TimetableInfo( - id: place.id, - label: place.name, - type: TimetableType.place, + TimetableSearchInfo( + info: TimetableInfo( + id: place.id, + label: place.name, + type: TimetableType.place, + ), ), ); } diff --git a/lib/features/timetable_search_page/models/timetable_search_group_info.dart b/lib/features/timetable_search_page/models/timetable_search_group_info.dart new file mode 100644 index 0000000..fdc3223 --- /dev/null +++ b/lib/features/timetable_search_page/models/timetable_search_group_info.dart @@ -0,0 +1,13 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'timetable_search_group_info.freezed.dart'; + +@freezed +class TimetableSearchGroupInfo with _$TimetableSearchGroupInfo { + factory TimetableSearchGroupInfo({ + required int course, + required String faculty, + required String directionCipher, + required String degreeStudy, + }) = _TimetableSearchGroupInfo; +} diff --git a/lib/features/timetable_search_page/models/timetable_search_group_info.freezed.dart b/lib/features/timetable_search_page/models/timetable_search_group_info.freezed.dart new file mode 100644 index 0000000..a5e0052 --- /dev/null +++ b/lib/features/timetable_search_page/models/timetable_search_group_info.freezed.dart @@ -0,0 +1,197 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'timetable_search_group_info.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +/// @nodoc +mixin _$TimetableSearchGroupInfo { + int get course => throw _privateConstructorUsedError; + String get faculty => throw _privateConstructorUsedError; + String get directionCipher => throw _privateConstructorUsedError; + String get degreeStudy => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $TimetableSearchGroupInfoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TimetableSearchGroupInfoCopyWith<$Res> { + factory $TimetableSearchGroupInfoCopyWith(TimetableSearchGroupInfo value, + $Res Function(TimetableSearchGroupInfo) then) = + _$TimetableSearchGroupInfoCopyWithImpl<$Res, TimetableSearchGroupInfo>; + @useResult + $Res call( + {int course, String faculty, String directionCipher, String degreeStudy}); +} + +/// @nodoc +class _$TimetableSearchGroupInfoCopyWithImpl<$Res, + $Val extends TimetableSearchGroupInfo> + implements $TimetableSearchGroupInfoCopyWith<$Res> { + _$TimetableSearchGroupInfoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? course = null, + Object? faculty = null, + Object? directionCipher = null, + Object? degreeStudy = null, + }) { + return _then(_value.copyWith( + course: null == course + ? _value.course + : course // ignore: cast_nullable_to_non_nullable + as int, + faculty: null == faculty + ? _value.faculty + : faculty // ignore: cast_nullable_to_non_nullable + as String, + directionCipher: null == directionCipher + ? _value.directionCipher + : directionCipher // ignore: cast_nullable_to_non_nullable + as String, + degreeStudy: null == degreeStudy + ? _value.degreeStudy + : degreeStudy // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_TimetableSearchGroupInfoCopyWith<$Res> + implements $TimetableSearchGroupInfoCopyWith<$Res> { + factory _$$_TimetableSearchGroupInfoCopyWith( + _$_TimetableSearchGroupInfo value, + $Res Function(_$_TimetableSearchGroupInfo) then) = + __$$_TimetableSearchGroupInfoCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int course, String faculty, String directionCipher, String degreeStudy}); +} + +/// @nodoc +class __$$_TimetableSearchGroupInfoCopyWithImpl<$Res> + extends _$TimetableSearchGroupInfoCopyWithImpl<$Res, + _$_TimetableSearchGroupInfo> + implements _$$_TimetableSearchGroupInfoCopyWith<$Res> { + __$$_TimetableSearchGroupInfoCopyWithImpl(_$_TimetableSearchGroupInfo _value, + $Res Function(_$_TimetableSearchGroupInfo) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? course = null, + Object? faculty = null, + Object? directionCipher = null, + Object? degreeStudy = null, + }) { + return _then(_$_TimetableSearchGroupInfo( + course: null == course + ? _value.course + : course // ignore: cast_nullable_to_non_nullable + as int, + faculty: null == faculty + ? _value.faculty + : faculty // ignore: cast_nullable_to_non_nullable + as String, + directionCipher: null == directionCipher + ? _value.directionCipher + : directionCipher // ignore: cast_nullable_to_non_nullable + as String, + degreeStudy: null == degreeStudy + ? _value.degreeStudy + : degreeStudy // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$_TimetableSearchGroupInfo implements _TimetableSearchGroupInfo { + _$_TimetableSearchGroupInfo( + {required this.course, + required this.faculty, + required this.directionCipher, + required this.degreeStudy}); + + @override + final int course; + @override + final String faculty; + @override + final String directionCipher; + @override + final String degreeStudy; + + @override + String toString() { + return 'TimetableSearchGroupInfo(course: $course, faculty: $faculty, directionCipher: $directionCipher, degreeStudy: $degreeStudy)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_TimetableSearchGroupInfo && + (identical(other.course, course) || other.course == course) && + (identical(other.faculty, faculty) || other.faculty == faculty) && + (identical(other.directionCipher, directionCipher) || + other.directionCipher == directionCipher) && + (identical(other.degreeStudy, degreeStudy) || + other.degreeStudy == degreeStudy)); + } + + @override + int get hashCode => + Object.hash(runtimeType, course, faculty, directionCipher, degreeStudy); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_TimetableSearchGroupInfoCopyWith<_$_TimetableSearchGroupInfo> + get copyWith => __$$_TimetableSearchGroupInfoCopyWithImpl< + _$_TimetableSearchGroupInfo>(this, _$identity); +} + +abstract class _TimetableSearchGroupInfo implements TimetableSearchGroupInfo { + factory _TimetableSearchGroupInfo( + {required final int course, + required final String faculty, + required final String directionCipher, + required final String degreeStudy}) = _$_TimetableSearchGroupInfo; + + @override + int get course; + @override + String get faculty; + @override + String get directionCipher; + @override + String get degreeStudy; + @override + @JsonKey(ignore: true) + _$$_TimetableSearchGroupInfoCopyWith<_$_TimetableSearchGroupInfo> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/features/timetable_search_page/models/timetable_search_info.dart b/lib/features/timetable_search_page/models/timetable_search_info.dart new file mode 100644 index 0000000..6ccc1f3 --- /dev/null +++ b/lib/features/timetable_search_page/models/timetable_search_info.dart @@ -0,0 +1,15 @@ +import 'package:cube_system/features/timetable_search_page/models/timetable_search_group_info.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'package:cube_system/models/timetable/timetable_info.dart'; + +part 'timetable_search_info.freezed.dart'; + +@freezed +class TimetableSearchInfo with _$TimetableSearchInfo { + factory TimetableSearchInfo({ + String? label, + required TimetableInfo info, + TimetableSearchGroupInfo? groupInfo, + }) = _TimetableSearchInfo; +} diff --git a/lib/features/timetable_search_page/models/timetable_search_info.freezed.dart b/lib/features/timetable_search_page/models/timetable_search_info.freezed.dart new file mode 100644 index 0000000..eb31f1b --- /dev/null +++ b/lib/features/timetable_search_page/models/timetable_search_info.freezed.dart @@ -0,0 +1,199 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'timetable_search_info.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +/// @nodoc +mixin _$TimetableSearchInfo { + String? get label => throw _privateConstructorUsedError; + TimetableInfo get info => throw _privateConstructorUsedError; + TimetableSearchGroupInfo? get groupInfo => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $TimetableSearchInfoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TimetableSearchInfoCopyWith<$Res> { + factory $TimetableSearchInfoCopyWith( + TimetableSearchInfo value, $Res Function(TimetableSearchInfo) then) = + _$TimetableSearchInfoCopyWithImpl<$Res, TimetableSearchInfo>; + @useResult + $Res call( + {String? label, TimetableInfo info, TimetableSearchGroupInfo? groupInfo}); + + $TimetableInfoCopyWith<$Res> get info; + $TimetableSearchGroupInfoCopyWith<$Res>? get groupInfo; +} + +/// @nodoc +class _$TimetableSearchInfoCopyWithImpl<$Res, $Val extends TimetableSearchInfo> + implements $TimetableSearchInfoCopyWith<$Res> { + _$TimetableSearchInfoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? label = freezed, + Object? info = null, + Object? groupInfo = freezed, + }) { + return _then(_value.copyWith( + label: freezed == label + ? _value.label + : label // ignore: cast_nullable_to_non_nullable + as String?, + info: null == info + ? _value.info + : info // ignore: cast_nullable_to_non_nullable + as TimetableInfo, + groupInfo: freezed == groupInfo + ? _value.groupInfo + : groupInfo // ignore: cast_nullable_to_non_nullable + as TimetableSearchGroupInfo?, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $TimetableInfoCopyWith<$Res> get info { + return $TimetableInfoCopyWith<$Res>(_value.info, (value) { + return _then(_value.copyWith(info: value) as $Val); + }); + } + + @override + @pragma('vm:prefer-inline') + $TimetableSearchGroupInfoCopyWith<$Res>? get groupInfo { + if (_value.groupInfo == null) { + return null; + } + + return $TimetableSearchGroupInfoCopyWith<$Res>(_value.groupInfo!, (value) { + return _then(_value.copyWith(groupInfo: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$_TimetableSearchInfoCopyWith<$Res> + implements $TimetableSearchInfoCopyWith<$Res> { + factory _$$_TimetableSearchInfoCopyWith(_$_TimetableSearchInfo value, + $Res Function(_$_TimetableSearchInfo) then) = + __$$_TimetableSearchInfoCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String? label, TimetableInfo info, TimetableSearchGroupInfo? groupInfo}); + + @override + $TimetableInfoCopyWith<$Res> get info; + @override + $TimetableSearchGroupInfoCopyWith<$Res>? get groupInfo; +} + +/// @nodoc +class __$$_TimetableSearchInfoCopyWithImpl<$Res> + extends _$TimetableSearchInfoCopyWithImpl<$Res, _$_TimetableSearchInfo> + implements _$$_TimetableSearchInfoCopyWith<$Res> { + __$$_TimetableSearchInfoCopyWithImpl(_$_TimetableSearchInfo _value, + $Res Function(_$_TimetableSearchInfo) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? label = freezed, + Object? info = null, + Object? groupInfo = freezed, + }) { + return _then(_$_TimetableSearchInfo( + label: freezed == label + ? _value.label + : label // ignore: cast_nullable_to_non_nullable + as String?, + info: null == info + ? _value.info + : info // ignore: cast_nullable_to_non_nullable + as TimetableInfo, + groupInfo: freezed == groupInfo + ? _value.groupInfo + : groupInfo // ignore: cast_nullable_to_non_nullable + as TimetableSearchGroupInfo?, + )); + } +} + +/// @nodoc + +class _$_TimetableSearchInfo implements _TimetableSearchInfo { + _$_TimetableSearchInfo({this.label, required this.info, this.groupInfo}); + + @override + final String? label; + @override + final TimetableInfo info; + @override + final TimetableSearchGroupInfo? groupInfo; + + @override + String toString() { + return 'TimetableSearchInfo(label: $label, info: $info, groupInfo: $groupInfo)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_TimetableSearchInfo && + (identical(other.label, label) || other.label == label) && + (identical(other.info, info) || other.info == info) && + (identical(other.groupInfo, groupInfo) || + other.groupInfo == groupInfo)); + } + + @override + int get hashCode => Object.hash(runtimeType, label, info, groupInfo); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_TimetableSearchInfoCopyWith<_$_TimetableSearchInfo> get copyWith => + __$$_TimetableSearchInfoCopyWithImpl<_$_TimetableSearchInfo>( + this, _$identity); +} + +abstract class _TimetableSearchInfo implements TimetableSearchInfo { + factory _TimetableSearchInfo( + {final String? label, + required final TimetableInfo info, + final TimetableSearchGroupInfo? groupInfo}) = _$_TimetableSearchInfo; + + @override + String? get label; + @override + TimetableInfo get info; + @override + TimetableSearchGroupInfo? get groupInfo; + @override + @JsonKey(ignore: true) + _$$_TimetableSearchInfoCopyWith<_$_TimetableSearchInfo> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart b/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart index cb25d7e..9ff51e7 100644 --- a/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart +++ b/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart @@ -1,6 +1,9 @@ import 'package:cube_system/models/timetable/timetable_info.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -final timetableSearchPageTimetables = StateProvider>((ref) { +import 'package:cube_system/features/timetable_search_page/models/timetable_search_info.dart'; + +final timetableSearchPageTimetables = + StateProvider>((ref) { return []; }); diff --git a/lib/features/timetable_search_page/ui/timetable_search_page.dart b/lib/features/timetable_search_page/ui/timetable_search_page.dart index 590fe2d..9a678a1 100644 --- a/lib/features/timetable_search_page/ui/timetable_search_page.dart +++ b/lib/features/timetable_search_page/ui/timetable_search_page.dart @@ -25,10 +25,18 @@ class _TimetableSearchPage extends ConsumerStatefulWidget { } class _TimetableSearchPageState extends ConsumerState<_TimetableSearchPage> { + @override + void initState() { + super.initState(); + + Future(() { + ref.read(timetableSearchPageManager).handleWelcome(); + }); + } + @override Widget build(BuildContext context) { final manager = ref.watch(timetableSearchPageManager); - manager.handleWelcome(); return Scaffold( body: SafeArea( diff --git a/lib/features/timetable_search_page/ui/widgets/timetable_card.dart b/lib/features/timetable_search_page/ui/widgets/timetable_card.dart deleted file mode 100644 index 5a81c24..0000000 --- a/lib/features/timetable_search_page/ui/widgets/timetable_card.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'package:cube_system/models/timetable/timetable_info.dart'; -import 'package:cube_system/styles/app_theme_context_extension.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:cube_system/models/timetable/timetable_type.dart'; - -class TimetableCard extends ConsumerWidget { - final TimetableInfo timetable; - - final VoidCallback onTap; - - const TimetableCard({ - required this.timetable, - required this.onTap, - super.key, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final Color color; - final Widget icon; - - switch (timetable.type) { - case TimetableType.group: - color = const Color(0xFF1aaf5c); - icon = Icon( - Icons.people_alt_rounded, - color: context.colors.white, - size: 18, - ); - break; - case TimetableType.teacher: - color = const Color(0xFF488aff); - icon = Icon( - Icons.person, - color: context.colors.white, - size: 18, - ); - break; - case TimetableType.place: - color = const Color(0xFFfa601f); - icon = Padding( - padding: const EdgeInsets.only(left: 1, top: 1), - child: Icon( - Icons.sell, - color: context.colors.white, - size: 18, - ), - ); - break; - } - - return Container( - decoration: BoxDecoration( - color: context.colors.background, - borderRadius: BorderRadius.circular(8), - boxShadow: [ - BoxShadow( - color: context.colors.shadow, - blurRadius: 12, - offset: const Offset(0, 2), - ) - ], - ), - clipBehavior: Clip.antiAlias, - child: Material( - type: MaterialType.transparency, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(8), - child: Row( - children: [ - Container( - height: 32, - width: 32, - margin: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: color.withOpacity(0.75), - shape: BoxShape.circle, - ), - child: icon, - ), - const SizedBox(width: 8), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - timetable.label, - style: context.textStyles.label, - ), - const SizedBox(height: 1), - Text( - timetable.type.label, - style: context.textStyles.smallSubTitle.copyWith( - color: context.colors.subduedText, - ), - ), - ], - ), - ) - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/features/timetable_search_page/ui/widgets/timetable_search_info_card.dart b/lib/features/timetable_search_page/ui/widgets/timetable_search_info_card.dart new file mode 100644 index 0000000..718b84a --- /dev/null +++ b/lib/features/timetable_search_page/ui/widgets/timetable_search_info_card.dart @@ -0,0 +1,152 @@ +import 'package:cube_system/styles/app_theme_context_extension.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:cube_system/models/timetable/timetable_type.dart'; + +import 'package:cube_system/features/timetable_search_page/models/timetable_search_info.dart'; + +class TimetableSearchInfoCard extends ConsumerWidget { + final TimetableSearchInfo timetable; + + final VoidCallback onTap; + + const TimetableSearchInfoCard({ + required this.timetable, + required this.onTap, + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final Color color; + final Widget icon; + + switch (timetable.info.type) { + case TimetableType.group: + color = const Color(0xFF1aaf5c); + icon = Icon( + Icons.people_alt_rounded, + color: context.colors.white, + size: 18, + ); + break; + case TimetableType.teacher: + color = const Color(0xFF488aff); + icon = Icon( + Icons.person, + color: context.colors.white, + size: 18, + ); + break; + case TimetableType.place: + color = const Color(0xFFfa601f); + icon = Padding( + padding: const EdgeInsets.only(left: 1, top: 1), + child: Icon( + Icons.sell, + color: context.colors.white, + size: 18, + ), + ); + break; + } + + return Container( + decoration: BoxDecoration( + color: context.colors.background, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: context.colors.shadow, + blurRadius: 12, + offset: const Offset(0, 2), + ) + ], + ), + clipBehavior: Clip.antiAlias, + child: Material( + type: MaterialType.transparency, + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), + child: SizedBox( + height: 38, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + Container( + height: 32, + width: 32, + margin: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: color.withOpacity(0.75), + shape: BoxShape.circle, + ), + child: icon, + ), + const SizedBox(width: 8), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + timetable.label ?? timetable.info.label, + style: context.textStyles.label, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 1), + Text( + timetable.info.type.label, + style: + context.textStyles.smallSubTitle.copyWith( + color: context.colors.subduedText, + ), + ), + ], + ), + ), + ], + ), + ), + if (timetable.info.type.isGroup) + Flexible( + child: Padding( + padding: const EdgeInsets.only(right: 6), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + timetable.groupInfo!.faculty, + style: context.textStyles.smallSubTitle.copyWith( + color: context.colors.subduedText, + ), + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 1), + Text( + '${timetable.groupInfo!.degreeStudy}, ${timetable.groupInfo!.directionCipher}', + style: context.textStyles.smallSubTitle.copyWith( + color: context.colors.subduedText, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/features/timetable_search_page/ui/widgets/timetable_search_page_body.dart b/lib/features/timetable_search_page/ui/widgets/timetable_search_page_body.dart index 938a270..ea7a183 100644 --- a/lib/features/timetable_search_page/ui/widgets/timetable_search_page_body.dart +++ b/lib/features/timetable_search_page/ui/widgets/timetable_search_page_body.dart @@ -1,6 +1,6 @@ import 'package:cube_system/features/timetable_search_page/state_holders/timetable_search_page_event.dart'; import 'package:cube_system/features/timetable_search_page/ui/event_pages/no_found_search_event_page.dart'; -import 'package:cube_system/features/timetable_search_page/ui/widgets/timetable_card.dart'; +import 'package:cube_system/features/timetable_search_page/ui/widgets/timetable_search_info_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -53,7 +53,7 @@ class TimetableSearchPageBody extends ConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), itemBuilder: (context, index) { final timetable = timetables[index]; - return TimetableCard( + return TimetableSearchInfoCard( timetable: timetable, onTap: () async { manager.selectTimetable(timetable); From 3481c7ea9514c0646da55a00d0cace9008818246 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 01:32:59 +0300 Subject: [PATCH 11/21] Week label only for groups --- .../widgets/timetable_page_header_date.dart | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart index 7947498..e15809e 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header_date.dart @@ -7,6 +7,8 @@ import 'package:intl/intl.dart'; import 'package:cube_system/features/date_time_contol/state_holders/current_date_time_state_holders.dart'; import 'package:cube_system/features/timetable_page/features/week_timeline/state_holders/week_timeline_shown_week_date.dart'; +import 'package:cube_system/features/timetable_page/state_holders/selected_timetable.dart'; + class TimetablePageHeaderDate extends ConsumerWidget { const TimetablePageHeaderDate({super.key}); @@ -23,6 +25,11 @@ class TimetablePageHeaderDate extends ConsumerWidget { weekLabel = 'Знаменатель'; } + final isGroup = ref.watch( + selectedTimetableStateHolder + .select((value) => value?.type.isGroup ?? false), + ); + return InkWell( borderRadius: const BorderRadius.all(Radius.circular(12)), child: Column( @@ -40,14 +47,15 @@ class TimetablePageHeaderDate extends ConsumerWidget { style: context.textStyles.label.copyWith(), textAlign: TextAlign.center, ), - Text( - weekLabel, - style: context.textStyles.smallSubTitle.copyWith( - fontSize: 10, - color: context.colors.subduedText, + if (isGroup) + Text( + weekLabel, + style: context.textStyles.smallSubTitle.copyWith( + fontSize: 10, + color: context.colors.subduedText, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), ], ), ); From 8b828a6d547d55f70158db53811bd7a2a40166a8 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 01:39:05 +0300 Subject: [PATCH 12/21] Fix check lesson collision --- .../managers/timetable_lessons_manager.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/features/timetable_page/managers/timetable_lessons_manager.dart b/lib/features/timetable_page/managers/timetable_lessons_manager.dart index 38848ad..5df9dd3 100644 --- a/lib/features/timetable_page/managers/timetable_lessons_manager.dart +++ b/lib/features/timetable_page/managers/timetable_lessons_manager.dart @@ -123,9 +123,12 @@ class TimetableLessonsManager { final lesson = lessons[i]; int emptyLessonsBefore = 0; - final equalPrevious = i > 0 && lessons[i - 1].number == lesson.number; - final equalNext = - i < lessons.length - 1 && lessons[i + 1].number == lesson.number; + final equalPrevious = i > 0 && + lessons[i - 1].number == lesson.number && + lessons[i - 1].date == lesson.date; + final equalNext = i < lessons.length - 1 && + lessons[i + 1].number == lesson.number && + lessons[i + 1].date == lesson.date; final isCollision = equalPrevious || equalNext; From 635447a1718a1be56ebc0e213854743597dc95e1 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 02:50:57 +0300 Subject: [PATCH 13/21] TimetablePageMessageCard draft --- .../ui/widgets/timetable_page_day.dart | 17 +++- .../widgets/timetable_page_message_card.dart | 92 +++++++++++++++++++ lib/ui/ui_kit/app_button.dart | 59 ++++++------ 3 files changed, 138 insertions(+), 30 deletions(-) create mode 100644 lib/features/timetable_page/ui/widgets/timetable_page_message_card.dart diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart index 6cc2481..41f9f61 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart @@ -1,5 +1,6 @@ import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; import 'package:cube_system/features/timetable_page/state_holders/timetable_page_events.dart'; +import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_message_card.dart'; import 'package:cube_system/models/timetable_day/timetable_day_type.dart'; import 'package:cube_system/features/timetable_page/ui/event_pages/weekend_event_page.dart'; import 'package:flutter/material.dart'; @@ -76,8 +77,20 @@ class TimetablePageDay extends ConsumerWidget { physics: const BouncingScrollPhysics( parent: AlwaysScrollableScrollPhysics(), ), - itemCount: lessons.length, - itemBuilder: (context, index) => LessonCard(lessons[index]), + itemCount: lessons.length + 1, + itemBuilder: (context, index) { + if (index == lessons.length) { + return const Padding( + padding: EdgeInsets.only(top: 9), + child: TimetablePageMessageCard(), + ); + } + final lesson = lessons[index]; + return LessonCard( + key: ValueKey(lesson), + lesson, + ); + }, separatorBuilder: (context, index) => const SizedBox(height: 11), ); } diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_message_card.dart b/lib/features/timetable_page/ui/widgets/timetable_page_message_card.dart new file mode 100644 index 0000000..cd5ebf0 --- /dev/null +++ b/lib/features/timetable_page/ui/widgets/timetable_page_message_card.dart @@ -0,0 +1,92 @@ +import 'package:cube_system/styles/app_theme_context_extension.dart'; +import 'package:cube_system/ui/ui_kit/app_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class TimetablePageMessageCard extends ConsumerWidget { + const TimetablePageMessageCard({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + color: context.colors.background, + boxShadow: [ + BoxShadow( + color: context.colors.shadow, + blurRadius: 12, + offset: const Offset(0, 1), + ) + ], + ), + padding: const EdgeInsets.only(left: 12, right: 4, top: 4, bottom: 12), + child: Material( + type: MaterialType.transparency, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + Text( + 'Информация о ближайших выходных днях', + style: context.textStyles.subTitle.copyWith( + // color: context.colors.subduedText, + ), + ), + const SizedBox(height: 8), + Text( + '''Студенты и работники КубГУ отдыхают: +• 25 апреля +• 1, 8 и 9 мая''', + style: context.textStyles.smallSubTitle.copyWith( + color: context.colors.subduedText, + ), + ), + // const SizedBox(height: 8), + // Text( + // 'Кому интересно, приходите 26 апреля в 14.10 в ауд. А424. Для записи на семинар заполните форму.', + // style: context.textStyles.smallSubTitle.copyWith( + // color: context.colors.subduedText, + // ), + // ), + // const SizedBox(height: 7), + // Text( + // 'https://forms.gle/3hRh6kQajuYBjbcW9', + // style: context.textStyles.smallSubTitle.copyWith( + // color: context.colors.primary, + // decoration: TextDecoration.underline, + // ), + // ), + const SizedBox(height: 12), + AppButton( + height: 32, + isExpanded: true, + style: AppButtonStyle.secondary, + onTap: () {}, + text: 'Понятно', + ) + ], + ), + ), + InkWell( + onTap: () {}, + borderRadius: BorderRadius.circular(99), + child: Padding( + padding: const EdgeInsets.all(8), + child: Icon( + Icons.close_rounded, + color: context.colors.text, + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/ui/ui_kit/app_button.dart b/lib/ui/ui_kit/app_button.dart index 054c179..50fd859 100644 --- a/lib/ui/ui_kit/app_button.dart +++ b/lib/ui/ui_kit/app_button.dart @@ -72,34 +72,37 @@ class AppButton extends StatelessWidget { ); } - return DecoratedBox( - decoration: BoxDecoration( - boxShadow: [ - if (style.isPrimary && onTap != null) - BoxShadow( - color: context.colors.primary.withOpacity(0.3), - offset: const Offset(0, 1), - blurRadius: 8, - ) - ], - borderRadius: BorderRadius.circular(8), - ), - child: GestureDetector( - onTap: isDisabled ? onDisabledTap : null, - child: TextButton( - onPressed: onTap, - style: buttonStyle, - child: rightIcon == null - ? Text(text ?? '') - : Stack( - children: [ - Center(child: Text(text ?? '')), - Align( - alignment: Alignment.centerRight, - child: rightIcon!, - ), - ], - ), + return SizedBox( + height: height, + child: DecoratedBox( + decoration: BoxDecoration( + boxShadow: [ + if (style.isPrimary && onTap != null) + BoxShadow( + color: context.colors.primary.withOpacity(0.3), + offset: const Offset(0, 1), + blurRadius: 8, + ) + ], + borderRadius: BorderRadius.circular(8), + ), + child: GestureDetector( + onTap: isDisabled ? onDisabledTap : null, + child: TextButton( + onPressed: onTap, + style: buttonStyle, + child: rightIcon == null + ? Text(text ?? '') + : Stack( + children: [ + Center(child: Text(text ?? '')), + Align( + alignment: Alignment.centerRight, + child: rightIcon!, + ), + ], + ), + ), ), ), ); From 8b8d802ab4a1966aa096547b0f748d0df6e3f453 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 19:21:10 +0300 Subject: [PATCH 14/21] Edit text in LandingWelcomePage --- .../landing_page/ui/widgets/landing_welcome_page.dart | 4 ++-- .../timetable_page/ui/widgets/timetable_page_day.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/features/landing_page/ui/widgets/landing_welcome_page.dart b/lib/features/landing_page/ui/widgets/landing_welcome_page.dart index 659a985..7cc3ba2 100644 --- a/lib/features/landing_page/ui/widgets/landing_welcome_page.dart +++ b/lib/features/landing_page/ui/widgets/landing_welcome_page.dart @@ -144,7 +144,7 @@ class _LandingWelcomePageState extends ConsumerState ], ), Text( - "Расписание", + 'Расписание', style: context.textStyles.largeTitle.copyWith( fontSize: 32, color: context.colors.text, @@ -156,7 +156,7 @@ class _LandingWelcomePageState extends ConsumerState ), const SizedBox(height: 48), Text( - "Организуйте свою академическую жизнь c современным электронным расписанием: актуальность, легкий доступ и приятный дизайн для студентов и преподавателей.", + 'Cовременный сервис учебного расписания для студентов, преподавателей и всех желающих, предоставляющий удобный и быстрый доступ, где бы вы ни находились.', style: context.textStyles.subTitle.copyWith( fontSize: 16, ), diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart index 41f9f61..1725c12 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_day.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_day.dart @@ -1,6 +1,5 @@ import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; import 'package:cube_system/features/timetable_page/state_holders/timetable_page_events.dart'; -import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_message_card.dart'; import 'package:cube_system/models/timetable_day/timetable_day_type.dart'; import 'package:cube_system/features/timetable_page/ui/event_pages/weekend_event_page.dart'; import 'package:flutter/material.dart'; @@ -82,7 +81,8 @@ class TimetablePageDay extends ConsumerWidget { if (index == lessons.length) { return const Padding( padding: EdgeInsets.only(top: 9), - child: TimetablePageMessageCard(), + // child: TimetablePageMessageCard(), + child: SizedBox(), ); } final lesson = lessons[index]; From 5ead15acae8f7c8ada6e339ac9064de5f1c8b321 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 19:40:32 +0300 Subject: [PATCH 15/21] Bump version to 0.8.0+4 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d425ff4..f9a02f1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: cube_system description: Modern electronic timetable publish_to: 'none' -version: 0.7.0+3 +version: 0.8.0+4 environment: sdk: '>=2.19.2 <3.0.0' From 8531dcd749532f0f80262f5dc08e745407bae5d1 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 20:13:13 +0300 Subject: [PATCH 16/21] Swap AppSplash and MainApp in main.dart --- lib/main.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5f6f609..2b741e0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,10 +33,10 @@ void main() async { ]); }, builder: (context, snapshot, _) { - if (snapshot.connectionState == ConnectionState.done) { - return const ProviderScope(child: MainApp()); + if (snapshot.connectionState != ConnectionState.done) { + return const AppSplash(); } - return const AppSplash(); + return const ProviderScope(child: MainApp()); }, ), onFlutterError: logger.flutterError, From 8f05c5a66d77ba8e58aea67fa51940eef9fd3f36 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 20:13:55 +0300 Subject: [PATCH 17/21] Test Upgrader --- lib/ui/main_app.dart | 14 +++++-- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 40 +++++++++++++++++++ pubspec.yaml | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/lib/ui/main_app.dart b/lib/ui/main_app.dart index 7838092..69604ba 100644 --- a/lib/ui/main_app.dart +++ b/lib/ui/main_app.dart @@ -10,6 +10,7 @@ import 'package:cube_system/features/navigation/router/app_router.dart'; import 'package:cube_system/styles/app_colors/app_colors.dart'; import 'package:cube_system/styles/app_text_styles/app_text_styles.dart'; import 'package:cube_system/styles/app_theme.dart'; +import 'package:upgrader/upgrader.dart'; class MainApp extends ConsumerWidget { const MainApp({super.key}); @@ -25,10 +26,15 @@ class MainApp extends ConsumerWidget { builder: (context) => MaterialApp.router( debugShowCheckedModeBanner: false, locale: DevicePreview.locale(context), - builder: (context, child) => Scaffold( - resizeToAvoidBottomInset: false, - body: FadeAnimatedWidget( - child: DevicePreview.appBuilder(context, child), + builder: (context, child) => UpgradeAlert( + upgrader: Upgrader( + countryCode: 'RU', + ), + child: Scaffold( + resizeToAvoidBottomInset: false, + body: FadeAnimatedWidget( + child: DevicePreview.appBuilder(context, child), + ), ), ), scrollBehavior: AppScrollBehavior(), diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 802712b..3e13a20 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import device_info_plus import package_info_plus import path_provider_foundation import rive_common @@ -13,6 +14,7 @@ import url_launcher_macos import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 98207da..f8c3595 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -297,6 +297,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 + url: "https://pub.dev" + source: hosted + version: "8.2.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" device_preview: dependency: "direct main" description: @@ -661,6 +677,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + os_detect: + dependency: transitive + description: + name: os_detect + sha256: faf3bcf39515e64da8ff76b2f2805b20a6ff47ae515393e535f8579ff91d6b7f + url: "https://pub.dev" + source: hosted + version: "2.0.1" package_config: dependency: transitive description: @@ -1107,6 +1131,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + upgrader: + dependency: "direct main" + description: + name: upgrader + sha256: "3c61e3a99184e60947d2b2d93c1b5243a98a634aa6cc852d49dfaaeb9f42a7b5" + url: "https://pub.dev" + source: hosted + version: "6.3.0" url_launcher: dependency: "direct main" description: @@ -1211,6 +1243,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + version: + dependency: transitive + description: + name: version + sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94" + url: "https://pub.dev" + source: hosted + version: "3.0.2" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f9a02f1..f689be4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: package_info_plus: ^3.1.0 flutter_dotenv: ^5.0.2 appmetrica_plugin: ^1.1.0 + upgrader: ^6.3.0 From 7c78cb1401fafe2bf048b81a1489c5bda87ea7c9 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 21:07:12 +0300 Subject: [PATCH 18/21] Edit text in KsrsEventPage --- .../timetable_page/ui/event_pages/ksrs_event_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/timetable_page/ui/event_pages/ksrs_event_page.dart b/lib/features/timetable_page/ui/event_pages/ksrs_event_page.dart index 753bcb9..9776ebd 100644 --- a/lib/features/timetable_page/ui/event_pages/ksrs_event_page.dart +++ b/lib/features/timetable_page/ui/event_pages/ksrs_event_page.dart @@ -11,8 +11,8 @@ class KsrsEventPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return AppEventPage( picture: Assets.brooklyn.rest3.svg(), - title: 'В этот день пар нет', - subTitle: 'Можно отдохнуть', + title: 'КСРС', + subTitle: 'Контролируемая самостоятельная работа студентов', ); } } From 754772b17138bf2b8c227b6cf1f8fecce9e20c52 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 21:55:30 +0300 Subject: [PATCH 19/21] LessonCardInfoPanel --- .../features/lesson_card/ui/lesson_card.dart | 7 +- .../lesson_card_info_panel.dart} | 67 ++++++++----------- .../lesson_card_info_panel_chip.dart | 44 ++++++++++++ .../lesson_card_info_panel_icon.dart | 50 ++++++++++++++ .../ui/widgets/lesson_card_icons_icon.dart | 63 ----------------- .../managers/lesson_convertor.dart | 3 +- lib/models/lesson/lesson.dart | 1 + lib/models/lesson/lesson.freezed.dart | 27 +++++++- lib/models/lesson/lesson.g.dart | 5 +- 9 files changed, 160 insertions(+), 107 deletions(-) rename lib/features/timetable_page/features/lesson_card/ui/widgets/{lesson_card_icons.dart => info_panel/lesson_card_info_panel.dart} (53%) create mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart create mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart delete mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart diff --git a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart index 09ef494..17b730d 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart @@ -27,8 +27,9 @@ import 'package:cube_system/features/timetable_page/state_holders/lessons/next_l part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_body.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart'; -part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart'; -part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart'; +part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart'; +part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart'; +part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_indicator.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/next_lesson_time_to_start_progress_bar.dart'; @@ -125,7 +126,7 @@ class LessonCard extends ConsumerWidget { const Positioned( top: 0, right: 8, - child: LessonCardIcons(), + child: LessonCardInfoPanel(), ), ], ), diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart similarity index 53% rename from lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart rename to lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart index 7dcd0de..92f03d7 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart @@ -1,21 +1,21 @@ part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; -class LessonCardIcons extends ConsumerWidget { - const LessonCardIcons({super.key}); +class LessonCardInfoPanel extends ConsumerWidget { + const LessonCardInfoPanel({super.key}); static final _random = Random(); @override Widget build(BuildContext context, WidgetRef ref) { - final color = - ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - final isRemotely = ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); final isCollision = ref.watch(_lessonInLessonCard.select((value) => value.isCollision)); + final isCancelled = + ref.watch(_lessonInLessonCard.select((value) => value.isCancelled)); + final isActiveLessons = ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); @@ -23,7 +23,7 @@ class LessonCardIcons extends ConsumerWidget { // final isRemotely = _random.nextInt(100) < 25; - final isCancelled = _random.nextInt(100) < 0; + // final isCancelled = _random.nextInt(100) < 0; final presentImportantNote = _random.nextInt(100) < 0; @@ -31,27 +31,17 @@ class LessonCardIcons extends ConsumerWidget { return Row( children: [ - if (isCancelled) - const LessonCardIconsIcon.icon( - icon: Icon(Icons.cancel), - isDestructive: true, - ), - if (isCollision) - const LessonCardIconsIcon.icon( - icon: Icon(Icons.error), - isDestructive: true, - ), if (isRemotely) - const LessonCardIconsIcon.icon( + const LessonCardInfoPanelIcon( icon: Icon(Icons.home), ), if (presentImportantNote) - const LessonCardIconsIcon.icon( + const LessonCardInfoPanelIcon( icon: Icon(Icons.priority_high_rounded), ), if (numberOfNotes > 0) - LessonCardIconsIcon.number( - number: numberOfNotes, + LessonCardInfoPanelIcon( + icon: Text('$numberOfNotes'), ), if (isActiveLessons) Consumer( @@ -64,26 +54,27 @@ class LessonCardIcons extends ConsumerWidget { final hasHours = (ref.read(currentLessonTimeToEndProvider)?.hours ?? 0) > 0; - return Container( - margin: const EdgeInsets.only(right: 4), - padding: - const EdgeInsets.symmetric(vertical: 1.5, horizontal: 5), - constraints: BoxConstraints( - minWidth: hasHours ? 66 : 46, - ), - decoration: BoxDecoration( - color: color, - borderRadius: const BorderRadius.all(Radius.circular(16)), - ), - child: const Center( - child: Padding( - padding: EdgeInsets.only(top: 0.5, left: 0), - child: LessonCardTimeLeft(), - ), - ), - ); + return hasHours + ? const LessonCardInfoPanelChip( + minWidth: 66, + text: LessonCardTimeLeft(), + ) + : const LessonCardInfoPanelChip( + minWidth: 46, + text: LessonCardTimeLeft(), + ); }, ), + if (isCollision) + const LessonCardInfoPanelChip( + text: Text('Коллизия'), + isDestructive: true, + ), + if (isCancelled) + const LessonCardInfoPanelChip( + text: Text('Отменено'), + isDestructive: true, + ), ], ); } diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart new file mode 100644 index 0000000..afd3edb --- /dev/null +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart @@ -0,0 +1,44 @@ +part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; + +class LessonCardInfoPanelChip extends ConsumerWidget { + final Widget text; + final bool isDestructive; + final double minWidth; + final Color? color; + + const LessonCardInfoPanelChip({ + super.key, + required this.text, + this.isDestructive = false, + this.minWidth = 0, + this.color, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final backgroundColor = isDestructive + ? context.colors.destructive + : color ?? + ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + + return Container( + margin: const EdgeInsets.only(right: 4), + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 6), + constraints: BoxConstraints(minWidth: minWidth), + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + child: Center( + child: Padding( + padding: const EdgeInsets.only(top: 0.5, left: 0), + child: DefaultTextStyle( + style: context.textStyles.chipLabel + .copyWith(color: context.colors.white), + child: text, + ), + ), + ), + ); + } +} diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart new file mode 100644 index 0000000..0101dd4 --- /dev/null +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart @@ -0,0 +1,50 @@ +part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; + +class LessonCardInfoPanelIcon extends ConsumerWidget { + final Widget icon; + final bool isDestructive; + final Color? color; + + const LessonCardInfoPanelIcon({ + super.key, + required this.icon, + this.isDestructive = false, + this.color, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final backgroundColor = isDestructive + ? context.colors.destructive + : color ?? + ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); + + return Container( + margin: const EdgeInsets.only(right: 4), + width: 18, + height: 18, + decoration: BoxDecoration( + color: backgroundColor, + shape: BoxShape.circle, + ), + child: Center( + child: DefaultTextStyle( + style: context.textStyles.chipLabel + .copyWith(color: context.colors.white), + child: IconTheme( + data: Theme.of(context).iconTheme.copyWith( + size: 13.5, + color: context.colors.white, + ), + child: Padding( + padding: icon is Text + ? const EdgeInsets.only(left: 0.4) + : const EdgeInsets.only(bottom: 1, right: 0.2), + child: icon, + ), + ), + ), + ), + ); + } +} diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart deleted file mode 100644 index 3e7131f..0000000 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_icons_icon.dart +++ /dev/null @@ -1,63 +0,0 @@ -part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; - -class LessonCardIconsIcon extends ConsumerWidget { - final int? number; - final Widget? icon; - final bool isDestructive; - final Color? color; - - const LessonCardIconsIcon.number({ - super.key, - required this.number, - this.isDestructive = false, - this.color, - }) : icon = null; - - const LessonCardIconsIcon.icon({ - super.key, - required this.icon, - this.isDestructive = false, - this.color, - }) : number = null; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final backgroundColor = isDestructive - ? context.colors.destructive - : color ?? - ref.watch(appLessonColorByLesson(ref.read(_lessonInLessonCard))); - - return Container( - margin: const EdgeInsets.only(right: 4), - width: 18, - height: 18, - decoration: BoxDecoration( - color: backgroundColor, - shape: BoxShape.circle, - ), - child: Center( - child: number != null - ? Padding( - padding: const EdgeInsets.only(left: 0.5), - child: Text( - number!.toString(), - style: context.textStyles.chipLabel - .copyWith(color: context.colors.white), - ), - ) - : icon != null - ? IconTheme( - data: Theme.of(context).iconTheme.copyWith( - size: 13.5, - color: context.colors.white, - ), - child: Padding( - padding: const EdgeInsets.only(bottom: 1, right: 0.2), - child: icon!, - ), - ) - : null, - ), - ); - } -} diff --git a/lib/features/timetable_page/managers/lesson_convertor.dart b/lib/features/timetable_page/managers/lesson_convertor.dart index aa3d2d7..1b6141b 100644 --- a/lib/features/timetable_page/managers/lesson_convertor.dart +++ b/lib/features/timetable_page/managers/lesson_convertor.dart @@ -90,9 +90,10 @@ class LessonConvertor { isElective: lesson.isElective, isRemotely: lesson.isRemotely, isEvent: isEvent, + isCollision: isCollision, + isCancelled: lesson.status == LessonStatus.value_3, defaultColor: color, emptyLessonsBefore: emptyLessonsBefore, - isCollision: isCollision, ); return newLesson; diff --git a/lib/models/lesson/lesson.dart b/lib/models/lesson/lesson.dart index d7e5256..3ce2cd4 100644 --- a/lib/models/lesson/lesson.dart +++ b/lib/models/lesson/lesson.dart @@ -26,6 +26,7 @@ class Lesson with _$Lesson { @HiveField(10) required bool isElective, @HiveField(11) required bool isEvent, @HiveField(14, defaultValue: false) required bool isCollision, + @HiveField(15, defaultValue: false) required bool isCancelled, @HiveField(12) required Color defaultColor, @HiveField(13) required int emptyLessonsBefore, }) = _Lesson; diff --git a/lib/models/lesson/lesson.freezed.dart b/lib/models/lesson/lesson.freezed.dart index 72f0f92..5853bc3 100644 --- a/lib/models/lesson/lesson.freezed.dart +++ b/lib/models/lesson/lesson.freezed.dart @@ -42,6 +42,8 @@ mixin _$Lesson { bool get isEvent => throw _privateConstructorUsedError; @HiveField(14, defaultValue: false) bool get isCollision => throw _privateConstructorUsedError; + @HiveField(15, defaultValue: false) + bool get isCancelled => throw _privateConstructorUsedError; @HiveField(12) Color get defaultColor => throw _privateConstructorUsedError; @HiveField(13) @@ -70,6 +72,7 @@ abstract class $LessonCopyWith<$Res> { @HiveField(10) bool isElective, @HiveField(11) bool isEvent, @HiveField(14, defaultValue: false) bool isCollision, + @HiveField(15, defaultValue: false) bool isCancelled, @HiveField(12) Color defaultColor, @HiveField(13) int emptyLessonsBefore}); @@ -103,6 +106,7 @@ class _$LessonCopyWithImpl<$Res, $Val extends Lesson> Object? isElective = null, Object? isEvent = null, Object? isCollision = null, + Object? isCancelled = null, Object? defaultColor = null, Object? emptyLessonsBefore = null, }) { @@ -159,6 +163,10 @@ class _$LessonCopyWithImpl<$Res, $Val extends Lesson> ? _value.isCollision : isCollision // ignore: cast_nullable_to_non_nullable as bool, + isCancelled: null == isCancelled + ? _value.isCancelled + : isCancelled // ignore: cast_nullable_to_non_nullable + as bool, defaultColor: null == defaultColor ? _value.defaultColor : defaultColor // ignore: cast_nullable_to_non_nullable @@ -207,6 +215,7 @@ abstract class _$$_LessonCopyWith<$Res> implements $LessonCopyWith<$Res> { @HiveField(10) bool isElective, @HiveField(11) bool isEvent, @HiveField(14, defaultValue: false) bool isCollision, + @HiveField(15, defaultValue: false) bool isCancelled, @HiveField(12) Color defaultColor, @HiveField(13) int emptyLessonsBefore}); @@ -239,6 +248,7 @@ class __$$_LessonCopyWithImpl<$Res> Object? isElective = null, Object? isEvent = null, Object? isCollision = null, + Object? isCancelled = null, Object? defaultColor = null, Object? emptyLessonsBefore = null, }) { @@ -295,6 +305,10 @@ class __$$_LessonCopyWithImpl<$Res> ? _value.isCollision : isCollision // ignore: cast_nullable_to_non_nullable as bool, + isCancelled: null == isCancelled + ? _value.isCancelled + : isCancelled // ignore: cast_nullable_to_non_nullable + as bool, defaultColor: null == defaultColor ? _value.defaultColor : defaultColor // ignore: cast_nullable_to_non_nullable @@ -325,6 +339,7 @@ class _$_Lesson implements _Lesson { @HiveField(10) required this.isElective, @HiveField(11) required this.isEvent, @HiveField(14, defaultValue: false) required this.isCollision, + @HiveField(15, defaultValue: false) required this.isCancelled, @HiveField(12) required this.defaultColor, @HiveField(13) required this.emptyLessonsBefore}) : _groupNames = groupNames, @@ -382,6 +397,9 @@ class _$_Lesson implements _Lesson { @HiveField(14, defaultValue: false) final bool isCollision; @override + @HiveField(15, defaultValue: false) + final bool isCancelled; + @override @HiveField(12) final Color defaultColor; @override @@ -390,7 +408,7 @@ class _$_Lesson implements _Lesson { @override String toString() { - return 'Lesson(number: $number, timings: $timings, dateTimings: $dateTimings, type: $type, typeShortName: $typeShortName, disciplineName: $disciplineName, place: $place, groupNames: $groupNames, teacherNames: $teacherNames, isRemotely: $isRemotely, isElective: $isElective, isEvent: $isEvent, isCollision: $isCollision, defaultColor: $defaultColor, emptyLessonsBefore: $emptyLessonsBefore)'; + return 'Lesson(number: $number, timings: $timings, dateTimings: $dateTimings, type: $type, typeShortName: $typeShortName, disciplineName: $disciplineName, place: $place, groupNames: $groupNames, teacherNames: $teacherNames, isRemotely: $isRemotely, isElective: $isElective, isEvent: $isEvent, isCollision: $isCollision, isCancelled: $isCancelled, defaultColor: $defaultColor, emptyLessonsBefore: $emptyLessonsBefore)'; } @override @@ -419,6 +437,8 @@ class _$_Lesson implements _Lesson { (identical(other.isEvent, isEvent) || other.isEvent == isEvent) && (identical(other.isCollision, isCollision) || other.isCollision == isCollision) && + (identical(other.isCancelled, isCancelled) || + other.isCancelled == isCancelled) && (identical(other.defaultColor, defaultColor) || other.defaultColor == defaultColor) && (identical(other.emptyLessonsBefore, emptyLessonsBefore) || @@ -441,6 +461,7 @@ class _$_Lesson implements _Lesson { isElective, isEvent, isCollision, + isCancelled, defaultColor, emptyLessonsBefore); @@ -466,6 +487,7 @@ abstract class _Lesson implements Lesson { @HiveField(10) required final bool isElective, @HiveField(11) required final bool isEvent, @HiveField(14, defaultValue: false) required final bool isCollision, + @HiveField(15, defaultValue: false) required final bool isCancelled, @HiveField(12) required final Color defaultColor, @HiveField(13) required final int emptyLessonsBefore}) = _$_Lesson; @@ -509,6 +531,9 @@ abstract class _Lesson implements Lesson { @HiveField(14, defaultValue: false) bool get isCollision; @override + @HiveField(15, defaultValue: false) + bool get isCancelled; + @override @HiveField(12) Color get defaultColor; @override diff --git a/lib/models/lesson/lesson.g.dart b/lib/models/lesson/lesson.g.dart index 3511a78..e3729c4 100644 --- a/lib/models/lesson/lesson.g.dart +++ b/lib/models/lesson/lesson.g.dart @@ -32,6 +32,7 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { isElective: fields[10] as bool, isEvent: fields[11] as bool, isCollision: fields[14] == null ? false : fields[14] as bool, + isCancelled: fields[15] == null ? false : fields[15] as bool, defaultColor: fields[12] as Color, emptyLessonsBefore: fields[13] as int, ); @@ -40,7 +41,7 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { @override void write(BinaryWriter writer, _$_Lesson obj) { writer - ..writeByte(15) + ..writeByte(16) ..writeByte(0) ..write(obj.number) ..writeByte(1) @@ -63,6 +64,8 @@ class LessonAdapter extends TypeAdapter<_$_Lesson> { ..write(obj.isEvent) ..writeByte(14) ..write(obj.isCollision) + ..writeByte(15) + ..write(obj.isCancelled) ..writeByte(12) ..write(obj.defaultColor) ..writeByte(13) From e531c5b83f80369f0a07554860a08dde64565888 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 3 May 2023 22:24:41 +0300 Subject: [PATCH 20/21] LessonCardInfoPanelTimeToEnd --- .../current_lesson_time_to_end_provider.dart | 2 +- ...time_to_start_progress_value_provider.dart | 4 +- .../next_lesson_time_to_start_provider.dart | 6 +- .../features/lesson_card/ui/lesson_card.dart | 4 +- .../info_panel/lesson_card_info_panel.dart | 44 +++++--------- .../lesson_card_info_panel_time_to_end.dart | 59 +++++++++++++++++++ .../ui/widgets/lesson_card_time_left.dart | 25 -------- .../ui/widgets/lesson_card_time_to_start.dart | 11 +++- .../managers/timetable_lessons_manager.dart | 11 +++- .../state_holders/lessons/current_lesson.dart | 5 +- .../state_holders/lessons/last_lesson.dart | 2 +- .../state_holders/lessons/next_lesson.dart | 2 +- 12 files changed, 104 insertions(+), 71 deletions(-) create mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart delete mode 100644 lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart diff --git a/lib/features/timetable_page/features/lesson_card/providers/current_lesson_time_to_end_provider.dart b/lib/features/timetable_page/features/lesson_card/providers/current_lesson_time_to_end_provider.dart index 787fec1..face12c 100644 --- a/lib/features/timetable_page/features/lesson_card/providers/current_lesson_time_to_end_provider.dart +++ b/lib/features/timetable_page/features/lesson_card/providers/current_lesson_time_to_end_provider.dart @@ -6,7 +6,7 @@ import 'package:cube_system/features/timetable_page/state_holders/lessons/curren final currentLessonTimeToEndProvider = Provider((ref) { final currentDateTime = ref.watch(currentDateTimeQuick); - final activeLesson = ref.watch(currentLesson); + final activeLesson = ref.watch(currentLessonStateHolder); if (activeLesson == null) return null; diff --git a/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_progress_value_provider.dart b/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_progress_value_provider.dart index 61dff2e..cc22aaf 100644 --- a/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_progress_value_provider.dart +++ b/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_progress_value_provider.dart @@ -17,8 +17,8 @@ final nextLessonTimeToStartProgressValueProvider = Provider((ref) { final timeLeft = ref.read(nextLessonTimeToStartProvider)?.duration; if (timeLeft == null) return 1; - final lessonNext = ref.watch(nextLesson); - final lessonLast = ref.watch(lastLesson); + final lessonNext = ref.watch(nextLessonStateHolder); + final lessonLast = ref.watch(lastLessonStateHolder); if (lessonNext == null || lessonLast == null) return 1; diff --git a/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_provider.dart b/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_provider.dart index 9c8592d..90adaac 100644 --- a/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_provider.dart +++ b/lib/features/timetable_page/features/lesson_card/providers/next_lesson_time_to_start_provider.dart @@ -16,13 +16,13 @@ final nextLessonTimeToStartProvider = Provider((ref) { if (condition.isNever) return null; if (condition.isOnlyRecessBetweenLessons) { - final last = ref.watch(lastLesson); - final next = ref.watch(nextLesson); + final last = ref.watch(lastLessonStateHolder); + final next = ref.watch(nextLessonStateHolder); if (last == null || next == null) return null; if (next.number - last.number != 1) return null; } - final next = ref.watch(nextLesson); + final next = ref.watch(nextLessonStateHolder); if (next == null) return null; diff --git a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart index 17b730d..c4da686 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart @@ -24,14 +24,16 @@ import 'package:cube_system/features/settings/state_holders/app_lesson_colors.da import 'package:cube_system/features/timetable_page/state_holders/lessons/next_lesson.dart'; +import 'package:cube_system/features/timetable_page/managers/timetable_lessons_manager.dart'; + part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_body.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_footer.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_header.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_icon.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_chip.dart'; +part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_indicator.dart'; -part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/next_lesson_time_to_start_progress_bar.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_lesson_type_chip.dart'; part 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_to_start.dart'; diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart index 92f03d7..3b89ef1 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart @@ -7,17 +7,22 @@ class LessonCardInfoPanel extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final isRemotely = - ref.watch(_lessonInLessonCard.select((value) => value.isRemotely)); + final lesson = ref.watch(_lessonInLessonCard); - final isCollision = - ref.watch(_lessonInLessonCard.select((value) => value.isCollision)); + final isRemotely = lesson.isRemotely; - final isCancelled = - ref.watch(_lessonInLessonCard.select((value) => value.isCancelled)); + final isCollision = lesson.isCollision; - final isActiveLessons = - ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); + final isCancelled = lesson.isCancelled; + + final currentLesson = ref.watch(currentLessonStateHolder); + + final equelNumber = lesson.number == currentLesson?.number; + + final equelStartDateTime = lesson.dateTimings.startDateTime == + currentLesson?.dateTimings.startDateTime; + + final isActiveLessons = equelNumber && equelStartDateTime; // final isCollision = _random.nextInt(100) < 25; @@ -43,28 +48,7 @@ class LessonCardInfoPanel extends ConsumerWidget { LessonCardInfoPanelIcon( icon: Text('$numberOfNotes'), ), - if (isActiveLessons) - Consumer( - builder: (context, ref, _) { - ref.watch( - currentLessonTimeToEndProvider - .select((value) => value?.format().length), - ); - - final hasHours = - (ref.read(currentLessonTimeToEndProvider)?.hours ?? 0) > 0; - - return hasHours - ? const LessonCardInfoPanelChip( - minWidth: 66, - text: LessonCardTimeLeft(), - ) - : const LessonCardInfoPanelChip( - minWidth: 46, - text: LessonCardTimeLeft(), - ); - }, - ), + const LessonCardInfoPanelTimeToEnd(), if (isCollision) const LessonCardInfoPanelChip( text: Text('Коллизия'), diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart new file mode 100644 index 0000000..6c29248 --- /dev/null +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart @@ -0,0 +1,59 @@ +part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; + +class LessonCardInfoPanelTimeToEnd extends ConsumerWidget { + const LessonCardInfoPanelTimeToEnd({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final lesson = ref.watch(_lessonInLessonCard); + + final currentLesson = ref.watch(currentLessonStateHolder); + + final manager = ref.read(timetableLessonsManager); + + final isActiveLessons = manager.isEquelLessons(lesson, currentLesson); + + if (!isActiveLessons) return const SizedBox(); + + return Consumer( + builder: (context, ref, _) { + ref.watch( + currentLessonTimeToEndProvider + .select((value) => value?.format().length), + ); + + final hasHours = + (ref.read(currentLessonTimeToEndProvider)?.hours ?? 0) > 0; + + return hasHours + ? const LessonCardInfoPanelChip( + minWidth: 66, + text: _LessonCardInfoPanelTimeToEndText(), + ) + : const LessonCardInfoPanelChip( + minWidth: 46, + text: _LessonCardInfoPanelTimeToEndText(), + ); + }, + ); + } +} + +class _LessonCardInfoPanelTimeToEndText extends ConsumerWidget { + const _LessonCardInfoPanelTimeToEndText({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Consumer( + builder: (context, ref, _) { + final timeToEnd = ref.watch(currentLessonTimeToEndProvider); + final timeToEndStr = timeToEnd?.format() ?? '00:00'; + return Text( + timeToEndStr, + style: context.textStyles.chipLabel + .copyWith(color: context.colors.white), + ); + }, + ); + } +} diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart deleted file mode 100644 index fef6a9e..0000000 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_left.dart +++ /dev/null @@ -1,25 +0,0 @@ -part of 'package:cube_system/features/timetable_page/features/lesson_card/ui/lesson_card.dart'; - -class LessonCardTimeLeft extends ConsumerWidget { - const LessonCardTimeLeft({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final isActiveLessons = - ref.watch(_lessonInLessonCard) == ref.watch(currentLesson); - - if (!isActiveLessons) return const SizedBox(); - - return Consumer( - builder: (context, ref, _) { - final timeToEnd = ref.watch(currentLessonTimeToEndProvider); - final timeToEndStr = timeToEnd?.format() ?? '00:00'; - return Text( - timeToEndStr, - style: context.textStyles.chipLabel - .copyWith(color: context.colors.white), - ); - }, - ); - } -} diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_to_start.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_to_start.dart index 8d43e3c..df20f74 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_to_start.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/lesson_card_time_to_start.dart @@ -15,10 +15,15 @@ class LessonCardTimeToStart extends ConsumerWidget { nextLessonTimeToStartProvider.select((value) => value == null), ); - final lessonNext = ref.watch(nextLesson); - final lessonCurrent = ref.watch(currentLesson); + final nextLesson = ref.watch(nextLessonStateHolder); - if (dontShow || lesson != lessonNext || lessonCurrent != null) { + final currentLesson = ref.watch(currentLessonStateHolder); + + final manager = ref.read(timetableLessonsManager); + + final isActiveLessons = manager.isEquelLessons(lesson, nextLesson); + + if (dontShow || !isActiveLessons || currentLesson != null) { return const SizedBox(); } diff --git a/lib/features/timetable_page/managers/timetable_lessons_manager.dart b/lib/features/timetable_page/managers/timetable_lessons_manager.dart index 5df9dd3..41ebd68 100644 --- a/lib/features/timetable_page/managers/timetable_lessons_manager.dart +++ b/lib/features/timetable_page/managers/timetable_lessons_manager.dart @@ -31,9 +31,9 @@ final timetableLessonsManager = Provider((ref) { events: ref.watch(timetablePageEvents.notifier), currentDateTime: ref.watch(currentDateTimeQuick.notifier), selectedDate: ref.watch(selectedDate.notifier), - currentLesson: ref.watch(currentLesson.notifier), - nextLesson: ref.watch(nextLesson.notifier), - lastLesson: ref.watch(lastLesson.notifier), + currentLesson: ref.watch(currentLessonStateHolder.notifier), + nextLesson: ref.watch(nextLessonStateHolder.notifier), + lastLesson: ref.watch(lastLessonStateHolder.notifier), ); }); @@ -215,4 +215,9 @@ class TimetableLessonsManager { } } } + + bool isEquelLessons(Lesson? one, Lesson? two) { + return one?.dateTimings.startDateTime == two?.dateTimings.startDateTime && + one?.number == two?.number; + } } diff --git a/lib/features/timetable_page/state_holders/lessons/current_lesson.dart b/lib/features/timetable_page/state_holders/lessons/current_lesson.dart index 6a6c0da..8541336 100644 --- a/lib/features/timetable_page/state_holders/lessons/current_lesson.dart +++ b/lib/features/timetable_page/state_holders/lessons/current_lesson.dart @@ -1,6 +1,9 @@ import 'package:cube_system/models/lesson/lesson.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -final currentLesson = StateProvider((ref) { +// TODO: Объеденить current, next, last в один stateHolder +// TODO: Возможно, стоит хранить не Lesson, a LessonDateTimings и LessonTimings + +final currentLessonStateHolder = StateProvider((ref) { return null; }); diff --git a/lib/features/timetable_page/state_holders/lessons/last_lesson.dart b/lib/features/timetable_page/state_holders/lessons/last_lesson.dart index e5cc722..e2cc33f 100644 --- a/lib/features/timetable_page/state_holders/lessons/last_lesson.dart +++ b/lib/features/timetable_page/state_holders/lessons/last_lesson.dart @@ -2,6 +2,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:cube_system/models/lesson/lesson.dart'; -final lastLesson = StateProvider((ref) { +final lastLessonStateHolder = StateProvider((ref) { return null; }); diff --git a/lib/features/timetable_page/state_holders/lessons/next_lesson.dart b/lib/features/timetable_page/state_holders/lessons/next_lesson.dart index 6868f4a..9497853 100644 --- a/lib/features/timetable_page/state_holders/lessons/next_lesson.dart +++ b/lib/features/timetable_page/state_holders/lessons/next_lesson.dart @@ -2,6 +2,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:cube_system/models/lesson/lesson.dart'; -final nextLesson = StateProvider((ref) { +final nextLessonStateHolder = StateProvider((ref) { return null; }); From 16f3698748187b0e286359855742ece09d3b35bb Mon Sep 17 00:00:00 2001 From: StarProxima Date: Sat, 6 May 2023 18:56:52 +0300 Subject: [PATCH 21/21] Dart format and fix --- .../settings/managers/settings_manager.dart | 1 + .../features/lesson_card/ui/lesson_card.dart | 2 -- .../info_panel/lesson_card_info_panel.dart | 9 -------- .../lesson_card_info_panel_time_to_end.dart | 2 +- .../ui/widgets/timetable_page_header.dart | 22 ------------------- .../timetable_search_page_timetables.dart | 1 - lib/ui/widgets/fade_animated_widget.dart | 1 - 7 files changed, 2 insertions(+), 36 deletions(-) diff --git a/lib/features/settings/managers/settings_manager.dart b/lib/features/settings/managers/settings_manager.dart index e69de29..8b13789 100644 --- a/lib/features/settings/managers/settings_manager.dart +++ b/lib/features/settings/managers/settings_manager.dart @@ -0,0 +1 @@ + diff --git a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart index c4da686..be64194 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/lesson_card.dart @@ -2,7 +2,6 @@ import 'dart:math'; import 'package:cube_system/features/settings/state_holders/app_settings_state_holder.dart'; import 'package:cube_system/features/timetable_page/features/lesson_card/ui/widgets/recess_card.dart'; -import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; import 'package:cube_system/features/timetable_page/state_holders/selected_timetable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -50,7 +49,6 @@ class LessonCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final manager = ref.watch(timetablePageManager); return ProviderScope( overrides: [ _lessonInLessonCard.overrideWithValue(lesson), diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart index 3b89ef1..80ef88d 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel.dart @@ -15,15 +15,6 @@ class LessonCardInfoPanel extends ConsumerWidget { final isCancelled = lesson.isCancelled; - final currentLesson = ref.watch(currentLessonStateHolder); - - final equelNumber = lesson.number == currentLesson?.number; - - final equelStartDateTime = lesson.dateTimings.startDateTime == - currentLesson?.dateTimings.startDateTime; - - final isActiveLessons = equelNumber && equelStartDateTime; - // final isCollision = _random.nextInt(100) < 25; // final isRemotely = _random.nextInt(100) < 25; diff --git a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart index 6c29248..c82040b 100644 --- a/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart +++ b/lib/features/timetable_page/features/lesson_card/ui/widgets/info_panel/lesson_card_info_panel_time_to_end.dart @@ -40,7 +40,7 @@ class LessonCardInfoPanelTimeToEnd extends ConsumerWidget { } class _LessonCardInfoPanelTimeToEndText extends ConsumerWidget { - const _LessonCardInfoPanelTimeToEndText({super.key}); + const _LessonCardInfoPanelTimeToEndText(); @override Widget build(BuildContext context, WidgetRef ref) { diff --git a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart index d9a9f76..fc1603d 100644 --- a/lib/features/timetable_page/ui/widgets/timetable_page_header.dart +++ b/lib/features/timetable_page/ui/widgets/timetable_page_header.dart @@ -1,36 +1,14 @@ -import 'package:cube_system/features/timetable_page/features/week_timeline/state_holders/week_timeline_shown_week_date.dart'; -import 'package:cube_system/features/timetable_page/managers/timetable_page_manager.dart'; -import 'package:cube_system/features/date_time_contol/state_holders/current_date_time_state_holders.dart'; import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_back_button.dart'; import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_date.dart'; import 'package:cube_system/features/timetable_page/ui/widgets/timetable_page_header_timetable_info.dart'; -import 'package:cube_system/core/extensions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:cube_system/features/timetable_page/features/week_timeline/providers/week_timeline_offset_back_button_direction_provider.dart'; - class TimetablePageHeader extends ConsumerWidget { const TimetablePageHeader({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final manager = ref.watch(timetablePageManager); - - final date = ref.watch(currentDate); - final weekDate = ref.watch(weekTimelineShownWeekDate); - - final weekOffsetButton = - ref.watch(weekTimelineOffsetBackButtonDirectionProvider); - - final String weekLabel; - - if (weekDate.weekNumber % 2 == 1) { - weekLabel = 'Числитель'; - } else { - weekLabel = 'Знаменатель'; - } - return SizedBox( height: 62, child: Row( diff --git a/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart b/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart index 9ff51e7..d9b1e22 100644 --- a/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart +++ b/lib/features/timetable_search_page/state_holders/timetable_search_page_timetables.dart @@ -1,4 +1,3 @@ -import 'package:cube_system/models/timetable/timetable_info.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:cube_system/features/timetable_search_page/models/timetable_search_info.dart'; diff --git a/lib/ui/widgets/fade_animated_widget.dart b/lib/ui/widgets/fade_animated_widget.dart index 08f9be5..e2a72ef 100644 --- a/lib/ui/widgets/fade_animated_widget.dart +++ b/lib/ui/widgets/fade_animated_widget.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; class FadeAnimatedWidget extends StatefulWidget {