Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Prohibit stores creation while the current map territory is being loaded #214

Merged
merged 2 commits into from
Feb 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions lib/ui/main/main_page.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:plante/l10n/strings.dart';
import 'package:plante/ui/base/colors_plante.dart';
import 'package:plante/ui/base/components/bottom_bar_plante.dart';
Expand All @@ -15,17 +16,20 @@ import 'package:plante/ui/profile/profile_page.dart';
import 'package:plante/ui/scan/barcode_scan_page.dart';

class MainPage extends PagePlante {
final GoogleMapController? mapControllerForTesting;
static const PAGE_NAME = 'MainPage';
const MainPage({Key? key}) : super(key: key);
const MainPage({Key? key, this.mapControllerForTesting}) : super(key: key);

@override
_MainPageState createState() => _MainPageState();
}

class _MainPageState extends PageStatePlante<MainPage> with RestorationMixin {
final _mapPageController = MapPageController();
late final _mapPage =
MapPage(key: const Key('main_map_page'), controller: _mapPageController);
late final _mapPage = MapPage(
key: const Key('main_map_page'),
controller: _mapPageController,
mapControllerForTesting: widget.mapControllerForTesting);
final _barcodePage =
BarcodeScanPage(key: const Key('main_barcode_scan_page'));
final _profilePage = ProfilePage(key: const Key('main_profile_page'));
Expand Down Expand Up @@ -130,24 +134,27 @@ class _MainPageState extends PageStatePlante<MainPage> with RestorationMixin {
}

void _onPlusClick() async {
final shopsLoaded = _mapPageController.isViewportLoaded();

final selected = await showMenuPlante(
target: _plusButtonKey,
context: context,
position: PlantePopupPosition.ABOVE_TARGET,
offsetFromTarget: 21,
values: [
context.strings.main_page_add_product,
context.strings.main_page_add_shop
if (shopsLoaded) context.strings.main_page_add_shop
],
children: [
Align(
alignment: Alignment.centerRight,
child: Text(context.strings.main_page_add_product,
style: TextStyles.headline2)),
Align(
alignment: Alignment.centerRight,
child: Text(context.strings.main_page_add_shop,
style: TextStyles.headline2))
if (shopsLoaded)
Align(
alignment: Alignment.centerRight,
child: Text(context.strings.main_page_add_shop,
style: TextStyles.headline2))
]);
if (selected == context.strings.main_page_add_product) {
_onAddProductClick();
Expand Down
7 changes: 7 additions & 0 deletions lib/ui/map/map_page/map_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum MapPageRequestedMode {
class MapPageController {
VoidCallback? _startStoreCreation;
VoidCallback? _switchToDefaultMode;
ResCallback<bool>? _isViewportLoaded;

/// Note: the map will switch to the default mode after store creation
/// is finished (or canceled).
Expand All @@ -66,6 +67,10 @@ class MapPageController {
void switchToDefaultMode() {
_switchToDefaultMode?.call();
}

bool isViewportLoaded() {
return _isViewportLoaded?.call() ?? false;
}
}

class MapPage extends PagePlante {
Expand Down Expand Up @@ -233,6 +238,8 @@ class _MapPageState extends PageStatePlante<MapPage>
switchModeCallback
.call(MapPageModeCreateShop(_mode.cachedVal.params, nextMode));
};
widget.controller?._isViewportLoaded =
() => _model.viewPortShopsLoaded.cachedVal;

_asyncInit();
_instances.add(this);
Expand Down
43 changes: 39 additions & 4 deletions test/ui/main/main_page_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ void main() {
.registerSingleton<UserContributionsManager>(userContributionsManager);
});

Future<void> forceMapIdleState(WidgetTester tester) async {
final mapPage = find.byType(MapPage).evaluate().first.widget as MapPage;
mapPage.onMapIdleForTesting();
await tester.pumpAndSettle();
}

Widget currentPage() {
final stack = find
.byKey(const Key('main_pages_stack'))
Expand Down Expand Up @@ -154,7 +160,9 @@ void main() {
});

testWidgets('plus button: add a store', (WidgetTester tester) async {
final context = await tester.superPump(const MainPage());
final context = await tester.superPump(
MainPage(mapControllerForTesting: mapTestsCommons.mapController));
await forceMapIdleState(tester);

// Force switch from the map page
await tester.superTap(find.byKey(const Key('bottom_bar_barcode')));
Expand Down Expand Up @@ -209,7 +217,9 @@ void main() {
GetIt.I.unregister<ShopsCreationManager>();
GetIt.I.registerSingleton<ShopsCreationManager>(mockShopsCreationManager);

final context = await tester.superPump(const MainPage());
final context = await tester.superPump(
MainPage(mapControllerForTesting: mapTestsCommons.mapController));
await forceMapIdleState(tester);

// Add FAB
await tester.superTap(find.byKey(const Key('bottom_bar_plus_fab')));
Expand All @@ -236,7 +246,9 @@ void main() {

testWidgets('plus button: click Add a Store twice in a row',
(WidgetTester tester) async {
final context = await tester.superPump(const MainPage());
final context = await tester.superPump(
MainPage(mapControllerForTesting: mapTestsCommons.mapController));
await forceMapIdleState(tester);

// Force switch from the map page
await tester.superTap(find.byKey(const Key('bottom_bar_barcode')));
Expand All @@ -263,7 +275,9 @@ void main() {

testWidgets('plus button: add a store is canceled when pages are switched',
(WidgetTester tester) async {
final context = await tester.superPump(const MainPage());
final context = await tester.superPump(
MainPage(mapControllerForTesting: mapTestsCommons.mapController));
await forceMapIdleState(tester);

// Force switch from the map page
await tester.superTap(find.byKey(const Key('bottom_bar_barcode')));
Expand Down Expand Up @@ -293,6 +307,27 @@ void main() {
findsNothing);
});

testWidgets(
'plus button: add a store item is not available until shops are loaded',
(WidgetTester tester) async {
final context = await tester.superPump(
MainPage(mapControllerForTesting: mapTestsCommons.mapController));

// No Add Store button
await tester.superTap(find.byKey(const Key('bottom_bar_plus_fab')));
expect(find.text(context.strings.main_page_add_shop), findsNothing);

// Idle state means the shops are loaded
await forceMapIdleState(tester);

// Close the popup
await tester.superTap(find.byKey(const Key('bottom_bar_map')));

// Not there is an Add Store button
await tester.superTap(find.byKey(const Key('bottom_bar_plus_fab')));
expect(find.text(context.strings.main_page_add_shop), findsWidgets);
});

testWidgets('viewed products are not requested implicitly',
(WidgetTester tester) async {
await tester.superPump(const MainPage());
Expand Down