Perf improvements (#1097)
This commit is contained in:
commit
47a7ac3bb2
15 changed files with 277 additions and 49 deletions
122
integration_test/app_test.dart
Normal file
122
integration_test/app_test.dart
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_test/flutter_test.dart";
|
||||||
|
import "package:integration_test/integration_test.dart";
|
||||||
|
import "package:photos/main.dart" as app;
|
||||||
|
import "package:scrollable_positioned_list/scrollable_positioned_list.dart";
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group("App test", () {
|
||||||
|
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||||
|
testWidgets("Demo test", (tester) async {
|
||||||
|
app.main();
|
||||||
|
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 5));
|
||||||
|
|
||||||
|
await dismissUpdateAppDialog(tester);
|
||||||
|
|
||||||
|
//Automatically clicks the sign in button on the landing page
|
||||||
|
final signInButton = find.byKey(const ValueKey("signInButton"));
|
||||||
|
await tester.tap(signInButton);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
//Need to enter email address manually and clicks the login button automatically
|
||||||
|
final emailInputField = find.byKey(const ValueKey("emailInputField"));
|
||||||
|
final logInButton = find.byKey(const ValueKey("logInButton"));
|
||||||
|
await tester.tap(emailInputField);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 20));
|
||||||
|
await findAndTapFAB(tester, logInButton);
|
||||||
|
|
||||||
|
//Need to enter OTT manually and clicks the verify button automatically
|
||||||
|
final ottVerificationInputField =
|
||||||
|
find.byKey(const ValueKey("ottVerificationInputField"));
|
||||||
|
final verifyOttButton = find.byKey(const ValueKey("verifyOttButton"));
|
||||||
|
await tester.tap(ottVerificationInputField);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 6));
|
||||||
|
await findAndTapFAB(tester, verifyOttButton);
|
||||||
|
|
||||||
|
//Need to enter password manually and clicks the verify button automatically
|
||||||
|
final passwordInputField =
|
||||||
|
find.byKey(const ValueKey("passwordInputField"));
|
||||||
|
final verifyPasswordButton =
|
||||||
|
find.byKey(const ValueKey("verifyPasswordButton"));
|
||||||
|
await tester.tap(passwordInputField);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 10));
|
||||||
|
await findAndTapFAB(tester, verifyPasswordButton);
|
||||||
|
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||||
|
await dismissUpdateAppDialog(tester);
|
||||||
|
|
||||||
|
//Grant permission to access photos. Must manually click the system dialog.
|
||||||
|
final grantPermissionButton =
|
||||||
|
find.byKey(const ValueKey("grantPermissionButton"));
|
||||||
|
await tester.tap(grantPermissionButton);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 1));
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||||
|
|
||||||
|
//Automatically skips backup
|
||||||
|
final skipBackupButton = find.byKey(const ValueKey("skipBackupButton"));
|
||||||
|
await tester.tap(skipBackupButton);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
await binding.traceAction(
|
||||||
|
() async {
|
||||||
|
//scroll gallery
|
||||||
|
final scrollablePositionedList =
|
||||||
|
find.byType(ScrollablePositionedList);
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, -5000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, 5000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, -7000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, 7000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, -9000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.fling(
|
||||||
|
scrollablePositionedList,
|
||||||
|
const Offset(0, 9000),
|
||||||
|
4500,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
},
|
||||||
|
reportKey: 'scrolling_summary',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> findAndTapFAB(WidgetTester tester, Finder finder) async {
|
||||||
|
final RenderBox box = tester.renderObject(finder);
|
||||||
|
final Offset desiredOffset = Offset(box.size.width - 10, box.size.height / 2);
|
||||||
|
// Calculate the global position of the desired offset within the widget.
|
||||||
|
final Offset globalPosition = box.localToGlobal(desiredOffset);
|
||||||
|
await tester.tapAt(globalPosition);
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> dismissUpdateAppDialog(WidgetTester tester) async {
|
||||||
|
await tester.tapAt(const Offset(0, 0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
}
|
|
@ -99,6 +99,8 @@ PODS:
|
||||||
- in_app_purchase_storekit (0.0.1):
|
- in_app_purchase_storekit (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- integration_test (0.0.1):
|
||||||
|
- Flutter
|
||||||
- libwebp (1.2.4):
|
- libwebp (1.2.4):
|
||||||
- libwebp/demux (= 1.2.4)
|
- libwebp/demux (= 1.2.4)
|
||||||
- libwebp/mux (= 1.2.4)
|
- libwebp/mux (= 1.2.4)
|
||||||
|
@ -195,6 +197,7 @@ DEPENDENCIES:
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
- image_editor_common (from `.symlinks/plugins/image_editor_common/ios`)
|
- image_editor_common (from `.symlinks/plugins/image_editor_common/ios`)
|
||||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/ios`)
|
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/ios`)
|
||||||
|
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||||
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
|
||||||
- media_extension (from `.symlinks/plugins/media_extension/ios`)
|
- media_extension (from `.symlinks/plugins/media_extension/ios`)
|
||||||
- motionphoto (from `.symlinks/plugins/motionphoto/ios`)
|
- motionphoto (from `.symlinks/plugins/motionphoto/ios`)
|
||||||
|
@ -276,6 +279,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/image_editor_common/ios"
|
:path: ".symlinks/plugins/image_editor_common/ios"
|
||||||
in_app_purchase_storekit:
|
in_app_purchase_storekit:
|
||||||
:path: ".symlinks/plugins/in_app_purchase_storekit/ios"
|
:path: ".symlinks/plugins/in_app_purchase_storekit/ios"
|
||||||
|
integration_test:
|
||||||
|
:path: ".symlinks/plugins/integration_test/ios"
|
||||||
local_auth_ios:
|
local_auth_ios:
|
||||||
:path: ".symlinks/plugins/local_auth_ios/ios"
|
:path: ".symlinks/plugins/local_auth_ios/ios"
|
||||||
media_extension:
|
media_extension:
|
||||||
|
@ -345,6 +350,7 @@ SPEC CHECKSUMS:
|
||||||
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
|
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
|
||||||
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
image_editor_common: d6f6644ae4a6de80481e89fe6d0a8c49e30b4b43
|
||||||
in_app_purchase_storekit: 6b297e2b5eab9fa3251a492d57301722e4132a71
|
in_app_purchase_storekit: 6b297e2b5eab9fa3251a492d57301722e4132a71
|
||||||
|
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
|
||||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
||||||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||||
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
|
||||||
|
|
|
@ -289,6 +289,7 @@
|
||||||
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
|
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/image_editor_common/image_editor_common.framework",
|
"${BUILT_PRODUCTS_DIR}/image_editor_common/image_editor_common.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/in_app_purchase_storekit/in_app_purchase_storekit.framework",
|
"${BUILT_PRODUCTS_DIR}/in_app_purchase_storekit/in_app_purchase_storekit.framework",
|
||||||
|
"${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
|
"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
|
"${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
|
||||||
"${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework",
|
"${BUILT_PRODUCTS_DIR}/media_extension/media_extension.framework",
|
||||||
|
@ -345,6 +346,7 @@
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_editor_common.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_editor_common.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/in_app_purchase_storekit.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/in_app_purchase_storekit.framework",
|
||||||
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
|
||||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework",
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/media_extension.framework",
|
||||||
|
|
|
@ -53,6 +53,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
),
|
),
|
||||||
body: _getBody(),
|
body: _getBody(),
|
||||||
floatingActionButton: DynamicFAB(
|
floatingActionButton: DynamicFAB(
|
||||||
|
key: const ValueKey("logInButton"),
|
||||||
isKeypadOpen: isKeypadOpen,
|
isKeypadOpen: isKeypadOpen,
|
||||||
isFormValid: _emailIsValid,
|
isFormValid: _emailIsValid,
|
||||||
buttonText: S.of(context).logInLabel,
|
buttonText: S.of(context).logInLabel,
|
||||||
|
@ -87,6 +88,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
|
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
key: const ValueKey("emailInputField"),
|
||||||
autofillHints: const [AutofillHints.email],
|
autofillHints: const [AutofillHints.email],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
fillColor: _emailInputFieldColor,
|
fillColor: _emailInputFieldColor,
|
||||||
|
@ -186,9 +188,9 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
const Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Container(),
|
child: SizedBox.shrink(),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -64,6 +64,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
||||||
),
|
),
|
||||||
body: _getBody(),
|
body: _getBody(),
|
||||||
floatingActionButton: DynamicFAB(
|
floatingActionButton: DynamicFAB(
|
||||||
|
key: const ValueKey("verifyOttButton"),
|
||||||
isKeypadOpen: isKeypadOpen,
|
isKeypadOpen: isKeypadOpen,
|
||||||
isFormValid: _verificationCodeController.text.isNotEmpty,
|
isFormValid: _verificationCodeController.text.isNotEmpty,
|
||||||
buttonText: S.of(context).verify,
|
buttonText: S.of(context).verify,
|
||||||
|
@ -146,6 +147,7 @@ class _OTTVerificationPageState extends State<OTTVerificationPage> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
|
padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
key: const ValueKey("ottVerificationInputField"),
|
||||||
style: Theme.of(context).textTheme.subtitle1,
|
style: Theme.of(context).textTheme.subtitle1,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
filled: true,
|
filled: true,
|
||||||
|
|
|
@ -66,6 +66,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
||||||
),
|
),
|
||||||
body: _getBody(),
|
body: _getBody(),
|
||||||
floatingActionButton: DynamicFAB(
|
floatingActionButton: DynamicFAB(
|
||||||
|
key: const ValueKey("verifyPasswordButton"),
|
||||||
isKeypadOpen: isKeypadOpen,
|
isKeypadOpen: isKeypadOpen,
|
||||||
isFormValid: _passwordController.text.isNotEmpty,
|
isFormValid: _passwordController.text.isNotEmpty,
|
||||||
buttonText: S.of(context).verifyPassword,
|
buttonText: S.of(context).verifyPassword,
|
||||||
|
@ -169,6 +170,7 @@ class _PasswordReentryPageState extends State<PasswordReentryPage> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
|
padding: const EdgeInsets.fromLTRB(20, 24, 20, 0),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
key: const ValueKey("passwordInputField"),
|
||||||
autofillHints: const [AutofillHints.password],
|
autofillHints: const [AutofillHints.password],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: S.of(context).enterYourPassword,
|
hintText: S.of(context).enterYourPassword,
|
||||||
|
|
|
@ -185,6 +185,7 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
|
||||||
bottom: Platform.isIOS ? 48 : 32,
|
bottom: Platform.isIOS ? 48 : 32,
|
||||||
),
|
),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
|
key: const ValueKey("skipBackupButton"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
|
|
@ -92,6 +92,7 @@ class GrantPermissionsWidget extends StatelessWidget {
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
),
|
),
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
|
key: const ValueKey("grantPermissionButton"),
|
||||||
child: Text(S.of(context).grantPermission),
|
child: Text(S.of(context).grantPermission),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final state = await PhotoManager.requestPermissionExtend();
|
final state = await PhotoManager.requestPermissionExtend();
|
||||||
|
|
|
@ -116,6 +116,7 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
|
||||||
child: Hero(
|
child: Hero(
|
||||||
tag: "log_in",
|
tag: "log_in",
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
|
key: const ValueKey("signInButton"),
|
||||||
style:
|
style:
|
||||||
Theme.of(context).colorScheme.optionalActionButtonStyle,
|
Theme.of(context).colorScheme.optionalActionButtonStyle,
|
||||||
onPressed: _navigateToSignInPage,
|
onPressed: _navigateToSignInPage,
|
||||||
|
|
|
@ -112,6 +112,7 @@ class _AppUpdateDialogState extends State<AppUpdateDialog> {
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async => !shouldForceUpdate,
|
onWillPop: () async => !shouldForceUpdate,
|
||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
|
key: const ValueKey("updateAppDialog"),
|
||||||
title: Column(
|
title: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -58,10 +58,13 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
bool _isLoadingRemoteThumbnail = false;
|
bool _isLoadingRemoteThumbnail = false;
|
||||||
bool _errorLoadingRemoteThumbnail = false;
|
bool _errorLoadingRemoteThumbnail = false;
|
||||||
ImageProvider? _imageProvider;
|
ImageProvider? _imageProvider;
|
||||||
|
int? optimizedImageHeight;
|
||||||
|
int? optimizedImageWidth;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
assignOptimizedImageDimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -83,6 +86,19 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Assigned dimension will be the size of a grid item. The size will be
|
||||||
|
///assigned to the side which is smaller in dimension.
|
||||||
|
void assignOptimizedImageDimensions() {
|
||||||
|
if (widget.file!.width == 0 || widget.file!.height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (widget.file!.width < widget.file!.height) {
|
||||||
|
optimizedImageWidth = widget.thumbnailSize;
|
||||||
|
} else {
|
||||||
|
optimizedImageHeight = widget.thumbnailSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.file!.isRemoteFile) {
|
if (widget.file!.isRemoteFile) {
|
||||||
|
@ -93,7 +109,13 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
Widget? image;
|
Widget? image;
|
||||||
if (_imageProvider != null) {
|
if (_imageProvider != null) {
|
||||||
image = Image(
|
image = Image(
|
||||||
image: _imageProvider!,
|
image: optimizedImageHeight != null || optimizedImageWidth != null
|
||||||
|
? ResizeImage(
|
||||||
|
_imageProvider!,
|
||||||
|
width: optimizedImageWidth,
|
||||||
|
height: optimizedImageHeight,
|
||||||
|
)
|
||||||
|
: _imageProvider!,
|
||||||
fit: widget.fit,
|
fit: widget.fit,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -148,11 +170,7 @@ class _ThumbnailWidgetState extends State<ThumbnailWidget> {
|
||||||
}
|
}
|
||||||
final List<Widget> viewChildren = [
|
final List<Widget> viewChildren = [
|
||||||
const ThumbnailPlaceHolder(),
|
const ThumbnailPlaceHolder(),
|
||||||
AnimatedOpacity(
|
content ?? const SizedBox(),
|
||||||
opacity: content == null ? 0 : 1.0,
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
child: content,
|
|
||||||
)
|
|
||||||
];
|
];
|
||||||
if (widget.shouldShowSyncStatus && widget.file!.uploadedFileID == null) {
|
if (widget.shouldShowSyncStatus && widget.file!.uploadedFileID == null) {
|
||||||
viewChildren.add(const UnSyncedIcon());
|
viewChildren.add(const UnSyncedIcon());
|
||||||
|
|
|
@ -60,46 +60,58 @@ class GalleryFileWidget extends StatelessWidget {
|
||||||
? _onLongPressWithSelectionLimit(context, file)
|
? _onLongPressWithSelectionLimit(context, file)
|
||||||
: _onLongPressNoSelectionLimit(context, file);
|
: _onLongPressNoSelectionLimit(context, file);
|
||||||
},
|
},
|
||||||
child: ClipRRect(
|
child: Stack(
|
||||||
borderRadius: BorderRadius.circular(1),
|
children: [
|
||||||
child: Stack(
|
ClipRRect(
|
||||||
children: [
|
borderRadius: BorderRadius.circular(1),
|
||||||
Hero(
|
child: Hero(
|
||||||
tag: tag + file.tag,
|
tag: tag + file.tag,
|
||||||
child: ColorFiltered(
|
child: isFileSelected
|
||||||
colorFilter: ColorFilter.mode(
|
? ColorFiltered(
|
||||||
Colors.black.withOpacity(
|
colorFilter: ColorFilter.mode(
|
||||||
isFileSelected ? 0.4 : 0,
|
Colors.black.withOpacity(
|
||||||
),
|
0.4,
|
||||||
BlendMode.darken,
|
),
|
||||||
),
|
BlendMode.darken,
|
||||||
child: ThumbnailWidget(
|
),
|
||||||
file,
|
child: ThumbnailWidget(
|
||||||
diskLoadDeferDuration: thumbnailDiskLoadDeferDuration,
|
file,
|
||||||
serverLoadDeferDuration: thumbnailServerLoadDeferDuration,
|
diskLoadDeferDuration: thumbnailDiskLoadDeferDuration,
|
||||||
shouldShowLivePhotoOverlay: true,
|
serverLoadDeferDuration:
|
||||||
key: Key(tag + file.tag),
|
thumbnailServerLoadDeferDuration,
|
||||||
thumbnailSize: photoGridSize < photoGridSizeDefault
|
shouldShowLivePhotoOverlay: true,
|
||||||
? thumbnailLargeSize
|
key: Key(tag + file.tag),
|
||||||
: thumbnailSmallSize,
|
thumbnailSize: photoGridSize < photoGridSizeDefault
|
||||||
shouldShowOwnerAvatar: !isFileSelected,
|
? thumbnailLargeSize
|
||||||
),
|
: thumbnailSmallSize,
|
||||||
),
|
shouldShowOwnerAvatar: !isFileSelected,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ThumbnailWidget(
|
||||||
|
file,
|
||||||
|
diskLoadDeferDuration: thumbnailDiskLoadDeferDuration,
|
||||||
|
serverLoadDeferDuration: thumbnailServerLoadDeferDuration,
|
||||||
|
shouldShowLivePhotoOverlay: true,
|
||||||
|
key: Key(tag + file.tag),
|
||||||
|
thumbnailSize: photoGridSize < photoGridSizeDefault
|
||||||
|
? thumbnailLargeSize
|
||||||
|
: thumbnailSmallSize,
|
||||||
|
shouldShowOwnerAvatar: !isFileSelected,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Visibility(
|
),
|
||||||
visible: isFileSelected,
|
isFileSelected
|
||||||
child: Positioned(
|
? Positioned(
|
||||||
right: 4,
|
right: 4,
|
||||||
top: 4,
|
top: 4,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.check_circle_rounded,
|
Icons.check_circle_rounded,
|
||||||
size: 20,
|
size: 20,
|
||||||
color: selectionColor, //same for both themes
|
color: selectionColor, //same for both themes
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
)
|
: const SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
35
pubspec.lock
35
pubspec.lock
|
@ -53,10 +53,10 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
|
sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.6"
|
version: "3.3.2"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -614,6 +614,11 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
|
flutter_driver:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
flutter_easyloading:
|
flutter_easyloading:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -877,6 +882,11 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.0"
|
version: "3.2.0"
|
||||||
|
fuchsia_remote_debug_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1013,6 +1023,11 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.5+2"
|
version: "0.3.5+2"
|
||||||
|
integration_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -1804,6 +1819,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
version: "7.0.0"
|
||||||
|
sync_http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sync_http
|
||||||
|
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.1"
|
||||||
syncfusion_flutter_core:
|
syncfusion_flutter_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -2130,6 +2153,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
|
webdriver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webdriver
|
||||||
|
sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
webkit_inspection_protocol:
|
webkit_inspection_protocol:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -140,12 +140,16 @@ dependency_overrides:
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.3.3
|
build_runner: ^2.3.3
|
||||||
|
flutter_driver:
|
||||||
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
freezed: ^2.3.2
|
freezed: ^2.3.2
|
||||||
|
integration_test:
|
||||||
|
sdk: flutter
|
||||||
json_serializable: ^6.6.1
|
json_serializable: ^6.6.1
|
||||||
test:
|
test: ^1.22.0
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
android: "launcher_icon"
|
android: "launcher_icon"
|
||||||
|
|
23
test_driver/perf_driver.dart
Normal file
23
test_driver/perf_driver.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import 'package:flutter_driver/flutter_driver.dart' as driver;
|
||||||
|
import 'package:integration_test/integration_test_driver.dart';
|
||||||
|
|
||||||
|
Future<void> main() {
|
||||||
|
return integrationDriver(
|
||||||
|
responseDataCallback: (data) async {
|
||||||
|
if (data != null) {
|
||||||
|
final timeline = driver.Timeline.fromJson(
|
||||||
|
data['scrolling_summary'] as Map<String, dynamic>,
|
||||||
|
);
|
||||||
|
|
||||||
|
final summary = driver.TimelineSummary.summarize(timeline);
|
||||||
|
|
||||||
|
await summary.writeTimelineToFile(
|
||||||
|
'scrolling_summary',
|
||||||
|
pretty: true,
|
||||||
|
includeSummary: true,
|
||||||
|
//Specify destination directory for the timeline files.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue