feat(mobile): reduce UI rebuilds (#3129)

This commit is contained in:
Fynn Petersen-Frey 2023-07-08 15:46:22 +02:00 committed by GitHub
parent 50c7b35291
commit fe2330ebf6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -50,86 +50,49 @@ class ImmichAssetGrid extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
var settings = ref.watch(appSettingsServiceProvider); final settings = ref.watch(appSettingsServiceProvider);
// Needs to suppress hero animations when navigating to this widget
final enableHeroAnimations = useState(false);
final transitionDuration = ModalRoute.of(context)?.transitionDuration;
final perRow = useState( final perRow = useState(
assetsPerRow ?? settings.getSetting(AppSettingsEnum.tilesPerRow)!, assetsPerRow ?? settings.getSetting(AppSettingsEnum.tilesPerRow)!,
); );
final scaleFactor = useState(7.0 - perRow.value); final scaleFactor = useState(7.0 - perRow.value);
final baseScaleFactor = useState(7.0 - perRow.value); final baseScaleFactor = useState(7.0 - perRow.value);
useEffect(
() {
// Wait for transition to complete, then re-enable
if (transitionDuration == null) {
// No route transition found, maybe we opened this up first
enableHeroAnimations.value = true;
} else {
// Unfortunately, using the transition animation itself didn't
// seem to work reliably. So instead, wait until the duration of the
// animation has elapsed to re-enable the hero animations
Future.delayed(transitionDuration).then((_) {
enableHeroAnimations.value = true;
});
}
return null;
},
[],
);
Future<bool> onWillPop() async {
enableHeroAnimations.value = false;
return true;
}
Widget buildAssetGridView(RenderList renderList) { Widget buildAssetGridView(RenderList renderList) {
return WillPopScope( return RawGestureDetector(
onWillPop: onWillPop, gestures: {
child: HeroMode( CustomScaleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
enabled: enableHeroAnimations.value, CustomScaleGestureRecognizer>(
child: RawGestureDetector( () => CustomScaleGestureRecognizer(),
gestures: { (CustomScaleGestureRecognizer scale) {
CustomScaleGestureRecognizer: scale.onStart = (details) {
GestureRecognizerFactoryWithHandlers< baseScaleFactor.value = scaleFactor.value;
CustomScaleGestureRecognizer>( };
() => CustomScaleGestureRecognizer(),
(CustomScaleGestureRecognizer scale) {
scale.onStart = (details) {
baseScaleFactor.value = scaleFactor.value;
};
scale.onUpdate = (details) { scale.onUpdate = (details) {
scaleFactor.value = scaleFactor.value =
max(min(5.0, baseScaleFactor.value * details.scale), 1.0); max(min(5.0, baseScaleFactor.value * details.scale), 1.0);
if (7 - scaleFactor.value.toInt() != perRow.value) { if (7 - scaleFactor.value.toInt() != perRow.value) {
perRow.value = 7 - scaleFactor.value.toInt(); perRow.value = 7 - scaleFactor.value.toInt();
} }
}; };
scale.onEnd = (details) {}; })
}) },
}, child: ImmichAssetGridView(
child: ImmichAssetGridView( onRefresh: onRefresh,
onRefresh: onRefresh, assetsPerRow: perRow.value,
assetsPerRow: perRow.value, listener: listener,
listener: listener, showStorageIndicator: showStorageIndicator ??
showStorageIndicator: showStorageIndicator ?? settings.getSetting(AppSettingsEnum.storageIndicator),
settings.getSetting(AppSettingsEnum.storageIndicator), renderList: renderList,
renderList: renderList, margin: margin,
margin: margin, selectionActive: selectionActive,
selectionActive: selectionActive, preselectedAssets: preselectedAssets,
preselectedAssets: preselectedAssets, canDeselect: canDeselect,
canDeselect: canDeselect, dynamicLayout: dynamicLayout ??
dynamicLayout: dynamicLayout ?? settings.getSetting(AppSettingsEnum.dynamicLayout),
settings.getSetting(AppSettingsEnum.dynamicLayout), showMultiSelectIndicator: showMultiSelectIndicator,
showMultiSelectIndicator: showMultiSelectIndicator, visibleItemsListener: visibleItemsListener,
visibleItemsListener: visibleItemsListener, topWidget: topWidget,
topWidget: topWidget,
),
),
), ),
); );
} }