Skip to content

Commit

Permalink
fix: Invisible loading animation (openfoodfacts#5641)
Browse files Browse the repository at this point in the history
  • Loading branch information
g123k authored Sep 30, 2024
1 parent b8af359 commit 3c8c299
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 230 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/duration_constants.dart';
import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart';
import 'package:smooth_app/themes/theme_provider.dart';

/// Container to display a product image on a product card.
///
Expand Down Expand Up @@ -163,20 +165,23 @@ class _SmoothAnimatedLogoState extends State<_SmoothAnimatedLogo>
Animation<double>? _animation;

@override
Widget build(BuildContext context) {
_attachAnimation();
void initState() {
super.initState();

SchedulerBinding.instance.addPostFrameCallback((_) {
_attachAnimation();
});
}

@override
Widget build(BuildContext context) {
return Opacity(
opacity: _animation?.value ?? widget.opacityMin,
child: const _SmoothAppLogo(),
);
}

void _attachAnimation() {
if (_animation != null) {
return;
}

AnimationController? controller =
_SmoothSharedAnimationControllerState.of(context);

Expand Down Expand Up @@ -214,7 +219,13 @@ class _SmoothAppLogo extends StatelessWidget {

@override
Widget build(BuildContext context) {
return SvgPicture.asset('assets/app/release_icon_transparent.svg');
final ThemeProvider themeProvider = context.watch<ThemeProvider>();

return SvgPicture.asset(
!themeProvider.isDarkMode(context)
? 'assets/app/release_icon_transparent.svg'
: 'assets/app/release_icon_dark_transparent_no_border.svg',
);
}
}

Expand Down Expand Up @@ -248,8 +259,8 @@ class _SmoothSharedAnimationControllerState

@override
Widget build(BuildContext context) {
return Provider<_SmoothSharedAnimationControllerState>.value(
value: this,
return Provider<_SmoothSharedAnimationControllerState>(
create: (_) => this,
child: widget.child,
);
}
Expand All @@ -262,8 +273,10 @@ class _SmoothSharedAnimationControllerState

static AnimationController? of(BuildContext context) {
try {
return Provider.of<_SmoothSharedAnimationControllerState>(context)
._controller;
return Provider.of<_SmoothSharedAnimationControllerState>(
context,
listen: false,
)._controller;
} catch (_) {
return null;
}
Expand Down
245 changes: 125 additions & 120 deletions packages/smooth_app/lib/pages/product/common/product_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import 'package:smooth_app/generic_lib/bottom_sheets/smooth_bottom_sheet.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/duration_constants.dart';
import 'package:smooth_app/generic_lib/loading_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_responsive.dart';
import 'package:smooth_app/helpers/app_helper.dart';
import 'package:smooth_app/helpers/robotoff_insight_helper.dart';
Expand Down Expand Up @@ -130,138 +131,142 @@ class _ProductListPageState extends State<ProductListPage>
final bool enableClear = products.isNotEmpty;
final bool enableRename = productList.listType == ProductListType.USER;

return SmoothScaffold(
floatingActionButton: products.isEmpty
? FloatingActionButton.extended(
icon: const Icon(CupertinoIcons.barcode),
label: Text(appLocalizations.product_list_empty_title),
onPressed: () =>
ExternalScanCarouselManager.read(context).showSearchCard(),
)
: _selectionMode
? null
: FloatingActionButton.extended(
onPressed: () => setState(() => _selectionMode = true),
label: const Text('Multi-select'),
icon: const Icon(Icons.checklist),
),
appBar: SmoothAppBar(
centerTitle: false,
actions: <Widget>[
SmoothPopupMenuButton<ProductListPopupItem>(
onSelected: (final ProductListPopupItem action) async {
final ProductList? differentProductList =
await action.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
);
if (differentProductList != null) {
setState(() => productList = differentProductList);
}
},
itemBuilder: (_) => <SmoothPopupMenuItem<ProductListPopupItem>>[
if (enableRename) _rename.getMenuItem(appLocalizations),
_share.getMenuItem(appLocalizations),
_openInWeb.getMenuItem(appLocalizations),
if (enableClear) _clear.getMenuItem(appLocalizations),
],
return SmoothSharedAnimationController(
child: SmoothScaffold(
floatingActionButton: products.isEmpty
? FloatingActionButton.extended(
icon: const Icon(CupertinoIcons.barcode),
label: Text(appLocalizations.product_list_empty_title),
onPressed: () =>
ExternalScanCarouselManager.read(context).showSearchCard(),
)
: _selectionMode
? null
: FloatingActionButton.extended(
onPressed: () => setState(() => _selectionMode = true),
label: const Text('Multi-select'),
icon: const Icon(Icons.checklist),
),
appBar: SmoothAppBar(
centerTitle: false,
actions: <Widget>[
SmoothPopupMenuButton<ProductListPopupItem>(
onSelected: (final ProductListPopupItem action) async {
final ProductList? differentProductList =
await action.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
);
if (differentProductList != null) {
setState(() => productList = differentProductList);
}
},
itemBuilder: (_) => <SmoothPopupMenuItem<ProductListPopupItem>>[
if (enableRename) _rename.getMenuItem(appLocalizations),
_share.getMenuItem(appLocalizations),
_openInWeb.getMenuItem(appLocalizations),
if (enableClear) _clear.getMenuItem(appLocalizations),
],
),
],
title: _ProductListAppBarTitle(
productList: productList,
onTap: () => _onChangeList(appLocalizations, daoProductList),
enabled: widget.allowToSwitchBetweenLists,
),
],
title: _ProductListAppBarTitle(
productList: productList,
onTap: () => _onChangeList(appLocalizations, daoProductList),
enabled: widget.allowToSwitchBetweenLists,
),
titleSpacing: 0.0,
actionMode: _selectionMode,
onLeaveActionMode: () {
setState(() => _selectionMode = false);
},
actionModeTitle: Text('${_selectedBarcodes.length}'),
actionModeActions: <Widget>[
SmoothPopupMenuButton<ProductListItemPopupItem>(
onSelected: (final ProductListItemPopupItem action) async {
final bool andThenSetState = await action.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
selectedBarcodes: _selectedBarcodes,
);
if (andThenSetState) {
if (context.mounted) {
setState(() {});
titleSpacing: 0.0,
actionMode: _selectionMode,
onLeaveActionMode: () {
setState(() => _selectionMode = false);
},
actionModeTitle: Text('${_selectedBarcodes.length}'),
actionModeActions: <Widget>[
SmoothPopupMenuButton<ProductListItemPopupItem>(
onSelected: (final ProductListItemPopupItem action) async {
final bool andThenSetState = await action.doSomething(
productList: productList,
localDatabase: localDatabase,
context: context,
selectedBarcodes: _selectedBarcodes,
);
if (andThenSetState) {
if (context.mounted) {
setState(() {});
}
}
}
},
itemBuilder: (_) => <SmoothPopupMenuItem<ProductListItemPopupItem>>[
if (userPreferences.getFlag(UserPreferencesDevMode
.userPreferencesFlagBoostedComparison) ==
true)
_sideBySideItems.getMenuItem(
},
itemBuilder: (_) =>
<SmoothPopupMenuItem<ProductListItemPopupItem>>[
if (userPreferences.getFlag(UserPreferencesDevMode
.userPreferencesFlagBoostedComparison) ==
true)
_sideBySideItems.getMenuItem(
appLocalizations,
_selectedBarcodes.length >= 2 &&
_selectedBarcodes.length <= 3,
),
_rankItems.getMenuItem(
appLocalizations,
_selectedBarcodes.length >= 2 &&
_selectedBarcodes.length <= 3,
),
_rankItems.getMenuItem(
appLocalizations,
_selectedBarcodes.length >= 2,
),
_deleteItems.getMenuItem(
appLocalizations,
_selectedBarcodes.isNotEmpty,
),
],
),
],
),
body: products.isEmpty
? Center(
child: Padding(
padding: const EdgeInsets.all(SMALL_SPACE),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SvgPicture.asset(
'assets/misc/empty-list.svg',
package: AppHelper.APP_PACKAGE,
width: MediaQuery.sizeOf(context).width / 2,
),
Text(
appLocalizations.product_list_empty_message,
textAlign: TextAlign.center,
style: themeData.textTheme.bodyMedium?.apply(
color: themeData.colorScheme.onSurface,
),
),
EMPTY_WIDGET,
],
_selectedBarcodes.length >= 2,
),
),
)
: WillPopScope2(
onWillPop: () async => (await _handleUserBacktap(), null),
child: RefreshIndicator(
//if it is in selectmode then refresh indicator is not shown
notificationPredicate:
_selectionMode ? (_) => false : (_) => true,
onRefresh: () async => _refreshListProducts(
products,
localDatabase,
_deleteItems.getMenuItem(
appLocalizations,
_selectedBarcodes.isNotEmpty,
),
],
),
],
),
body: products.isEmpty
? Center(
child: Padding(
padding: const EdgeInsets.all(SMALL_SPACE),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SvgPicture.asset(
'assets/misc/empty-list.svg',
package: AppHelper.APP_PACKAGE,
width: MediaQuery.sizeOf(context).width / 2,
),
Text(
appLocalizations.product_list_empty_message,
textAlign: TextAlign.center,
style: themeData.textTheme.bodyMedium?.apply(
color: themeData.colorScheme.onSurface,
),
),
EMPTY_WIDGET,
],
),
),
child: ListView.builder(
itemCount: products.length,
itemBuilder: (BuildContext context, int index) => _buildItem(
dismissible,
)
: WillPopScope2(
onWillPop: () async => (await _handleUserBacktap(), null),
child: RefreshIndicator(
//if it is in selectmode then refresh indicator is not shown
notificationPredicate:
_selectionMode ? (_) => false : (_) => true,
onRefresh: () async => _refreshListProducts(
products,
index,
localDatabase,
appLocalizations,
),
child: ListView.builder(
itemCount: products.length,
itemBuilder: (BuildContext context, int index) =>
_buildItem(
dismissible,
products,
index,
localDatabase,
appLocalizations,
),
),
),
),
),
),
);
}

Expand Down
Loading

0 comments on commit 3c8c299

Please sign in to comment.