Merge branch 'main' into keychain_migration

This commit is contained in:
Neeraj Gupta 2022-12-31 10:25:21 +05:30
commit 18f4731eb3
No known key found for this signature in database
GPG key ID: 3C5A1684DC1729E1
55 changed files with 335 additions and 465 deletions

View file

@ -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

View file

@ -1,4 +1,3 @@
// @dart=2.9
import 'package:photos/models/file.dart';
class GalleryItemsFilter {

View file

@ -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" ||

View file

@ -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<BillingPlans> _future;
Future<BillingPlans>? _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<Response<dynamic>> _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;

View file

@ -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';

View file

@ -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';

View file

@ -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<ChangeEmailDialog> createState() => _ChangeEmailDialogState();
}
class _ChangeEmailDialogState extends State<ChangeEmailDialog> {
String _email;
String? _email;
@override
Widget build(BuildContext context) {

View file

@ -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 {

View file

@ -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';

View file

@ -65,6 +65,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
return Scaffold(
appBar: widget.showProgressBar
? AppBar(
automaticallyImplyLeading: false,
elevation: 0,
title: Hero(
tag: "recovery_key",
@ -97,6 +98,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.showAppBar
? const SizedBox.shrink()

View file

@ -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<SessionsPage> createState() => _SessionsPageState();
}
class _SessionsPageState extends State<SessionsPage> {
Sessions _sessions;
Sessions? _sessions;
final Logger _logger = Logger("SessionsPageState");
@override
@ -45,7 +43,7 @@ class _SessionsPageState extends State<SessionsPage> {
}
final List<Widget> 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<SessionsPage> {
.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) {

View file

@ -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!;
}
}
},

View file

@ -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

View file

@ -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<TwoFactorSetupPage>
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<TwoFactorSetupPage>
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!;
}
}
},

View file

@ -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';

View file

@ -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

View file

@ -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';

View file

@ -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';

View file

@ -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,

View file

@ -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 {

View file

@ -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(),

View file

@ -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<TrashButtonWidget> {
StreamSubscription<TrashUpdatedEvent> _trashUpdatedEventSubscription;
late StreamSubscription<TrashUpdatedEvent> _trashUpdatedEventSubscription;
@override
void initState() {
@ -37,7 +35,7 @@ class _TrashButtonWidgetState extends State<TrashButtonWidget> {
@override
void dispose() {
_trashUpdatedEventSubscription?.cancel();
_trashUpdatedEventSubscription.cancel();
super.dispose();
}
@ -52,7 +50,7 @@ class _TrashButtonWidgetState extends State<TrashButtonWidget> {
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<TrashButtonWidget> {
FutureBuilder<int>(
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,

View file

@ -14,37 +14,13 @@ enum ActionSheetType {
iconOnly,
}
Future<ButtonAction?> showCommonActionSheet({
required BuildContext context,
required List<ButtonWidget> 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<ButtonAction?> showActionSheet({
required BuildContext context,
required List<ButtonWidget> buttons,
required ActionSheetType actionSheetType,
bool enableDrag = true,
bool isDismissible = true,
bool isCheckIconGreen = false,
String? title,
String? body,
@ -54,6 +30,8 @@ Future<ButtonAction?> showActionSheet({
barrierColor: backdropFaintDark,
useRootNavigator: true,
context: context,
isDismissible: isDismissible,
enableDrag: enableDrag,
builder: (_) {
return ActionSheetWidget(
title: title,
@ -63,8 +41,6 @@ Future<ButtonAction?> showActionSheet({
isCheckIconGreen: isCheckIconGreen,
);
},
isDismissible: false,
enableDrag: false,
);
}

View file

@ -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<ButtonAction?> 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<ButtonAction?> 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<ButtonAction?> showDialogWidget({
required BuildContext context,
required String title,
String? body,
required List<ButtonWidget> buttons,
IconData? icon,
bool isDismissible = true,
}) {
return showDialog(
barrierDismissible: false,
barrierDismissible: isDismissible,
barrierColor: backdropFaintDark,
context: context,
builder: (context) {
@ -89,7 +32,6 @@ Future<ButtonAction?> showDialogWidget({
title: title,
body: body,
buttons: buttons,
isMobileSmall: isMobileSmall,
icon: icon,
),
),
@ -103,12 +45,10 @@ class DialogWidget extends StatelessWidget {
final String? body;
final List<ButtonWidget> 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),

View file

@ -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';

View file

@ -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,
),

View file

@ -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) {

View file

@ -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';

View file

@ -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),
),
),

View file

@ -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 {

View file

@ -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<TextStyle>(
(Set<MaterialState> states) {
return Theme.of(context).textTheme.subtitle1;
return Theme.of(context).textTheme.subtitle1!;
},
),
),

View file

@ -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';

View file

@ -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;
}

View file

@ -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';

View file

@ -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

View file

@ -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) {

View file

@ -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<AppVersionWidget> {
static const kTapThresholdForInspector = 5;
static const kConsecutiveTapTimeWindowInMilliseconds = 2000;
int _lastTap;
int? _lastTap;
int _consecutiveTaps = 0;
@override
@ -35,14 +33,14 @@ class _AppVersionWidgetState extends State<AppVersionWidget> {
}
_lastTap = now;
},
child: FutureBuilder(
child: FutureBuilder<String>(
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,
),
);

View file

@ -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<BackupSectionWidget> {
}
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<BackupSectionWidget> {
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,

View file

@ -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",

View file

@ -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) {

View file

@ -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<SecuritySectionWidget> createState() => _SecuritySectionWidgetState();
@ -29,7 +27,8 @@ class SecuritySectionWidget extends StatefulWidget {
class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
final _config = Configuration.instance;
StreamSubscription<TwoFactorStatusChangeEvent> _twoFactorStatusChangeEvent;
late StreamSubscription<TwoFactorStatusChangeEvent>
_twoFactorStatusChangeEvent;
@override
void initState() {

View file

@ -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)),
],
);
}
}

View file

@ -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

View file

@ -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);
},

View file

@ -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';

View file

@ -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<ShareCollectionPage> createState() => _ShareCollectionPageState();
}
class _ShareCollectionPageState extends State<ShareCollectionPage> {
List<User> _sharees;
late List<User?> _sharees;
final Logger _logger = Logger("SharingDialogState");
final CollectionActions collectionActions =
CollectionActions(CollectionsService.instance);
@ -132,7 +130,7 @@ class _ShareCollectionPageState extends State<ShareCollectionPage> {
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<ShareCollectionPage> {
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<ShareCollectionPage> {
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,

View file

@ -158,6 +158,8 @@ class _AppStorageViewerState extends State<AppStorageViewer> {
),
menuItemColor:
getEnteColorScheme(context).fillFaint,
pressedColor:
getEnteColorScheme(context).fillFaintPressed,
borderRadius: 8,
onTap: () async {
for (var pathItem in paths) {

View file

@ -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';

View file

@ -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<GalleryAppBarWidget> {
}
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,

View file

@ -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';

View file

@ -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) {

View file

@ -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';

View file

@ -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<ButtonAction?> 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<ButtonAction?> 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<ButtonAction?> 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<dynamic> 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<T> showConfettiDialog<T>({
@required BuildContext context,
WidgetBuilder builder,
Future<ButtonAction?> showConfettiDialog<T>({
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<T> showConfettiDialog<T>({
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,

View file

@ -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';

View file

@ -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';