forked from Cutlery/immich
		
	feat(mobile): long-press delete button to permanently delete asset (#6240)
* feat(mobile): delete assets from device only * mobile: add backed up only toggle for delete device only * remove toggle inside alert and show different content * mobile: change content color for local only * mobile: delete local only button to dialog * style: display bottom action in two lines * feat: separate delete buttons * fix: incorrect error message for ownedRemoteSelection * feat(mobile): long-press delete to permanently delete asset * chore: add todo to handle long press to delete in gallery_viewer * chore: rebase on deletion branch * feat(mobile): long-press delete to permanently delete asset * fix(mobile): update minChildSize of control bottom app bar --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
		
							parent
							
								
									04c783f2f0
								
							
						
					
					
						commit
						f62678f58f
					
				@ -633,6 +633,7 @@ class GalleryViewerPage extends HookConsumerWidget {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Migrate to a custom bottom bar and handle long press to delete
 | 
				
			||||||
    Widget buildBottomBar() {
 | 
					    Widget buildBottomBar() {
 | 
				
			||||||
      // !!!! itemsList and actionlist should always be in sync
 | 
					      // !!!! itemsList and actionlist should always be in sync
 | 
				
			||||||
      final itemsList = [
 | 
					      final itemsList = [
 | 
				
			||||||
 | 
				
			|||||||
@ -63,6 +63,22 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
        ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
 | 
					        ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
 | 
				
			||||||
    final albums = ref.watch(albumProvider).where((a) => a.isRemote).toList();
 | 
					    final albums = ref.watch(albumProvider).where((a) => a.isRemote).toList();
 | 
				
			||||||
    final sharedAlbums = ref.watch(sharedAlbumProvider);
 | 
					    final sharedAlbums = ref.watch(sharedAlbumProvider);
 | 
				
			||||||
 | 
					    const bottomPadding = 0.20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void showForceDeleteDialog(
 | 
				
			||||||
 | 
					      Function(bool) deleteCb, {
 | 
				
			||||||
 | 
					      String? alertMsg,
 | 
				
			||||||
 | 
					    }) {
 | 
				
			||||||
 | 
					      showDialog(
 | 
				
			||||||
 | 
					        context: context,
 | 
				
			||||||
 | 
					        builder: (BuildContext context) {
 | 
				
			||||||
 | 
					          return DeleteDialog(
 | 
				
			||||||
 | 
					            alert: alertMsg,
 | 
				
			||||||
 | 
					            onDelete: () => deleteCb(true),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void handleRemoteDelete(
 | 
					    void handleRemoteDelete(
 | 
				
			||||||
      bool force,
 | 
					      bool force,
 | 
				
			||||||
@ -73,15 +89,7 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
        deleteCb(force);
 | 
					        deleteCb(force);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      showDialog(
 | 
					      return showForceDeleteDialog(deleteCb, alertMsg: alertMsg);
 | 
				
			||||||
        context: context,
 | 
					 | 
				
			||||||
        builder: (BuildContext context) {
 | 
					 | 
				
			||||||
          return DeleteDialog(
 | 
					 | 
				
			||||||
            alert: alertMsg,
 | 
					 | 
				
			||||||
            onDelete: () => deleteCb(force),
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    List<Widget> renderActionButtons() {
 | 
					    List<Widget> renderActionButtons() {
 | 
				
			||||||
@ -132,6 +140,12 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
                        alertMsg: "delete_dialog_alert_remote",
 | 
					                        alertMsg: "delete_dialog_alert_remote",
 | 
				
			||||||
                      )
 | 
					                      )
 | 
				
			||||||
                  : null,
 | 
					                  : null,
 | 
				
			||||||
 | 
					              onLongPressed: enabled
 | 
				
			||||||
 | 
					                  ? () => showForceDeleteDialog(
 | 
				
			||||||
 | 
					                        onDeleteServer!,
 | 
				
			||||||
 | 
					                        alertMsg: "delete_dialog_alert_remote",
 | 
				
			||||||
 | 
					                      )
 | 
				
			||||||
 | 
					                  : null,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        if (hasLocal && onDeleteLocal != null)
 | 
					        if (hasLocal && onDeleteLocal != null)
 | 
				
			||||||
@ -167,6 +181,8 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
              onPressed: enabled
 | 
					              onPressed: enabled
 | 
				
			||||||
                  ? () => handleRemoteDelete(!trashEnabled, onDelete!)
 | 
					                  ? () => handleRemoteDelete(!trashEnabled, onDelete!)
 | 
				
			||||||
                  : null,
 | 
					                  : null,
 | 
				
			||||||
 | 
					              onLongPressed:
 | 
				
			||||||
 | 
					                  enabled ? () => showForceDeleteDialog(onDelete!) : null,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        if (hasRemote && onEditTime != null)
 | 
					        if (hasRemote && onEditTime != null)
 | 
				
			||||||
@ -214,9 +230,9 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return DraggableScrollableSheet(
 | 
					    return DraggableScrollableSheet(
 | 
				
			||||||
      initialChildSize: hasRemote ? 0.30 : 0.18,
 | 
					      initialChildSize: hasRemote ? 0.30 : bottomPadding,
 | 
				
			||||||
      minChildSize: 0.18,
 | 
					      minChildSize: bottomPadding,
 | 
				
			||||||
      maxChildSize: hasRemote ? 0.60 : 0.18,
 | 
					      maxChildSize: hasRemote ? 0.60 : bottomPadding,
 | 
				
			||||||
      snap: true,
 | 
					      snap: true,
 | 
				
			||||||
      builder: (
 | 
					      builder: (
 | 
				
			||||||
        BuildContext context,
 | 
					        BuildContext context,
 | 
				
			||||||
 | 
				
			|||||||
@ -201,9 +201,9 @@ class MultiselectGrid extends HookConsumerWidget {
 | 
				
			|||||||
            msg: '${selection.value.length} $assetOrAssets $trashOrRemoved',
 | 
					            msg: '${selection.value.length} $assetOrAssets $trashOrRemoved',
 | 
				
			||||||
            gravity: ToastGravity.BOTTOM,
 | 
					            gravity: ToastGravity.BOTTOM,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
 | 
					          selectionEnabledHook.value = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } finally {
 | 
					      } finally {
 | 
				
			||||||
        selectionEnabledHook.value = false;
 | 
					 | 
				
			||||||
        processing.value = false;
 | 
					        processing.value = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -224,9 +224,9 @@ class MultiselectGrid extends HookConsumerWidget {
 | 
				
			|||||||
                '${localIds.length} $assetOrAssets removed permanently from your device',
 | 
					                '${localIds.length} $assetOrAssets removed permanently from your device',
 | 
				
			||||||
            gravity: ToastGravity.BOTTOM,
 | 
					            gravity: ToastGravity.BOTTOM,
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
 | 
					          selectionEnabledHook.value = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } finally {
 | 
					      } finally {
 | 
				
			||||||
        selectionEnabledHook.value = false;
 | 
					 | 
				
			||||||
        processing.value = false;
 | 
					        processing.value = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -23,11 +23,13 @@ class ControlBoxButton extends StatelessWidget {
 | 
				
			|||||||
    required this.label,
 | 
					    required this.label,
 | 
				
			||||||
    required this.iconData,
 | 
					    required this.iconData,
 | 
				
			||||||
    this.onPressed,
 | 
					    this.onPressed,
 | 
				
			||||||
 | 
					    this.onLongPressed,
 | 
				
			||||||
  }) : super(key: key);
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final String label;
 | 
					  final String label;
 | 
				
			||||||
  final IconData iconData;
 | 
					  final IconData iconData;
 | 
				
			||||||
  final void Function()? onPressed;
 | 
					  final void Function()? onPressed;
 | 
				
			||||||
 | 
					  final void Function()? onLongPressed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
@ -35,6 +37,7 @@ class ControlBoxButton extends StatelessWidget {
 | 
				
			|||||||
      padding: const EdgeInsets.all(10),
 | 
					      padding: const EdgeInsets.all(10),
 | 
				
			||||||
      shape: const CircleBorder(),
 | 
					      shape: const CircleBorder(),
 | 
				
			||||||
      onPressed: onPressed,
 | 
					      onPressed: onPressed,
 | 
				
			||||||
 | 
					      onLongPress: onLongPressed,
 | 
				
			||||||
      minWidth: 75.0,
 | 
					      minWidth: 75.0,
 | 
				
			||||||
      child: Column(
 | 
					      child: Column(
 | 
				
			||||||
        mainAxisAlignment: MainAxisAlignment.start,
 | 
					        mainAxisAlignment: MainAxisAlignment.start,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user