diff --git a/hooks/pre-commit b/hooks/pre-commit index 16fca9ef1..242916516 100755 --- a/hooks/pre-commit +++ b/hooks/pre-commit @@ -2,8 +2,9 @@ # This git hook fails if a user is trying to add a new file which is # not null safe. -# Check the contents of each file that is being added or modified -for file in `git diff --name-only --cached`; do +# Check the contents of each file that is being added(A) or modified(N) or +# copied (C) +for file in `git diff --name-only --diff-filter=ACM --cached`; do # Ignore the hooks from any pre-commit check if echo "$file" | grep -q 'hooks/'; then continue diff --git a/lib/models/filters/gallery_items_filter.dart b/lib/models/filters/gallery_items_filter.dart index 11b992a8c..f0e643aea 100644 --- a/lib/models/filters/gallery_items_filter.dart +++ b/lib/models/filters/gallery_items_filter.dart @@ -1,4 +1,3 @@ -// @dart=2.9 import 'package:photos/models/file.dart'; class GalleryItemsFilter { diff --git a/lib/models/filters/important_items_filter.dart b/lib/models/filters/important_items_filter.dart index 22d25d8b6..473149810 100644 --- a/lib/models/filters/important_items_filter.dart +++ b/lib/models/filters/important_items_filter.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:io'; import 'package:path/path.dart'; @@ -15,7 +13,10 @@ class ImportantItemsFilter implements GalleryItemsFilter { if (file.uploadedFileID != null) { return true; } - final String folder = basename(file.deviceFolder); + if (file.deviceFolder == null) { + return false; + } + final String folder = basename(file.deviceFolder!); if (_importantPaths.isEmpty && Platform.isAndroid) { return folder == "Camera" || folder == "Recents" || diff --git a/lib/services/billing_service.dart b/lib/services/billing_service.dart index 360d5abbc..a2042e3a2 100644 --- a/lib/services/billing_service.dart +++ b/lib/services/billing_service.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:io'; import 'package:dio/dio.dart'; @@ -15,7 +13,6 @@ import 'package:photos/models/subscription.dart'; import 'package:photos/models/user_details.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/ui/common/web_page.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; const kWebPaymentRedirectUrl = "https://payments.ente.io/frameRedirect"; @@ -39,7 +36,7 @@ class BillingService { bool _isOnSubscriptionPage = false; - Future _future; + Future? _future; void init() { // if (Platform.isIOS && kDebugMode) { @@ -75,7 +72,7 @@ class BillingService { _future ??= _fetchBillingPlans().then((response) { return BillingPlans.fromMap(response.data); }); - return _future; + return _future!; } Future> _fetchBillingPlans() { @@ -99,7 +96,7 @@ class BillingService { ); return Subscription.fromMap(response.data["subscription"]); } on DioError catch (e) { - if (e.response != null && e.response.statusCode == 409) { + if (e.response != null && e.response!.statusCode == 409) { throw SubscriptionAlreadyClaimedError(); } else { rethrow; diff --git a/lib/services/hidden_service.dart b/lib/services/hidden_service.dart index 72559df63..e12a22e9d 100644 --- a/lib/services/hidden_service.dart +++ b/lib/services/hidden_service.dart @@ -14,7 +14,6 @@ import 'package:photos/models/file.dart'; import 'package:photos/models/magic_metadata.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/file_magic_service.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/dialog_util.dart'; diff --git a/lib/services/user_service.dart b/lib/services/user_service.dart index 73c91cc28..3b9d0f4bf 100644 --- a/lib/services/user_service.dart +++ b/lib/services/user_service.dart @@ -30,7 +30,6 @@ import 'package:photos/ui/account/password_reentry_page.dart'; import 'package:photos/ui/account/two_factor_authentication_page.dart'; import 'package:photos/ui/account/two_factor_recovery_page.dart'; import 'package:photos/ui/account/two_factor_setup_page.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; diff --git a/lib/ui/account/change_email_dialog.dart b/lib/ui/account/change_email_dialog.dart index d9522acc5..37dd55535 100644 --- a/lib/ui/account/change_email_dialog.dart +++ b/lib/ui/account/change_email_dialog.dart @@ -1,19 +1,17 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/email_util.dart'; class ChangeEmailDialog extends StatefulWidget { - const ChangeEmailDialog({Key key}) : super(key: key); + const ChangeEmailDialog({Key? key}) : super(key: key); @override State createState() => _ChangeEmailDialogState(); } class _ChangeEmailDialogState extends State { - String _email; + String? _email; @override Widget build(BuildContext context) { diff --git a/lib/ui/account/delete_account_page.dart b/lib/ui/account/delete_account_page.dart index cab7b0f57..4e82d09e1 100644 --- a/lib/ui/account/delete_account_page.dart +++ b/lib/ui/account/delete_account_page.dart @@ -10,9 +10,9 @@ import 'package:photos/services/local_authentication_service.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/button_widget.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/utils/crypto_util.dart'; +import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/email_util.dart'; class DeleteAccountPage extends StatelessWidget { diff --git a/lib/ui/account/password_entry_page.dart b/lib/ui/account/password_entry_page.dart index 9b5b3a477..4545c38ed 100644 --- a/lib/ui/account/password_entry_page.dart +++ b/lib/ui/account/password_entry_page.dart @@ -12,7 +12,6 @@ import 'package:photos/services/user_service.dart'; import 'package:photos/ui/account/recovery_key_page.dart'; import 'package:photos/ui/common/dynamic_fab.dart'; import 'package:photos/ui/common/web_page.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/payment/subscription.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; diff --git a/lib/ui/account/recovery_key_page.dart b/lib/ui/account/recovery_key_page.dart index 64522fd6f..0867bd2e2 100644 --- a/lib/ui/account/recovery_key_page.dart +++ b/lib/ui/account/recovery_key_page.dart @@ -65,6 +65,7 @@ class _RecoveryKeyPageState extends State { return Scaffold( appBar: widget.showProgressBar ? AppBar( + automaticallyImplyLeading: false, elevation: 0, title: Hero( tag: "recovery_key", @@ -97,6 +98,7 @@ class _RecoveryKeyPageState extends State { child: IntrinsicHeight( child: Column( mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, children: [ widget.showAppBar ? const SizedBox.shrink() diff --git a/lib/ui/account/sessions_page.dart b/lib/ui/account/sessions_page.dart index 44d6b5ff8..80fe7cc0a 100644 --- a/lib/ui/account/sessions_page.dart +++ b/lib/ui/account/sessions_page.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; @@ -12,14 +10,14 @@ import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/toast_util.dart'; class SessionsPage extends StatefulWidget { - const SessionsPage({Key key}) : super(key: key); + const SessionsPage({Key? key}) : super(key: key); @override State createState() => _SessionsPageState(); } class _SessionsPageState extends State { - Sessions _sessions; + Sessions? _sessions; final Logger _logger = Logger("SessionsPageState"); @override @@ -45,7 +43,7 @@ class _SessionsPageState extends State { } final List rows = []; rows.add(const Padding(padding: EdgeInsets.all(4))); - for (final session in _sessions.sessions) { + for (final session in _sessions!.sessions) { rows.add(_getSessionWidget(session)); } return SingleChildScrollView( @@ -133,12 +131,14 @@ class _SessionsPageState extends State { .getActiveSessions() .onError((error, stackTrace) { showToast(context, "Failed to fetch active sessions"); - throw error; + throw error!; }); - _sessions.sessions.sort((first, second) { - return second.lastUsedTime.compareTo(first.lastUsedTime); - }); - setState(() {}); + if (_sessions != null) { + _sessions!.sessions.sort((first, second) { + return second.lastUsedTime.compareTo(first.lastUsedTime); + }); + setState(() {}); + } } void _showSessionTerminationDialog(Session session) { diff --git a/lib/ui/account/two_factor_authentication_page.dart b/lib/ui/account/two_factor_authentication_page.dart index 011a5f4e2..d41035a13 100644 --- a/lib/ui/account/two_factor_authentication_page.dart +++ b/lib/ui/account/two_factor_authentication_page.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:photos/services/user_service.dart'; @@ -9,7 +7,7 @@ import 'package:pinput/pin_put/pin_put.dart'; class TwoFactorAuthenticationPage extends StatefulWidget { final String sessionID; - const TwoFactorAuthenticationPage(this.sessionID, {Key key}) + const TwoFactorAuthenticationPage(this.sessionID, {Key? key}) : super(key: key); @override @@ -25,7 +23,7 @@ class _TwoFactorAuthenticationPageState borderRadius: BorderRadius.circular(15.0), ); String _code = ""; - LifecycleEventHandler _lifecycleEventHandler; + late LifecycleEventHandler _lifecycleEventHandler; @override void initState() { @@ -33,8 +31,8 @@ class _TwoFactorAuthenticationPageState resumeCallBack: () async { if (mounted) { final data = await Clipboard.getData(Clipboard.kTextPlain); - if (data != null && data.text != null && data.text.length == 6) { - _pinController.text = data.text; + if (data != null && data.text != null && data.text!.length == 6) { + _pinController.text = data.text!; } } }, diff --git a/lib/ui/account/two_factor_recovery_page.dart b/lib/ui/account/two_factor_recovery_page.dart index 12450a81c..acb2ba206 100644 --- a/lib/ui/account/two_factor_recovery_page.dart +++ b/lib/ui/account/two_factor_recovery_page.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:ui'; import 'package:flutter/material.dart'; @@ -15,7 +13,7 @@ class TwoFactorRecoveryPage extends StatefulWidget { this.sessionID, this.encryptedSecret, this.secretDecryptionNonce, { - Key key, + Key? key, }) : super(key: key); @override diff --git a/lib/ui/account/two_factor_setup_page.dart b/lib/ui/account/two_factor_setup_page.dart index 0ab4268cf..c3eaaabca 100644 --- a/lib/ui/account/two_factor_setup_page.dart +++ b/lib/ui/account/two_factor_setup_page.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:async'; import 'dart:ui'; @@ -24,7 +22,7 @@ class TwoFactorSetupPage extends StatefulWidget { this.secretCode, this.qrCode, this.completer, { - Key key, + Key? key, }) : super(key: key); @override @@ -33,15 +31,15 @@ class TwoFactorSetupPage extends StatefulWidget { class _TwoFactorSetupPageState extends State with SingleTickerProviderStateMixin { - TabController _tabController; + late TabController _tabController; final _pinController = TextEditingController(); final _pinPutDecoration = BoxDecoration( border: Border.all(color: const Color.fromRGBO(45, 194, 98, 1.0)), borderRadius: BorderRadius.circular(15.0), ); String _code = ""; - ImageProvider _imageProvider; - LifecycleEventHandler _lifecycleEventHandler; + late ImageProvider _imageProvider; + late LifecycleEventHandler _lifecycleEventHandler; @override void initState() { @@ -55,8 +53,8 @@ class _TwoFactorSetupPageState extends State resumeCallBack: () async { if (mounted) { final data = await Clipboard.getData(Clipboard.kTextPlain); - if (data != null && data.text != null && data.text.length == 6) { - _pinController.text = data.text; + if (data != null && data.text != null && data.text!.length == 6) { + _pinController.text = data.text!; } } }, diff --git a/lib/ui/account/verify_recovery_page.dart b/lib/ui/account/verify_recovery_page.dart index 44cf063a4..823672277 100644 --- a/lib/ui/account/verify_recovery_page.dart +++ b/lib/ui/account/verify_recovery_page.dart @@ -14,7 +14,6 @@ import 'package:photos/services/user_service.dart'; import 'package:photos/ui/account/recovery_key_page.dart'; import 'package:photos/ui/common/dialogs.dart'; import 'package:photos/ui/common/gradient_button.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; diff --git a/lib/ui/actions/collection/collection_file_actions.dart b/lib/ui/actions/collection/collection_file_actions.dart index 25f3bc345..a0cd57b89 100644 --- a/lib/ui/actions/collection/collection_file_actions.dart +++ b/lib/ui/actions/collection/collection_file_actions.dart @@ -8,7 +8,6 @@ import 'package:photos/services/favorites_service.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; import 'package:photos/ui/common/progress_dialog.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/toast_util.dart'; @@ -21,7 +20,9 @@ extension CollectionFileActions on CollectionActions { final count = selectedFiles.files.length; final textTheme = getEnteTextTheme(context); final showDeletePrompt = await _anyItemPresentOnlyInCurrentAlbum( - selectedFiles.files, collection.id); + selectedFiles.files, + collection.id, + ); final String title = showDeletePrompt ? "Delete items?" : "Remove from album?"; final String message1 = showDeletePrompt diff --git a/lib/ui/actions/collection/collection_sharing_actions.dart b/lib/ui/actions/collection/collection_sharing_actions.dart index 47fb86930..0a9fa7ba8 100644 --- a/lib/ui/actions/collection/collection_sharing_actions.dart +++ b/lib/ui/actions/collection/collection_sharing_actions.dart @@ -11,7 +11,6 @@ import 'package:photos/services/hidden_service.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/common/dialogs.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/payment/subscription.dart'; import 'package:photos/utils/date_time_util.dart'; import 'package:photos/utils/dialog_util.dart'; diff --git a/lib/ui/backup_folder_selection_page.dart b/lib/ui/backup_folder_selection_page.dart index a0b681ea7..61a3afab1 100644 --- a/lib/ui/backup_folder_selection_page.dart +++ b/lib/ui/backup_folder_selection_page.dart @@ -16,7 +16,6 @@ import 'package:photos/models/device_collection.dart'; import 'package:photos/models/file.dart'; import 'package:photos/services/remote_sync_service.dart'; import 'package:photos/ui/common/loading_widget.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/viewer/file/thumbnail_widget.dart'; import 'package:photos/utils/dialog_util.dart'; diff --git a/lib/ui/collections/archived_collections_button_widget.dart b/lib/ui/collections/archived_collections_button_widget.dart index 95e0f5443..fd1292588 100644 --- a/lib/ui/collections/archived_collections_button_widget.dart +++ b/lib/ui/collections/archived_collections_button_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/core/configuration.dart'; import 'package:photos/db/files_db.dart'; @@ -12,7 +10,7 @@ class ArchivedCollectionsButtonWidget extends StatelessWidget { const ArchivedCollectionsButtonWidget( this.textStyle, { - Key key, + Key? key, }) : super(key: key); @override @@ -26,7 +24,7 @@ class ArchivedCollectionsButtonWidget extends StatelessWidget { padding: const EdgeInsets.all(0), side: BorderSide( width: 0.5, - color: Theme.of(context).iconTheme.color.withOpacity(0.24), + color: Theme.of(context).iconTheme.color!.withOpacity(0.24), ), ), child: SizedBox( @@ -50,7 +48,7 @@ class ArchivedCollectionsButtonWidget extends StatelessWidget { Configuration.instance.getUserID(), ), builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data > 0) { + if (snapshot.hasData && snapshot.data! > 0) { return RichText( text: TextSpan( style: textStyle, diff --git a/lib/ui/collections/create_new_album_widget.dart b/lib/ui/collections/create_new_album_widget.dart index 3adf8dc4f..31e5d3463 100644 --- a/lib/ui/collections/create_new_album_widget.dart +++ b/lib/ui/collections/create_new_album_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:photos/core/event_bus.dart'; @@ -7,9 +5,7 @@ import 'package:photos/events/tab_changed_event.dart'; import 'package:photos/utils/toast_util.dart'; class CreateNewAlbumWidget extends StatelessWidget { - const CreateNewAlbumWidget({ - Key key, - }) : super(key: key); + const CreateNewAlbumWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -23,14 +19,14 @@ class CreateNewAlbumWidget extends StatelessWidget { blurRadius: 2, spreadRadius: 0, offset: const Offset(0, 0), - color: Theme.of(context).iconTheme.color.withOpacity(0.3), + color: Theme.of(context).iconTheme.color!.withOpacity(0.3), ) ], borderRadius: BorderRadius.circular(4), ), child: Icon( Icons.add, - color: Theme.of(context).iconTheme.color.withOpacity(0.25), + color: Theme.of(context).iconTheme.color!.withOpacity(0.25), ), ), onTap: () async { diff --git a/lib/ui/collections/device_folder_icon_widget.dart b/lib/ui/collections/device_folder_icon_widget.dart index f81ab1de0..d76e40068 100644 --- a/lib/ui/collections/device_folder_icon_widget.dart +++ b/lib/ui/collections/device_folder_icon_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/ente_theme_data.dart'; import 'package:photos/models/device_collection.dart'; @@ -12,7 +10,7 @@ class DeviceFolderIcon extends StatelessWidget { final DeviceCollection deviceCollection; const DeviceFolderIcon( this.deviceCollection, { - Key key, + Key? key, }) : super(key: key); @override @@ -35,7 +33,7 @@ class DeviceFolderIcon extends StatelessWidget { child: Hero( tag: "device_folder:" + deviceCollection.name + - deviceCollection.thumbnail.tag, + deviceCollection.thumbnail!.tag, child: Stack( children: [ ThumbnailWidget( @@ -44,7 +42,7 @@ class DeviceFolderIcon extends StatelessWidget { key: Key( "device_folder:" + deviceCollection.name + - deviceCollection.thumbnail.tag, + deviceCollection.thumbnail!.tag, ), ), isBackedUp ? Container() : const UnSyncedIcon(), diff --git a/lib/ui/collections/trash_button_widget.dart b/lib/ui/collections/trash_button_widget.dart index 74d426283..f407fe02b 100644 --- a/lib/ui/collections/trash_button_widget.dart +++ b/lib/ui/collections/trash_button_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:async'; import 'package:flutter/material.dart'; @@ -12,7 +10,7 @@ import 'package:photos/utils/navigation_util.dart'; class TrashButtonWidget extends StatefulWidget { const TrashButtonWidget( this.textStyle, { - Key key, + Key? key, }) : super(key: key); final TextStyle textStyle; @@ -22,7 +20,7 @@ class TrashButtonWidget extends StatefulWidget { } class _TrashButtonWidgetState extends State { - StreamSubscription _trashUpdatedEventSubscription; + late StreamSubscription _trashUpdatedEventSubscription; @override void initState() { @@ -37,7 +35,7 @@ class _TrashButtonWidgetState extends State { @override void dispose() { - _trashUpdatedEventSubscription?.cancel(); + _trashUpdatedEventSubscription.cancel(); super.dispose(); } @@ -52,7 +50,7 @@ class _TrashButtonWidgetState extends State { padding: const EdgeInsets.all(0), side: BorderSide( width: 0.5, - color: Theme.of(context).iconTheme.color.withOpacity(0.24), + color: Theme.of(context).iconTheme.color!.withOpacity(0.24), ), ), child: SizedBox( @@ -73,7 +71,7 @@ class _TrashButtonWidgetState extends State { FutureBuilder( future: TrashDB.instance.count(), builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data > 0) { + if (snapshot.hasData && snapshot.data! > 0) { return RichText( text: TextSpan( style: widget.textStyle, diff --git a/lib/ui/components/action_sheet_widget.dart b/lib/ui/components/action_sheet_widget.dart index 0158377ee..71e6a7a2e 100644 --- a/lib/ui/components/action_sheet_widget.dart +++ b/lib/ui/components/action_sheet_widget.dart @@ -14,37 +14,13 @@ enum ActionSheetType { iconOnly, } -Future showCommonActionSheet({ - required BuildContext context, - required List buttons, - required ActionSheetType actionSheetType, - bool isCheckIconGreen = false, - String? title, - String? body, -}) { - return showMaterialModalBottomSheet( - backgroundColor: Colors.transparent, - barrierColor: backdropFaintDark, - useRootNavigator: true, - context: context, - builder: (_) { - return ActionSheetWidget( - title: title, - body: body, - actionButtons: buttons, - actionSheetType: actionSheetType, - isCheckIconGreen: isCheckIconGreen, - ); - }, - isDismissible: false, - enableDrag: false, - ); -} - +///Returns null if dismissed Future showActionSheet({ required BuildContext context, required List buttons, required ActionSheetType actionSheetType, + bool enableDrag = true, + bool isDismissible = true, bool isCheckIconGreen = false, String? title, String? body, @@ -54,6 +30,8 @@ Future showActionSheet({ barrierColor: backdropFaintDark, useRootNavigator: true, context: context, + isDismissible: isDismissible, + enableDrag: enableDrag, builder: (_) { return ActionSheetWidget( title: title, @@ -63,8 +41,6 @@ Future showActionSheet({ isCheckIconGreen: isCheckIconGreen, ); }, - isDismissible: false, - enableDrag: false, ); } diff --git a/lib/ui/components/dialog_widget.dart b/lib/ui/components/dialog_widget.dart index 9c0f25c82..d2a1b0aa8 100644 --- a/lib/ui/components/dialog_widget.dart +++ b/lib/ui/components/dialog_widget.dart @@ -6,76 +6,19 @@ import 'package:photos/theme/colors.dart'; import 'package:photos/theme/effects.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/button_widget.dart'; -import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/utils/separators_util.dart'; -Future showGenericErrorDialog({ - required BuildContext context, -}) async { - return showDialogWidget( - context: context, - title: "Error", - icon: Icons.error_outline_outlined, - body: "It looks like something went wrong. Please try again.", - buttons: const [ - ButtonWidget( - buttonType: ButtonType.secondary, - labelText: "OK", - isInAlert: true, - ), - ], - ); -} - -Future showNewChoiceDialog({ - required BuildContext context, - required String title, - String? body, - required String firstButtonLabel, - String secondButtonLabel = "Cancel", - ButtonType firstButtonType = ButtonType.neutral, - ButtonType secondButtonType = ButtonType.secondary, - ButtonAction firstButtonAction = ButtonAction.first, - ButtonAction secondButtonAction = ButtonAction.cancel, - FutureVoidCallback? firstButtonOnTap, - FutureVoidCallback? secondButtonOnTap, - bool isCritical = false, - IconData? icon, -}) async { - final buttons = [ - ButtonWidget( - buttonType: isCritical ? ButtonType.critical : firstButtonType, - labelText: firstButtonLabel, - isInAlert: true, - onTap: firstButtonOnTap, - buttonAction: firstButtonAction, - ), - ButtonWidget( - buttonType: secondButtonType, - labelText: secondButtonLabel, - isInAlert: true, - onTap: secondButtonOnTap, - buttonAction: secondButtonAction, - ), - ]; - return showDialogWidget( - context: context, - title: title, - body: body, - buttons: buttons, - icon: icon, - ); -} - +///Will return null if dismissed by tapping outside Future showDialogWidget({ required BuildContext context, required String title, String? body, required List buttons, IconData? icon, + bool isDismissible = true, }) { return showDialog( - barrierDismissible: false, + barrierDismissible: isDismissible, barrierColor: backdropFaintDark, context: context, builder: (context) { @@ -89,7 +32,6 @@ Future showDialogWidget({ title: title, body: body, buttons: buttons, - isMobileSmall: isMobileSmall, icon: icon, ), ), @@ -103,12 +45,10 @@ class DialogWidget extends StatelessWidget { final String? body; final List buttons; final IconData? icon; - final bool isMobileSmall; const DialogWidget({ required this.title, this.body, required this.buttons, - required this.isMobileSmall, this.icon, super.key, }); @@ -116,6 +56,7 @@ class DialogWidget extends StatelessWidget { @override Widget build(BuildContext context) { final widthOfScreen = MediaQuery.of(context).size.width; + final isMobileSmall = widthOfScreen <= mobileSmallThreshold; final colorScheme = getEnteColorScheme(context); return Container( width: min(widthOfScreen, 320), diff --git a/lib/ui/create_collection_page.dart b/lib/ui/create_collection_page.dart index 0b1c2c120..23ff5980a 100644 --- a/lib/ui/create_collection_page.dart +++ b/lib/ui/create_collection_page.dart @@ -14,7 +14,6 @@ import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/services/remote_sync_service.dart'; import 'package:photos/ui/common/gradient_button.dart'; import 'package:photos/ui/common/loading_widget.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/viewer/file/no_thumbnail_widget.dart'; import 'package:photos/ui/viewer/file/thumbnail_widget.dart'; import 'package:photos/ui/viewer/gallery/collection_page.dart'; diff --git a/lib/ui/home/grant_permissions_widget.dart b/lib/ui/home/grant_permissions_widget.dart index 091bc8844..84c352eda 100644 --- a/lib/ui/home/grant_permissions_widget.dart +++ b/lib/ui/home/grant_permissions_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:io'; import 'package:flutter/material.dart'; @@ -7,7 +5,7 @@ import 'package:photo_manager/photo_manager.dart'; import 'package:photos/services/sync_service.dart'; class GrantPermissionsWidget extends StatelessWidget { - const GrantPermissionsWidget({Key key}) : super(key: key); + const GrantPermissionsWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final isLightMode = @@ -55,7 +53,7 @@ class GrantPermissionsWidget extends StatelessWidget { text: TextSpan( style: Theme.of(context) .textTheme - .headline5 + .headline5! .copyWith(fontWeight: FontWeight.w700), children: [ const TextSpan(text: 'ente '), @@ -63,7 +61,7 @@ class GrantPermissionsWidget extends StatelessWidget { text: "needs permission to ", style: Theme.of(context) .textTheme - .headline5 + .headline5! .copyWith(fontWeight: FontWeight.w400), ), const TextSpan(text: 'preserve your photos'), @@ -109,7 +107,7 @@ class GrantPermissionsWidget extends StatelessWidget { TextButton( child: Text( "OK", - style: Theme.of(context).textTheme.subtitle1.copyWith( + style: Theme.of(context).textTheme.subtitle1!.copyWith( fontSize: 14, fontWeight: FontWeight.w700, ), diff --git a/lib/ui/huge_listview/place_holder_widget.dart b/lib/ui/huge_listview/place_holder_widget.dart index 06c0d3342..7b87dfc30 100644 --- a/lib/ui/huge_listview/place_holder_widget.dart +++ b/lib/ui/huge_listview/place_holder_widget.dart @@ -1,12 +1,10 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; class PlaceHolderWidget extends StatelessWidget { const PlaceHolderWidget( this.count, this.columns, { - Key key, + Key? key, }) : super(key: key); final int count, columns; @@ -33,7 +31,7 @@ class PlaceHolderWidget extends StatelessWidget { ), ); } - return _gridViewCache[key]; + return _gridViewCache[key]!; } String _getCacheKey(int totalCount, int columns) { diff --git a/lib/ui/notification/prompts/password_reminder.dart b/lib/ui/notification/prompts/password_reminder.dart index 3a5fa655d..d3b8ac5fc 100644 --- a/lib/ui/notification/prompts/password_reminder.dart +++ b/lib/ui/notification/prompts/password_reminder.dart @@ -11,7 +11,6 @@ import 'package:photos/theme/colors.dart'; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/account/password_entry_page.dart'; import 'package:photos/ui/common/gradient_button.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/home_widget.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; diff --git a/lib/ui/payment/child_subscription_widget.dart b/lib/ui/payment/child_subscription_widget.dart index 6c1fa03bb..c6808fbe2 100644 --- a/lib/ui/payment/child_subscription_widget.dart +++ b/lib/ui/payment/child_subscription_widget.dart @@ -1,24 +1,21 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/ente_theme_data.dart'; import 'package:photos/models/user_details.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/ui/common/dialogs.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; class ChildSubscriptionWidget extends StatelessWidget { const ChildSubscriptionWidget({ - Key key, - @required this.userDetails, + Key? key, + required this.userDetails, }) : super(key: key); final UserDetails userDetails; @override Widget build(BuildContext context) { - final String familyAdmin = userDetails.familyData.members + final String familyAdmin = userDetails.familyData!.members! .firstWhere((element) => element.isAdmin) .email; return Padding( @@ -102,7 +99,7 @@ class ChildSubscriptionWidget extends StatelessWidget { ), TextSpan( text: "support@ente.io", - style: Theme.of(context).textTheme.bodyText2.copyWith( + style: Theme.of(context).textTheme.bodyText2?.copyWith( color: const Color.fromRGBO(29, 185, 84, 1), ), ), diff --git a/lib/ui/payment/payment_web_page.dart b/lib/ui/payment/payment_web_page.dart index ff4419491..8266bfef4 100644 --- a/lib/ui/payment/payment_web_page.dart +++ b/lib/ui/payment/payment_web_page.dart @@ -12,7 +12,6 @@ import 'package:photos/services/billing_service.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/ui/common/loading_widget.dart'; import 'package:photos/ui/common/progress_dialog.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; class PaymentWebPage extends StatefulWidget { diff --git a/lib/ui/payment/skip_subscription_widget.dart b/lib/ui/payment/skip_subscription_widget.dart index 0e4490a3a..1f122c4f0 100644 --- a/lib/ui/payment/skip_subscription_widget.dart +++ b/lib/ui/payment/skip_subscription_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/core/event_bus.dart'; import 'package:photos/events/subscription_purchased_event.dart'; @@ -10,8 +8,8 @@ import 'package:photos/ui/home_widget.dart'; class SkipSubscriptionWidget extends StatelessWidget { const SkipSubscriptionWidget({ - Key key, - @required this.freePlan, + Key? key, + required this.freePlan, }) : super(key: key); final FreePlan freePlan; @@ -24,10 +22,10 @@ class SkipSubscriptionWidget extends StatelessWidget { margin: const EdgeInsets.fromLTRB(0, 30, 0, 0), padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), child: OutlinedButton( - style: Theme.of(context).outlinedButtonTheme.style.copyWith( + style: Theme.of(context).outlinedButtonTheme.style?.copyWith( textStyle: MaterialStateProperty.resolveWith( (Set states) { - return Theme.of(context).textTheme.subtitle1; + return Theme.of(context).textTheme.subtitle1!; }, ), ), diff --git a/lib/ui/payment/stripe_subscription_page.dart b/lib/ui/payment/stripe_subscription_page.dart index 1903fbf48..bc6091d8f 100644 --- a/lib/ui/payment/stripe_subscription_page.dart +++ b/lib/ui/payment/stripe_subscription_page.dart @@ -15,7 +15,6 @@ import 'package:photos/ui/common/dialogs.dart'; import 'package:photos/ui/common/loading_widget.dart'; import 'package:photos/ui/common/progress_dialog.dart'; import 'package:photos/ui/common/web_page.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/payment/child_subscription_widget.dart'; import 'package:photos/ui/payment/payment_web_page.dart'; import 'package:photos/ui/payment/skip_subscription_widget.dart'; diff --git a/lib/ui/payment/subscription.dart b/lib/ui/payment/subscription.dart index f4c8d1b27..7096ee919 100644 --- a/lib/ui/payment/subscription.dart +++ b/lib/ui/payment/subscription.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/cupertino.dart'; import 'package:photos/core/configuration.dart'; import 'package:photos/services/feature_flag_service.dart'; @@ -24,5 +22,5 @@ StatefulWidget getSubscriptionPage({bool isOnBoarding = false}) { // users who might have paid via playStore. This method should be removed once // we have better handling for active play/app store subscription & stripe plans. bool _isUserCreatedPostStripeSupport() { - return Configuration.instance.getUserID() > 1580559962386460; + return Configuration.instance.getUserID()! > 1580559962386460; } diff --git a/lib/ui/payment/subscription_page.dart b/lib/ui/payment/subscription_page.dart index 33144cfef..2c45b7a77 100644 --- a/lib/ui/payment/subscription_page.dart +++ b/lib/ui/payment/subscription_page.dart @@ -16,7 +16,6 @@ import 'package:photos/services/billing_service.dart'; import 'package:photos/services/user_service.dart'; import 'package:photos/ui/common/loading_widget.dart'; import 'package:photos/ui/common/progress_dialog.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/payment/child_subscription_widget.dart'; import 'package:photos/ui/payment/skip_subscription_widget.dart'; import 'package:photos/ui/payment/subscription_common_widgets.dart'; diff --git a/lib/ui/settings/about_section_widget.dart b/lib/ui/settings/about_section_widget.dart index 4e2428346..8e852aa5a 100644 --- a/lib/ui/settings/about_section_widget.dart +++ b/lib/ui/settings/about_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/services/update_service.dart'; import 'package:photos/theme/ente_theme.dart'; @@ -14,7 +12,7 @@ import 'package:photos/utils/toast_util.dart'; import 'package:url_launcher/url_launcher.dart'; class AboutSectionWidget extends StatelessWidget { - const AboutSectionWidget({Key key}) : super(key: key); + const AboutSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -96,12 +94,12 @@ class AboutSectionWidget extends StatelessWidget { class AboutMenuItemWidget extends StatelessWidget { final String title; final String url; - final String webPageTitle; + final String? webPageTitle; const AboutMenuItemWidget({ - @required this.title, - @required this.url, + required this.title, + required this.url, this.webPageTitle, - Key key, + Key? key, }) : super(key: key); @override diff --git a/lib/ui/settings/account_section_widget.dart b/lib/ui/settings/account_section_widget.dart index 7b374c3b3..276647709 100644 --- a/lib/ui/settings/account_section_widget.dart +++ b/lib/ui/settings/account_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:async'; import 'package:flutter/material.dart'; @@ -13,14 +11,14 @@ import 'package:photos/ui/account/delete_account_page.dart'; import 'package:photos/ui/account/password_entry_page.dart'; import 'package:photos/ui/account/recovery_key_page.dart'; import 'package:photos/ui/components/captioned_text_widget.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/components/expandable_menu_item_widget.dart'; import 'package:photos/ui/components/menu_item_widget.dart'; import 'package:photos/ui/settings/common_settings.dart'; +import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; class AccountSectionWidget extends StatelessWidget { - const AccountSectionWidget({Key key}) : super(key: key); + const AccountSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/app_version_widget.dart b/lib/ui/settings/app_version_widget.dart index a991dafad..ee04caca9 100644 --- a/lib/ui/settings/app_version_widget.dart +++ b/lib/ui/settings/app_version_widget.dart @@ -1,11 +1,9 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; class AppVersionWidget extends StatefulWidget { const AppVersionWidget({ - Key key, + Key? key, }) : super(key: key); @override @@ -16,7 +14,7 @@ class _AppVersionWidgetState extends State { static const kTapThresholdForInspector = 5; static const kConsecutiveTapTimeWindowInMilliseconds = 2000; - int _lastTap; + int? _lastTap; int _consecutiveTaps = 0; @override @@ -35,14 +33,14 @@ class _AppVersionWidgetState extends State { } _lastTap = now; }, - child: FutureBuilder( + child: FutureBuilder( future: _getAppVersion(), builder: (context, snapshot) { if (snapshot.hasData) { return Padding( padding: const EdgeInsets.all(20), child: Text( - "Version: " + snapshot.data, + "Version: " + snapshot.data!, style: Theme.of(context).textTheme.caption, ), ); diff --git a/lib/ui/settings/backup_section_widget.dart b/lib/ui/settings/backup_section_widget.dart index 397dbd18c..25d103d7d 100644 --- a/lib/ui/settings/backup_section_widget.dart +++ b/lib/ui/settings/backup_section_widget.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:photos/ente_theme_data.dart'; import 'package:photos/models/backup_status.dart'; import 'package:photos/models/duplicate_files.dart'; import 'package:photos/services/deduplication_service.dart'; @@ -16,6 +15,7 @@ import 'package:photos/ui/components/captioned_text_widget.dart'; import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/components/expandable_menu_item_widget.dart'; import 'package:photos/ui/components/menu_item_widget.dart'; +import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/ui/settings/common_settings.dart'; import 'package:photos/ui/tools/deduplicate_page.dart'; import 'package:photos/ui/tools/free_space_page.dart'; @@ -162,45 +162,30 @@ class BackupSectionWidgetState extends State { } void _showSpaceFreedDialog(BackupStatus status) { - final AlertDialog alert = AlertDialog( - title: const Text("Success"), - content: Text( - "You have successfully freed up " + formatBytes(status.size) + "!", - ), - actions: [ - TextButton( - child: Text( - "Rate us", - style: TextStyle( - color: Theme.of(context).colorScheme.greenAlternative, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - final url = UpdateService.instance.getRateDetails().item2; - launchUrlString(url); - }, - ), - TextButton( - child: const Text( - "Ok", - ), - onPressed: () { - if (Platform.isIOS) { - showToast( - context, - "Also empty \"Recently Deleted\" from \"Settings\" -> \"Storage\" to claim the freed space", - ); - } - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], + final DialogWidget dialog = choiceDialog( + title: "Success", + body: "You have successfully freed up " + formatBytes(status.size) + "!", + firstButtonLabel: "Rate us", + firstButtonOnTap: () async { + final url = UpdateService.instance.getRateDetails().item2; + launchUrlString(url); + }, + firstButtonType: ButtonType.primary, + secondButtonLabel: "OK", + secondButtonOnTap: () async { + if (Platform.isIOS) { + showToast( + context, + "Also empty \"Recently Deleted\" from \"Settings\" -> \"Storage\" to claim the freed space", + ); + } + }, ); + showConfettiDialog( context: context, - builder: (BuildContext context) { - return alert; + dialogBuilder: (BuildContext context) { + return dialog; }, barrierColor: Colors.black87, confettiAlignment: Alignment.topCenter, @@ -212,48 +197,33 @@ class BackupSectionWidgetState extends State { final String countText = result.count.toString() + " duplicate file" + (result.count == 1 ? "" : "s"); - final AlertDialog alert = AlertDialog( - title: const Text("✨ Success"), - content: Text( - "You have cleaned up " + - countText + - ", saving " + - formatBytes(result.size) + - "!", - ), - actions: [ - TextButton( - child: Text( - "Rate us", - style: TextStyle( - color: Theme.of(context).colorScheme.greenAlternative, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - // TODO: Replace with https://pub.dev/packages/in_app_review - final url = UpdateService.instance.getRateDetails().item2; - launchUrlString(url); - }, - ), - TextButton( - child: const Text( - "Ok", - ), - onPressed: () { - showShortToast( - context, - "Also empty your \"Trash\" to claim the freed up space", - ); - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], + final DialogWidget dialog = choiceDialog( + title: "✨ Success", + body: "You have cleaned up " + + countText + + ", saving " + + formatBytes(result.size) + + "!", + firstButtonLabel: "Rate us", + firstButtonOnTap: () async { + // TODO: Replace with https://pub.dev/packages/in_app_review + final url = UpdateService.instance.getRateDetails().item2; + launchUrlString(url); + }, + firstButtonType: ButtonType.primary, + secondButtonLabel: "OK", + secondButtonOnTap: () async { + showShortToast( + context, + "Also empty your \"Trash\" to claim the freed up space", + ); + }, ); + showConfettiDialog( context: context, - builder: (BuildContext context) { - return alert; + dialogBuilder: (BuildContext context) { + return dialog; }, barrierColor: Colors.black87, confettiAlignment: Alignment.topCenter, diff --git a/lib/ui/settings/debug_section_widget.dart b/lib/ui/settings/debug_section_widget.dart index a2f608605..c5b950dac 100644 --- a/lib/ui/settings/debug_section_widget.dart +++ b/lib/ui/settings/debug_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:flutter_sodium/flutter_sodium.dart'; import 'package:photos/core/configuration.dart'; @@ -15,7 +13,7 @@ import 'package:photos/ui/settings/common_settings.dart'; import 'package:photos/utils/toast_util.dart'; class DebugSectionWidget extends StatelessWidget { - const DebugSectionWidget({Key key}) : super(key: key); + const DebugSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -75,7 +73,7 @@ class DebugSectionWidget extends StatelessWidget { } void _showKeyAttributesDialog(BuildContext context) { - final keyAttributes = Configuration.instance.getKeyAttributes(); + final keyAttributes = Configuration.instance.getKeyAttributes()!; final AlertDialog alert = AlertDialog( title: const Text("key attributes"), content: SingleChildScrollView( @@ -85,7 +83,7 @@ class DebugSectionWidget extends StatelessWidget { "Key", style: TextStyle(fontWeight: FontWeight.bold), ), - Text(Sodium.bin2base64(Configuration.instance.getKey())), + Text(Sodium.bin2base64(Configuration.instance.getKey()!)), const Padding(padding: EdgeInsets.all(12)), const Text( "Encrypted Key", diff --git a/lib/ui/settings/general_section_widget.dart b/lib/ui/settings/general_section_widget.dart index c1696a0d2..a3e73bf34 100644 --- a/lib/ui/settings/general_section_widget.dart +++ b/lib/ui/settings/general_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/services/user_service.dart'; @@ -14,7 +12,7 @@ import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/navigation_util.dart'; class GeneralSectionWidget extends StatelessWidget { - const GeneralSectionWidget({Key key}) : super(key: key); + const GeneralSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/settings/security_section_widget.dart b/lib/ui/settings/security_section_widget.dart index ea964247e..4c1d5e5ec 100644 --- a/lib/ui/settings/security_section_widget.dart +++ b/lib/ui/settings/security_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:async'; import 'dart:io'; @@ -20,7 +18,7 @@ import 'package:photos/ui/components/toggle_switch_widget.dart'; import 'package:photos/ui/settings/common_settings.dart'; class SecuritySectionWidget extends StatefulWidget { - const SecuritySectionWidget({Key key}) : super(key: key); + const SecuritySectionWidget({Key? key}) : super(key: key); @override State createState() => _SecuritySectionWidgetState(); @@ -29,7 +27,8 @@ class SecuritySectionWidget extends StatefulWidget { class _SecuritySectionWidgetState extends State { final _config = Configuration.instance; - StreamSubscription _twoFactorStatusChangeEvent; + late StreamSubscription + _twoFactorStatusChangeEvent; @override void initState() { diff --git a/lib/ui/settings/settings_text_item.dart b/lib/ui/settings/settings_text_item.dart deleted file mode 100644 index 32dc01b08..000000000 --- a/lib/ui/settings/settings_text_item.dart +++ /dev/null @@ -1,35 +0,0 @@ -// @dart=2.9 - -import 'dart:io'; - -import 'package:flutter/material.dart'; - -class SettingsTextItem extends StatelessWidget { - final String text; - final IconData icon; - const SettingsTextItem({ - Key key, - @required this.text, - @required this.icon, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Padding(padding: EdgeInsets.all(Platform.isIOS ? 4 : 6)), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Align( - alignment: Alignment.centerLeft, - child: Text(text, style: Theme.of(context).textTheme.subtitle1), - ), - Icon(icon), - ], - ), - Padding(padding: EdgeInsets.all(Platform.isIOS ? 4 : 6)), - ], - ); - } -} diff --git a/lib/ui/settings/social_section_widget.dart b/lib/ui/settings/social_section_widget.dart index 26517f8a4..a2f4fc358 100644 --- a/lib/ui/settings/social_section_widget.dart +++ b/lib/ui/settings/social_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/services/update_service.dart'; import 'package:photos/theme/ente_theme.dart'; @@ -10,7 +8,7 @@ import 'package:photos/ui/settings/common_settings.dart'; import 'package:url_launcher/url_launcher_string.dart'; class SocialSectionWidget extends StatelessWidget { - const SocialSectionWidget({Key key}) : super(key: key); + const SocialSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -60,7 +58,7 @@ class SocialSectionWidget extends StatelessWidget { class SocialsMenuItemWidget extends StatelessWidget { final String text; final String urlSring; - const SocialsMenuItemWidget(this.text, this.urlSring, {Key key}) + const SocialsMenuItemWidget(this.text, this.urlSring, {Key? key}) : super(key: key); @override diff --git a/lib/ui/settings/support_section_widget.dart b/lib/ui/settings/support_section_widget.dart index 2407885aa..cbd2458a5 100644 --- a/lib/ui/settings/support_section_widget.dart +++ b/lib/ui/settings/support_section_widget.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'dart:io'; import 'package:flutter/material.dart'; @@ -15,7 +13,7 @@ import 'package:photos/ui/settings/common_settings.dart'; import 'package:photos/utils/email_util.dart'; class SupportSectionWidget extends StatelessWidget { - const SupportSectionWidget({Key key}) : super(key: key); + const SupportSectionWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -63,7 +61,9 @@ class SupportSectionWidget extends StatelessWidget { final endpoint = Configuration.instance.getHttpEndpoint() + "/users/roadmap"; final url = Configuration.instance.isLoggedIn() - ? endpoint + "?token=" + Configuration.instance.getToken() + ? endpoint + + "?token=" + + Configuration.instance.getToken()! : roadmapURL; return WebPage("Suggest features", url); }, diff --git a/lib/ui/sharing/manage_links_widget.dart b/lib/ui/sharing/manage_links_widget.dart index 0b8c1ddbb..6eaf01e84 100644 --- a/lib/ui/sharing/manage_links_widget.dart +++ b/lib/ui/sharing/manage_links_widget.dart @@ -15,7 +15,6 @@ import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; import 'package:photos/ui/common/dialogs.dart'; import 'package:photos/ui/components/captioned_text_widget.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/components/divider_widget.dart'; import 'package:photos/ui/components/menu_item_widget.dart'; import 'package:photos/ui/components/menu_section_description_widget.dart'; diff --git a/lib/ui/sharing/share_collection_page.dart b/lib/ui/sharing/share_collection_page.dart index 139fe011d..90f74afaf 100644 --- a/lib/ui/sharing/share_collection_page.dart +++ b/lib/ui/sharing/share_collection_page.dart @@ -1,5 +1,3 @@ -// @dart=2.9 - import 'package:collection/collection.dart'; import 'package:fast_base58/fast_base58.dart'; import 'package:flutter/material.dart'; @@ -25,14 +23,14 @@ import 'package:photos/utils/toast_util.dart'; class ShareCollectionPage extends StatefulWidget { final Collection collection; - const ShareCollectionPage(this.collection, {Key key}) : super(key: key); + const ShareCollectionPage(this.collection, {Key? key}) : super(key: key); @override State createState() => _ShareCollectionPageState(); } class _ShareCollectionPageState extends State { - List _sharees; + late List _sharees; final Logger _logger = Logger("SharingDialogState"); final CollectionActions collectionActions = CollectionActions(CollectionsService.instance); @@ -132,7 +130,7 @@ class _ShareCollectionPageState extends State { CollectionsService.instance.getCollectionKey(widget.collection.id), ); final String url = - "${widget.collection.publicURLs.first.url}#$collectionKey"; + "${widget.collection.publicURLs!.first!.url}#$collectionKey"; children.addAll( [ MenuItemWidget( @@ -235,8 +233,8 @@ class _ShareCollectionPageState extends State { return Scaffold( appBar: AppBar( title: Text( - widget.collection.name, - style: Theme.of(context).textTheme.headline5.copyWith(fontSize: 16), + widget.collection.name ?? "Unnamed", + style: Theme.of(context).textTheme.headline5?.copyWith(fontSize: 16), ), elevation: 0, centerTitle: false, @@ -260,12 +258,12 @@ class _ShareCollectionPageState extends State { class EmailItemWidget extends StatelessWidget { final Collection collection; - final Function onTap; + final Function? onTap; const EmailItemWidget( this.collection, { this.onTap, - Key key, + Key? key, }) : super(key: key); @override @@ -291,7 +289,7 @@ class EmailItemWidget extends StatelessWidget { trailingIcon: Icons.chevron_right, onTap: () async { if (onTap != null) { - onTap(); + onTap!(); } }, isBottomBorderRadiusRemoved: true, @@ -317,7 +315,7 @@ class EmailItemWidget extends StatelessWidget { trailingIcon: Icons.chevron_right, onTap: () async { if (onTap != null) { - onTap(); + onTap!(); } }, isBottomBorderRadiusRemoved: true, diff --git a/lib/ui/tools/debug/app_storage_viewer.dart b/lib/ui/tools/debug/app_storage_viewer.dart index 5ae010b5d..6129fb707 100644 --- a/lib/ui/tools/debug/app_storage_viewer.dart +++ b/lib/ui/tools/debug/app_storage_viewer.dart @@ -158,6 +158,8 @@ class _AppStorageViewerState extends State { ), menuItemColor: getEnteColorScheme(context).fillFaint, + pressedColor: + getEnteColorScheme(context).fillFaintPressed, borderRadius: 8, onTap: () async { for (var pathItem in paths) { diff --git a/lib/ui/viewer/file/fading_app_bar.dart b/lib/ui/viewer/file/fading_app_bar.dart index d42a80fd5..b0dbe1d66 100644 --- a/lib/ui/viewer/file/fading_app_bar.dart +++ b/lib/ui/viewer/file/fading_app_bar.dart @@ -25,7 +25,6 @@ import 'package:photos/services/hidden_service.dart'; import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/services/local_sync_service.dart'; import 'package:photos/ui/common/progress_dialog.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/create_collection_page.dart'; import 'package:photos/ui/viewer/file/custom_app_bar.dart'; import 'package:photos/utils/delete_file_util.dart'; diff --git a/lib/ui/viewer/gallery/gallery_app_bar_widget.dart b/lib/ui/viewer/gallery/gallery_app_bar_widget.dart index 5b5078c3c..310fb156a 100644 --- a/lib/ui/viewer/gallery/gallery_app_bar_widget.dart +++ b/lib/ui/viewer/gallery/gallery_app_bar_widget.dart @@ -22,6 +22,7 @@ import 'package:photos/services/update_service.dart'; import 'package:photos/ui/common/dialogs.dart'; import 'package:photos/ui/common/rename_dialog.dart'; import 'package:photos/ui/components/dialog_widget.dart'; +import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/ui/sharing/album_participants_page.dart'; import 'package:photos/ui/sharing/share_collection_page.dart'; import 'package:photos/ui/tools/free_space_page.dart'; @@ -200,46 +201,31 @@ class _GalleryAppBarWidgetState extends State { } void _showSpaceFreedDialog(BackupStatus status) { - final AlertDialog alert = AlertDialog( - title: const Text("Success"), - content: Text( - "You have successfully freed up " + formatBytes(status.size) + "!", - ), - actions: [ - TextButton( - child: Text( - "Rate us", - style: TextStyle( - color: Theme.of(context).colorScheme.greenAlternative, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - // TODO: Replace with https://pub.dev/packages/in_app_review - final url = UpdateService.instance.getRateDetails().item2; - launchUrlString(url); - }, - ), - TextButton( - child: const Text( - "Ok", - ), - onPressed: () { - if (Platform.isIOS) { - showToast( - context, - "Also empty \"Recently Deleted\" from \"Settings\" -> \"Storage\" to claim the freed space", - ); - } - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], + final DialogWidget dialog = choiceDialog( + title: "Success", + body: "You have successfully freed up " + formatBytes(status.size) + "!", + firstButtonLabel: "Rate us", + firstButtonOnTap: () async { + // TODO: Replace with https://pub.dev/packages/in_app_review + final url = UpdateService.instance.getRateDetails().item2; + launchUrlString(url); + }, + firstButtonType: ButtonType.primary, + secondButtonLabel: "OK", + secondButtonOnTap: () async { + if (Platform.isIOS) { + showToast( + context, + "Also empty \"Recently Deleted\" from \"Settings\" -> \"Storage\" to claim the freed space", + ); + } + }, ); + showConfettiDialog( context: context, - builder: (BuildContext context) { - return alert; + dialogBuilder: (BuildContext context) { + return dialog; }, barrierColor: Colors.black87, confettiAlignment: Alignment.topCenter, diff --git a/lib/ui/viewer/gallery/gallery_overlay_widget.dart b/lib/ui/viewer/gallery/gallery_overlay_widget.dart index e5e4b5713..f899644f1 100644 --- a/lib/ui/viewer/gallery/gallery_overlay_widget.dart +++ b/lib/ui/viewer/gallery/gallery_overlay_widget.dart @@ -18,7 +18,6 @@ import 'package:photos/models/magic_metadata.dart'; import 'package:photos/models/selected_files.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/hidden_service.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/create_collection_page.dart'; import 'package:photos/utils/delete_file_util.dart'; import 'package:photos/utils/dialog_util.dart'; diff --git a/lib/ui/viewer/search/result/no_result_widget.dart b/lib/ui/viewer/search/result/no_result_widget.dart index bde983b35..0c26e28c6 100644 --- a/lib/ui/viewer/search/result/no_result_widget.dart +++ b/lib/ui/viewer/search/result/no_result_widget.dart @@ -1,10 +1,8 @@ -// @dart=2.9 - import 'package:flutter/material.dart'; import 'package:photos/ente_theme_data.dart'; class NoResultWidget extends StatelessWidget { - const NoResultWidget({Key key}) : super(key: key); + const NoResultWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/utils/delete_file_util.dart b/lib/utils/delete_file_util.dart index 839eaa450..66e2468cd 100644 --- a/lib/utils/delete_file_util.dart +++ b/lib/utils/delete_file_util.dart @@ -24,7 +24,6 @@ import 'package:photos/services/sync_service.dart'; import 'package:photos/services/trash_sync_service.dart'; import 'package:photos/ui/common/dialogs.dart'; import 'package:photos/ui/common/linear_progress_dialog.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/file_util.dart'; import 'package:photos/utils/toast_util.dart'; diff --git a/lib/utils/dialog_util.dart b/lib/utils/dialog_util.dart index 06ffdbec7..6ffef2962 100644 --- a/lib/utils/dialog_util.dart +++ b/lib/utils/dialog_util.dart @@ -1,11 +1,136 @@ -// @dart=2.9 - import 'dart:math'; import 'package:confetti/confetti.dart'; import 'package:flutter/material.dart'; +import 'package:photos/core/constants.dart'; import 'package:photos/ui/common/loading_widget.dart'; import 'package:photos/ui/common/progress_dialog.dart'; +import 'package:photos/ui/components/button_widget.dart'; +import 'package:photos/ui/components/dialog_widget.dart'; +import 'package:photos/ui/components/models/button_type.dart'; + +typedef DialogBuilder = DialogWidget Function(BuildContext context); + +///Will return null if dismissed by tapping outside +Future showErrorDialog( + BuildContext context, + String title, + String? body, { + bool isDismissable = true, +}) async { + return showDialogWidget( + context: context, + title: title, + body: body, + isDismissible: isDismissable, + buttons: const [ + ButtonWidget( + buttonType: ButtonType.secondary, + labelText: "OK", + isInAlert: true, + buttonAction: ButtonAction.first, + ), + ], + ); +} + +///Will return null if dismissed by tapping outside +Future showGenericErrorDialog({ + required BuildContext context, + bool isDismissible = true, +}) async { + return showDialogWidget( + context: context, + title: "Error", + icon: Icons.error_outline_outlined, + body: "It looks like something went wrong. Please try again.", + isDismissible: isDismissible, + buttons: const [ + ButtonWidget( + buttonType: ButtonType.secondary, + labelText: "OK", + isInAlert: true, + ), + ], + ); +} + +DialogWidget choiceDialog({ + required String title, + String? body, + required String firstButtonLabel, + String secondButtonLabel = "Cancel", + ButtonType firstButtonType = ButtonType.neutral, + ButtonType secondButtonType = ButtonType.secondary, + ButtonAction firstButtonAction = ButtonAction.first, + ButtonAction secondButtonAction = ButtonAction.cancel, + FutureVoidCallback? firstButtonOnTap, + FutureVoidCallback? secondButtonOnTap, + bool isCritical = false, + IconData? icon, +}) { + final buttons = [ + ButtonWidget( + buttonType: isCritical ? ButtonType.critical : firstButtonType, + labelText: firstButtonLabel, + isInAlert: true, + onTap: firstButtonOnTap, + buttonAction: firstButtonAction, + ), + ButtonWidget( + buttonType: secondButtonType, + labelText: secondButtonLabel, + isInAlert: true, + onTap: secondButtonOnTap, + buttonAction: secondButtonAction, + ), + ]; + + return DialogWidget(title: title, body: body, buttons: buttons, icon: icon); +} + +///Will return null if dismissed by tapping outside +Future showNewChoiceDialog({ + required BuildContext context, + required String title, + String? body, + required String firstButtonLabel, + String secondButtonLabel = "Cancel", + ButtonType firstButtonType = ButtonType.neutral, + ButtonType secondButtonType = ButtonType.secondary, + ButtonAction firstButtonAction = ButtonAction.first, + ButtonAction secondButtonAction = ButtonAction.cancel, + FutureVoidCallback? firstButtonOnTap, + FutureVoidCallback? secondButtonOnTap, + bool isCritical = false, + IconData? icon, + bool isDismissible = true, +}) async { + final buttons = [ + ButtonWidget( + buttonType: isCritical ? ButtonType.critical : firstButtonType, + labelText: firstButtonLabel, + isInAlert: true, + onTap: firstButtonOnTap, + buttonAction: firstButtonAction, + ), + ButtonWidget( + buttonType: secondButtonType, + labelText: secondButtonLabel, + isInAlert: true, + onTap: secondButtonOnTap, + buttonAction: secondButtonAction, + ), + ]; + return showDialogWidget( + context: context, + title: title, + body: body, + buttons: buttons, + icon: icon, + isDismissible: isDismissible, + ); +} ProgressDialog createProgressDialog( BuildContext context, @@ -30,56 +155,20 @@ ProgressDialog createProgressDialog( return dialog; } -Future showErrorDialog( - BuildContext context, - String title, - String content, -) { - final AlertDialog alert = AlertDialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - title: title.isEmpty - ? const SizedBox.shrink() - : Text( - title, - style: Theme.of(context).textTheme.headline6, - ), - content: Text(content), - actions: [ - TextButton( - child: Text( - "Ok", - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - ], - ); - - return showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - barrierColor: Colors.black12, - ); -} - -Future showConfettiDialog({ - @required BuildContext context, - WidgetBuilder builder, +Future showConfettiDialog({ + required BuildContext context, + required DialogBuilder dialogBuilder, bool barrierDismissible = true, - Color barrierColor, + Color? barrierColor, bool useSafeArea = true, bool useRootNavigator = true, - RouteSettings routeSettings, + RouteSettings? routeSettings, Alignment confettiAlignment = Alignment.center, }) { + final widthOfScreen = MediaQuery.of(context).size.width; + final isMobileSmall = widthOfScreen <= mobileSmallThreshold; final pageBuilder = Builder( - builder: builder, + builder: dialogBuilder, ); final ConfettiController confettiController = ConfettiController(duration: const Duration(seconds: 1)); @@ -87,22 +176,25 @@ Future showConfettiDialog({ return showDialog( context: context, builder: (BuildContext buildContext) { - return Stack( - children: [ - pageBuilder, - Align( - alignment: confettiAlignment, - child: ConfettiWidget( - confettiController: confettiController, - blastDirection: pi / 2, - emissionFrequency: 0, - numberOfParticles: 100, - // a lot of particles at once - gravity: 1, - blastDirectionality: BlastDirectionality.explosive, + return Padding( + padding: EdgeInsets.symmetric(horizontal: isMobileSmall ? 8 : 0), + child: Stack( + children: [ + Align(alignment: Alignment.center, child: pageBuilder), + Align( + alignment: confettiAlignment, + child: ConfettiWidget( + confettiController: confettiController, + blastDirection: pi / 2, + emissionFrequency: 0, + numberOfParticles: 100, + // a lot of particles at once + gravity: 1, + blastDirectionality: BlastDirectionality.explosive, + ), ), - ), - ], + ], + ), ); }, barrierDismissible: barrierDismissible, diff --git a/lib/utils/email_util.dart b/lib/utils/email_util.dart index c5de45ffc..a19b3264a 100644 --- a/lib/utils/email_util.dart +++ b/lib/utils/email_util.dart @@ -16,7 +16,6 @@ import 'package:photos/core/configuration.dart'; import 'package:photos/core/error-reporting/super_logging.dart'; import 'package:photos/ente_theme_data.dart'; import 'package:photos/ui/common/dialogs.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/ui/tools/debug/log_file_viewer.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/toast_util.dart'; diff --git a/lib/utils/share_util.dart b/lib/utils/share_util.dart index 3a685caa2..043d0e7df 100644 --- a/lib/utils/share_util.dart +++ b/lib/utils/share_util.dart @@ -10,7 +10,6 @@ import 'package:photos/core/configuration.dart'; import 'package:photos/core/constants.dart'; import 'package:photos/models/file.dart'; import 'package:photos/models/file_type.dart'; -import 'package:photos/ui/components/dialog_widget.dart'; import 'package:photos/utils/date_time_util.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/exif_util.dart';