diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart index 136105b..98927ed 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -4,6 +4,7 @@ import 'package:flutter/scheduler.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:nwt_reading/src/base/presentation/plan.dart'; import 'package:nwt_reading/src/base/repositories/shared_preferences_repository.dart'; import 'package:nwt_reading/src/bible_languages/entities/bible_languages.dart'; @@ -11,7 +12,9 @@ import 'package:nwt_reading/src/bible_languages/repositories/bible_languages_rep import 'package:nwt_reading/src/plans/entities/plan.dart'; import 'package:nwt_reading/src/plans/entities/plans.dart'; import 'package:nwt_reading/src/plans/presentations/plan_card.dart'; +import 'package:nwt_reading/src/plans/presentations/plan_name_tile.dart'; import 'package:nwt_reading/src/plans/repositories/plans_repository.dart'; +import 'package:nwt_reading/src/plans/stories/plan_edit_story.dart'; import 'package:nwt_reading/src/schedules/entities/events.dart'; import 'package:nwt_reading/src/schedules/entities/locations.dart'; import 'package:nwt_reading/src/schedules/entities/schedule.dart'; @@ -129,20 +132,27 @@ void main() async { await tester.pumpAndSettle(); await takeScreenshot(tester: tester, binding: binding, filename: 'new'); - expect(providerContainer.read(plansProvider).plans.length, 0); + BuildContext buildContext = + tester.firstElement(find.byKey(const Key('plan-name'))); + TextFormField nameTextFormField = + tester.firstWidget(find.byKey(const Key('plan-name'))); + String? planId = + (tester.firstWidget(find.byKey(const Key('plan-name-tile'))) + as PlanNameTile) + .planId; expect( - (tester.firstWidget(find.byKey(const Key('plan-name'))) - as TextFormField) - .controller - ?.text, - 'Chronological y1'); + nameTextFormField.controller?.text, + getPlanName(buildContext, + providerContainer.read(planEditProviderFamily(planId)))); + expect(providerContainer.read(plansProvider).plans.length, 0); expect(find.byKey(const Key('target-status')), findsNothing); await tester.tap(find.byIcon(Icons.done)); await tester.pumpAndSettle(); - var plan = providerContainer.read(plansProvider).plans.first; - expect(plan.name, 'Chronological y1'); + Plan plan = providerContainer.read(plansProvider).plans.first; + buildContext = tester.element(find.byKey(const Key('plans-grid'))); + expect(plan.name, null); expect(plan.scheduleKey.type, ScheduleType.chronological); expect(plan.scheduleKey.duration, ScheduleDuration.y1); expect(plan.scheduleKey.version, '1.0'); @@ -165,12 +175,16 @@ void main() async { .last); await tester.pumpAndSettle(); + buildContext = tester.firstElement(find.byKey(const Key('plan-name'))); + nameTextFormField = + tester.firstWidget(find.byKey(const Key('plan-name'))) as TextFormField; + planId = (tester.firstWidget(find.byKey(const Key('plan-name-tile'))) + as PlanNameTile) + .planId; expect( - (tester.firstWidget(find.byKey(const Key('plan-name'))) - as TextFormField) - .controller - ?.text, - 'Canonical y4'); + nameTextFormField.controller?.text, + getPlanName(buildContext, + providerContainer.read(planEditProviderFamily(planId)))); final firstBibleLanguageKey = providerContainer .read(bibleLanguagesProvider) @@ -721,12 +735,15 @@ void main() async { await tester.pumpAndSettle(); await takeScreenshot(tester: tester, binding: binding, filename: 'edit'); + Plan plan = providerContainer.read(plansProvider).plans.first; + BuildContext buildContext = + tester.firstElement(find.byKey(const Key('plan-name'))); expect( (tester.firstWidget(find.byKey(const Key('plan-name'))) as TextFormField) .controller ?.text, - 'Chronological y1'); + getPlanName(buildContext, plan)); await tester.tap(find .descendant( @@ -740,13 +757,14 @@ void main() async { as TextFormField) .controller ?.text, - 'Chronological y4'); + getPlanName(buildContext, + providerContainer.read(planEditProviderFamily(plan.id)))); await tester.enterText(find.byKey(const Key('plan-name')), 'Test 😃'); await tester.pumpAndSettle(); - var plan = providerContainer.read(plansProvider).plans.first; - expect(plan.name, 'Chronological y1'); + plan = providerContainer.read(plansProvider).plans.first; + expect(plan.name, null); await tester.tap(find.byIcon(Icons.done)); await tester.pumpAndSettle(); diff --git a/lib/src/base/presentation/plan.dart b/lib/src/base/presentation/plan.dart new file mode 100644 index 0000000..82ba174 --- /dev/null +++ b/lib/src/base/presentation/plan.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:nwt_reading/src/localization/app_localizations_getter.dart'; +import 'package:nwt_reading/src/plans/entities/plan.dart'; +import 'package:nwt_reading/src/schedules/entities/schedule.dart'; + +String getPlanName(BuildContext context, Plan plan) => + plan.name ?? + '${toBeginningOfSentenceCase( + switch (plan.scheduleKey.type) { + ScheduleType.chronological => + context.loc.planEditPageChronologicalLabel, + ScheduleType.canonical => context.loc.planEditPageCanonicalLabel, + ScheduleType.written => context.loc.planEditPageAsWrittenLabel, + }, + )} ${switch (plan.scheduleKey.duration) { + ScheduleDuration.m3 => context.loc.planEditPageMonthsLabel(3), + ScheduleDuration.m6 => context.loc.planEditPageMonthsLabel(6), + ScheduleDuration.y1 => context.loc.planEditPageYearsLabel(1), + ScheduleDuration.y2 => context.loc.planEditPageYearsLabel(2), + ScheduleDuration.y4 => context.loc.planEditPageYearsLabel(4), + }}'; diff --git a/lib/src/plans/entities/plan.dart b/lib/src/plans/entities/plan.dart index 38af3f1..4f0d390 100644 --- a/lib/src/plans/entities/plan.dart +++ b/lib/src/plans/entities/plan.dart @@ -133,7 +133,7 @@ class TogglingTooManyDaysException implements Exception {} class Plan extends Equatable { const Plan({ required this.id, - required this.name, + this.name, required this.scheduleKey, required this.language, required this.bookmark, @@ -146,7 +146,7 @@ class Plan extends Equatable { }); final String id; - final String name; + final String? name; final ScheduleKey scheduleKey; final String language; final Bookmark bookmark; diff --git a/lib/src/plans/entities/plans.dart b/lib/src/plans/entities/plans.dart index 0aac02e..7327f9c 100644 --- a/lib/src/plans/entities/plans.dart +++ b/lib/src/plans/entities/plans.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; import 'package:nwt_reading/src/plans/entities/plan.dart'; import 'package:nwt_reading/src/schedules/entities/schedule.dart'; import 'package:uuid/uuid.dart'; @@ -22,19 +21,14 @@ class PlansNotifier extends Notifier { String getNewPlanId() => _uuid.v4(); - String getDefaultName(ScheduleKey scheduleKey) => - '${toBeginningOfSentenceCase(scheduleKey.type.name)} ${scheduleKey.duration.name}'; - Plan getNewPlan(String planId) { const scheduleKey = ScheduleKey( type: ScheduleType.chronological, duration: ScheduleDuration.y1, version: '1.0'); - final name = getDefaultName(scheduleKey); return Plan( id: planId, - name: name, scheduleKey: scheduleKey, language: 'en', bookmark: const Bookmark(dayIndex: 0, sectionIndex: -1), diff --git a/lib/src/plans/presentations/plan_card.dart b/lib/src/plans/presentations/plan_card.dart index e89e216..bc3d83b 100644 --- a/lib/src/plans/presentations/plan_card.dart +++ b/lib/src/plans/presentations/plan_card.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:nwt_reading/src/base/presentation/plan.dart'; import 'package:nwt_reading/src/localization/app_localizations_getter.dart'; import 'package:nwt_reading/src/plans/entities/plan.dart'; import 'package:nwt_reading/src/schedules/entities/schedule.dart'; @@ -41,7 +42,7 @@ class PlanCard extends ConsumerWidget { ], ), Text( - plan.name, + getPlanName(context, plan), style: Theme.of(context) .textTheme .headlineMedium diff --git a/lib/src/plans/presentations/plan_edit_dialog.dart b/lib/src/plans/presentations/plan_edit_dialog.dart index 4cc67dd..4375259 100644 --- a/lib/src/plans/presentations/plan_edit_dialog.dart +++ b/lib/src/plans/presentations/plan_edit_dialog.dart @@ -51,7 +51,7 @@ class PlanEditDialog extends ConsumerWidget { } }) ]), - PlanNameTile(planId), + PlanNameTile(planId, key: const Key('plan-name-tile')), const SizedBox(height: 20), if (isNewPlan) PlanTypeSegmentedButton(planId), if (isNewPlan) const SizedBox(height: 20), diff --git a/lib/src/plans/presentations/plan_name_tile.dart b/lib/src/plans/presentations/plan_name_tile.dart index e89641d..d162b28 100644 --- a/lib/src/plans/presentations/plan_name_tile.dart +++ b/lib/src/plans/presentations/plan_name_tile.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:nwt_reading/src/base/presentation/plan.dart'; import 'package:nwt_reading/src/plans/stories/plan_edit_story.dart'; class PlanNameTile extends ConsumerWidget { @@ -10,6 +11,7 @@ class PlanNameTile extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final plan = ref.watch(planEditProviderFamily(planId)); + final planName = getPlanName(context, plan); final planEdit = ref.read(planEditProviderFamily(planId).notifier); return ListTile( @@ -17,16 +19,11 @@ class PlanNameTile extends ConsumerWidget { key: const Key('plan-name'), autofillHints: const ['plan-name'], autofocus: true, - controller: TextEditingController(text: plan.name), + controller: TextEditingController(text: planName), decoration: const InputDecoration(hintText: 'Enter a name for your reading plan'), - onChanged: (name) => planEdit.changeName(name), - validator: (name) { - if (name == null || name.isEmpty) { - return 'Please enter a name'; - } - return null; - }, + onChanged: (name) => + (name != planName) ? planEdit.changeName(name) : null, )); } } diff --git a/lib/src/plans/presentations/plans_page.dart b/lib/src/plans/presentations/plans_page.dart index b4519fc..b1bfa78 100644 --- a/lib/src/plans/presentations/plans_page.dart +++ b/lib/src/plans/presentations/plans_page.dart @@ -48,7 +48,9 @@ class PlansPageState extends ConsumerState { ), ], ), - body: PlansGrid(), + body: PlansGrid( + key: const Key('plans-grid'), + ), floatingActionButton: FloatingActionButton( tooltip: context.loc.plansPageAddPlanTooltip, onPressed: () => showDialog( diff --git a/lib/src/plans/repositories/plans_deserializer.dart b/lib/src/plans/repositories/plans_deserializer.dart index 1c9e850..31a237a 100644 --- a/lib/src/plans/repositories/plans_deserializer.dart +++ b/lib/src/plans/repositories/plans_deserializer.dart @@ -25,7 +25,7 @@ class PlansDeserializer { Plan _convertMapToPlan(Map planMap) { final id = planMap['id'] as String; - final name = planMap['name'] as String; + final name = planMap['name'] == null ? null : planMap['name'] as String; final schedule = convertMapToScheduleKey(planMap['scheduleKey'] as Map); final language = planMap['language'] as String; diff --git a/lib/src/plans/repositories/plans_repository.dart b/lib/src/plans/repositories/plans_repository.dart index 0897ef9..85d1934 100644 --- a/lib/src/plans/repositories/plans_repository.dart +++ b/lib/src/plans/repositories/plans_repository.dart @@ -92,7 +92,6 @@ class PlansRepository { plans = Plans([ Plan( id: _uuid.v4(), - name: plansNotifier.getDefaultName(scheduleKey), scheduleKey: scheduleKey, language: readingLanguage ?? language ?? 'en', bookmark: bookmark, diff --git a/lib/src/plans/repositories/plans_serializer.dart b/lib/src/plans/repositories/plans_serializer.dart index f6a4fec..2b0c583 100644 --- a/lib/src/plans/repositories/plans_serializer.dart +++ b/lib/src/plans/repositories/plans_serializer.dart @@ -10,7 +10,7 @@ class PlansSerializer { Map _convertPlanToMap(Plan plan) => { 'id': plan.id, - 'name': plan.name, + if (plan.name != null) 'name': plan.name, 'scheduleKey': _convertScheduleKeyToMap(plan.scheduleKey), 'language': plan.language, 'bookmark': _convertBookmarkToMap(plan.bookmark), diff --git a/lib/src/plans/stories/plan_edit_story.dart b/lib/src/plans/stories/plan_edit_story.dart index 49e4e27..c69d70b 100644 --- a/lib/src/plans/stories/plan_edit_story.dart +++ b/lib/src/plans/stories/plan_edit_story.dart @@ -24,16 +24,6 @@ class PlanEdit extends AutoDisposeFamilyNotifier { void changeName(String name) => _name = name; - void updateDefaultName(ScheduleKey scheduleKey) { - final plansNotifier = ref.read(plansProvider.notifier); - final isDefaultName = _name == null || - _name == plansNotifier.getDefaultName(state.scheduleKey); - - if (isDefaultName) { - _name = plansNotifier.getDefaultName(scheduleKey); - } - } - void updateLanguage(String language) { if (language != state.language) { state = state.copyWith(language: language); @@ -54,7 +44,6 @@ class PlanEdit extends AutoDisposeFamilyNotifier { final newDayIndex = (state.bookmark.dayIndex * newScheduleLength / oldScheduleLength) .round(); - updateDefaultName(newScheduleKey); state = state.copyWith( name: _name, @@ -70,7 +59,6 @@ class PlanEdit extends AutoDisposeFamilyNotifier { void updateScheduleType(ScheduleType scheduleType) { if (scheduleType != state.scheduleKey.type) { final newScheduleKey = state.scheduleKey.copyWith(type: scheduleType); - updateDefaultName(newScheduleKey); state = state.copyWith( name: _name, diff --git a/lib/src/schedules/presentations/schedule_page.dart b/lib/src/schedules/presentations/schedule_page.dart index 89178da..c5aff00 100644 --- a/lib/src/schedules/presentations/schedule_page.dart +++ b/lib/src/schedules/presentations/schedule_page.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:nwt_reading/src/base/presentation/plan.dart'; import 'package:nwt_reading/src/localization/app_localizations_getter.dart'; import 'package:nwt_reading/src/plans/entities/plan.dart'; import 'package:nwt_reading/src/plans/presentations/plan_edit_dialog.dart'; @@ -112,12 +113,12 @@ class _SchedulePageState extends ConsumerState { return Scaffold( appBar: AppBar( title: deviationDays == 0 - ? Text(plan.name) + ? Text(getPlanName(context, plan)) : Badge( label: Text('${deviationDays.abs()}'), backgroundColor: badgeColor, offset: Offset(23, -5), - child: Text(plan.name), + child: Text(getPlanName(context, plan)), ), actions: [ IconButton( diff --git a/test/test_data.dart b/test/test_data.dart index 2fd4e2b..1f947cc 100644 --- a/test/test_data.dart +++ b/test/test_data.dart @@ -16,7 +16,6 @@ Future> getWhatsNewSeenPreference() async => { final Plans testPlans = Plans([ Plan( id: '5aa4de9e-036b-42cd-8bcb-a92cae46db27', - name: 'Chronological y1', scheduleKey: ScheduleKey( type: ScheduleType.chronological, duration: ScheduleDuration.y1, @@ -66,7 +65,7 @@ final Plans testPlans = Plans([ ]); const List testPlansSerialized = [ - '{"id":"5aa4de9e-036b-42cd-8bcb-a92cae46db27","name":"Chronological y1","scheduleKey":{"type":0,"duration":2,"version":"1.0"},"language":"en","bookmark":{"dayIndex":75,"sectionIndex":0},"withTargetDate":true,"showEvents":true,"showLocations":true}', + '{"id":"5aa4de9e-036b-42cd-8bcb-a92cae46db27","scheduleKey":{"type":0,"duration":2,"version":"1.0"},"language":"en","bookmark":{"dayIndex":75,"sectionIndex":0},"withTargetDate":true,"showEvents":true,"showLocations":true}', '{"id":"0da6b8a7-ccd4-4270-8058-9e30a3f55ceb","name":"Written","scheduleKey":{"type":2,"duration":2,"version":"1.0"},"language":"de","bookmark":{"dayIndex":0,"sectionIndex":-1},"withTargetDate":false,"showEvents":false,"showLocations":false}', '{"id":"2dab49f3-aecf-4aba-9e91-d75c297d4b7e","name":"Canonical","scheduleKey":{"type":1,"duration":2,"version":"1.0"},"language":"ro","bookmark":{"dayIndex":364,"sectionIndex":1},"lastDate":"2024-11-21T00:00:00.000","withTargetDate":true,"showEvents":true,"showLocations":true}', '{"id":"e37bf9df-077a-49db-adcb-d56384906103","name":"Chronological","scheduleKey":{"type":0,"duration":1,"version":"1.0"},"language":"en","bookmark":{"dayIndex":182,"sectionIndex":1},"withTargetDate":true,"showEvents":true,"showLocations":true}' @@ -100,7 +99,6 @@ final List testLegacyExports = [ plans: Plans(const [ Plan( id: '', - name: 'Canonical y1', scheduleKey: ScheduleKey( type: ScheduleType.canonical, duration: ScheduleDuration.y1, @@ -119,7 +117,6 @@ final List testLegacyExports = [ plans: Plans([ Plan( id: '', - name: 'Chronological y1', scheduleKey: const ScheduleKey( type: ScheduleType.chronological, duration: ScheduleDuration.y1, @@ -139,7 +136,6 @@ final List testLegacyExports = [ plans: Plans([ Plan( id: '3266e6fd-ce74-48f0-a491-da086a7704c7', - name: 'Chronological y1', scheduleKey: const ScheduleKey( type: ScheduleType.chronological, duration: ScheduleDuration.y1,