Skip to content
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
1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_bootstrap.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_clean.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_run_analyze.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_run_asset_gen.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_run_build_apk.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/runConfigurations/melos_run_build_bundle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_build_ipa.xml

This file was deleted.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_build_runner.xml

This file was deleted.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_format.xml

This file was deleted.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_go_ios_go.xml

This file was deleted.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_locale_gen.xml

This file was deleted.

11 changes: 0 additions & 11 deletions .idea/runConfigurations/melos_run_widgetbook_gen.xml

This file was deleted.

6 changes: 3 additions & 3 deletions apps/app_core/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {

android {
namespace = "com.flutter.boilerplate.app"
compileSdk = 35
compileSdk = 36
ndkVersion = "29.0.13113456 rc1"

compileOptions {
Expand All @@ -23,7 +23,7 @@ android {

defaultConfig {
applicationId = "com.flutter.boilerplate.app"
minSdk = 23
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
Expand Down Expand Up @@ -64,4 +64,4 @@ flutter {
dependencies {
implementation(platform("com.google.firebase:firebase-bom:33.8.0"))
implementation("com.google.firebase:firebase-analytics")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
2 changes: 1 addition & 1 deletion apps/app_core/android/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pluginManagement {

plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.0" apply false
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.0.0" apply false
id("com.google.gms.google-services") version "4.4.2" apply false
}
Expand Down
2 changes: 2 additions & 0 deletions apps/app_core/lib/app/app.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import 'package:app_core/app/config/app_config.dart';
import 'package:app_core/app/helpers/injection.dart';
import 'package:app_core/app/routes/app_router.dart';
Expand Down Expand Up @@ -127,4 +128,5 @@ class _AppState extends State<App> {
getIt<NotificationServiceInterface>().dispose();
super.dispose();
}

}
4 changes: 2 additions & 2 deletions apps/app_core/lib/app/helpers/injection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import 'package:get_it/get_it.dart';

final GetIt getIt = GetIt.instance;

final userApiClient = getIt.get<RestApiClient>(instanceName: 'user');
final RestApiClient userApiClient = getIt.get<RestApiClient>(instanceName: 'user');

final baseApiClient = getIt.get<RestApiClient>(instanceName: 'base');
final RestApiClient baseApiClient = getIt.get<RestApiClient>(instanceName: 'base');
4 changes: 2 additions & 2 deletions apps/app_core/lib/app/helpers/mixins/pagination_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ mixin PaginationService<T extends StatefulWidget> on State<T> {
/// _checkIfCanLoadMore();
/// }
/// ```
void listener() {
Future<void> listener() async {
if (scrollController.offset > scrollController.position.maxScrollExtent - 50) {
_checkIfCanLoadMore();
await _checkIfCanLoadMore();
}
}
Comment on lines +27 to 31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Async conversion is ineffective in this context.

Two issues with this change:

  1. ScrollController.addListener() expects a VoidCallback, so the returned Future<void> is ignored by the scroll controller.
  2. _checkIfCanLoadMore() contains no await statements—it calls synchronous onEndScroll()/onTopScroll() and resets the guard flags immediately, so the await on line 29 completes synchronously.

The guard flags (_canFetchBottom, _canFetchTop) are reset immediately after calling the handlers, which means they don't prevent duplicate fetch requests during actual async operations triggered by implementers.

If the intent is to prevent multiple simultaneous load-more requests, consider:

  • Making onEndScroll() return Future<void> and awaiting it before resetting the flag
  • Or exposing a method for implementers to signal completion
Suggested pattern for actual async guard protection
-  void onEndScroll();
+  Future<void> onEndScroll();

-  void onTopScroll() {}
+  Future<void> onTopScroll() async {}

   Future<void> _checkIfCanLoadMore() async {
     if (scrollController.position.pixels == 0) {
       if (!_canFetchTop) return;
       _canFetchTop = false;
-      onTopScroll();
+      await onTopScroll();
       _canFetchTop = true;
     } else {
       if (!_canFetchBottom) return;
       _canFetchBottom = false;
-      onEndScroll();
+      await onEndScroll();
       _canFetchBottom = true;
     }
   }
🤖 Prompt for AI Agents
In @apps/app_core/lib/app/helpers/mixins/pagination_mixin.dart around lines 27 -
31, The listener being async is ineffective because ScrollController.addListener
expects a VoidCallback and any Future is ignored; fix by making
onEndScroll/onTopScroll return Future<void>, update _checkIfCanLoadMore() to be
async and await those handlers before resetting the guards
(_canFetchBottom/_canFetchTop) so the flags actually prevent concurrent loads,
and change listener() to a synchronous VoidCallback that simply calls
_checkIfCanLoadMore() (fire-and-forget) or alternatively expose a completion
method for implementers to call when their async work finishes; update
references to listener(), _checkIfCanLoadMore(), onEndScroll(), onTopScroll(),
and the guard flags accordingly.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class PermissionsHelper {
return result.values.toList()[0];
}

void redirectToSettings() {
openAppSettings();
Future<void> redirectToSettings() async {
await openAppSettings();
}

/// Request multiple [permissions]
Expand Down
1 change: 0 additions & 1 deletion apps/app_core/lib/app/observers/app_bloc_observer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ final class AppBlocObserver extends BlocObserver {
super.onChange(bloc, change);
if (kDebugMode) {
logger
// ignore: avoid_dynamic_calls
.f(
'onChange(${bloc.runtimeType}, ${change.nextState.runtimeType})',
);
Expand Down
2 changes: 1 addition & 1 deletion apps/app_core/lib/app/routes/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import 'package:flutter/cupertino.dart';
part 'app_router.gr.dart';

/// [Doc Link](https://codelabs-preview.appspot.com/?file_id=1BDawGTK-riXb-PjwFCCqjwZ74yhdzFapw9kT2yJnp88#6)
@AutoRouterConfig(replaceInRouteName: 'Page|Screen,Route')
@AutoRouterConfig()
class AppRouter extends RootStackRouter {
@override
List<AutoRoute> get routes => [
Expand Down
1 change: 0 additions & 1 deletion apps/app_core/lib/bootstrap.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// ignore_for_file: require_trailing_commas
import 'dart:async';

import 'package:api_client/api_client.dart';
Expand Down
1 change: 0 additions & 1 deletion apps/app_core/lib/core/data/models/pagination_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import 'package:equatable/equatable.dart';

// ignore: must_be_immutable
class PaginationModel extends Equatable {
const PaginationModel({this.currentPage, this.hasMorePages, this.total});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class ConnectivityService {
_isDialogVisible = false;
}

void dispose() {
Future<void> dispose() async {
_removeNoInternetOverlay();
_controller.close();
await _controller.close();
}
}
1 change: 0 additions & 1 deletion apps/app_core/lib/core/data/services/media.service.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// ignore_for_file: constant_identifier_names

import 'dart:io';
import 'package:image_picker/image_picker.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class NetWorkInfoService {
});
}

void dispose() {
listener.cancel();
Future<void> dispose() async {
await listener.cancel();
}

ConnectionStatus connectionStatus = ConnectionStatus.online;
Expand Down
34 changes: 20 additions & 14 deletions apps/app_core/lib/core/presentation/screens/webview_screen.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:app_ui/app_ui.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
Expand All @@ -22,25 +24,29 @@ class WebViewScreen extends StatefulWidget {

class _WebViewScreenState extends State<WebViewScreen> {
late WebViewController webViewController = WebViewController();
bool isLoading = false;
bool _isLoading = true;

@override
void initState() {
webViewController =
WebViewController()
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (finish) {
setState(() {
isLoading = true;
});
},
),
)
..loadRequest(Uri.parse('${widget.url}'));
super.initState();
unawaited(
webViewController.setNavigationDelegate(
NavigationDelegate(
onPageFinished: (_) {
if (!mounted) return;
setState(() => _isLoading = false);

},
),
),
);

unawaited(
webViewController.loadRequest(Uri.parse(widget.url ?? '')),
);
}


@override
Widget build(BuildContext context) {
return AppScaffold(
Expand All @@ -50,7 +56,7 @@ class _WebViewScreenState extends State<WebViewScreen> {
backgroundColor: context.colorScheme.white,
),
body:
!isLoading
_isLoading
? const Center(child: AppCircularProgressIndicator())
: WebViewWidget(controller: webViewController),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:app_core/core/data/services/force_update_client.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
Expand Down Expand Up @@ -38,13 +40,13 @@ class _ForceUpdateWidgetState extends State<ForceUpdateWidget>
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_checkIfAppUpdateIsNeeded();
unawaited(_checkIfAppUpdateIsNeeded());
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_checkIfAppUpdateIsNeeded();
unawaited(_checkIfAppUpdateIsNeeded());
}
}

Expand Down Expand Up @@ -101,7 +103,7 @@ class _ForceUpdateWidgetState extends State<ForceUpdateWidget>
await widget.showStoreListing(storeUrl);
} else if (success == false) {
// * user clicked on the cancel button
} else if (success == null && allowCancel == false) {
} else if (success == null && !allowCancel) {
// * user clicked on the Android back button: show alert again
return _triggerForceUpdate(storeUrl, allowCancel);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// ignore_for_file: require_trailing_commas
import 'package:api_client/api_client.dart';
import 'package:app_core/app/config/api_endpoints.dart';
import 'package:app_core/app/helpers/injection.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
on<SignInWithGoogleTaped>(_onSignInWithGoogleTaped);
}

// ignore: unused_field
final IAuthRepository _authenticationRepository;

void _onEmailChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class SignInPage extends StatelessWidget implements AutoRouteWrapper {
SlideAndFadeAnimationWrapper(delay: 400, child: _PasswordInput()),
VSpace.large24(),
AnimatedGestureDetector(
onTap: () {
context.pushRoute(const ForgotPasswordRoute());
onTap: () async {
await context.pushRoute(const ForgotPasswordRoute());
},
child: SlideAndFadeAnimationWrapper(
delay: 200,
Expand Down Expand Up @@ -208,8 +208,8 @@ class _CreateAccountButton extends StatelessWidget {
textColor: context.colorScheme.primary500,
backgroundColor: context.colorScheme.white,
text: context.t.sign_up,
onPressed: () {
context.pushRoute(const SignUpRoute());
onPressed: () async {
await context.pushRoute(const SignUpRoute());
},
isExpanded: true,
);
Expand Down Expand Up @@ -237,8 +237,8 @@ class _ContinueWithGoogleButton extends StatelessWidget {
);
}

void _loginWithGoogle(BuildContext context) {
GoogleAuthHelper.signIn(
Future<void> _loginWithGoogle(BuildContext context) async {
await GoogleAuthHelper.signIn(
context,
onSuccess: () {
if (context.mounted) {
Expand Down
Loading
Loading