mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	Optimize mobile - Avoid creating unnecessary widgets (#268)
* Avoid creating unnecessary widgets * more flexible null handling and runtime errors prevention
This commit is contained in:
		| @@ -39,14 +39,10 @@ class ImageViewerService { | ||||
|         entity = await PhotoManager.editor.saveVideo(tempFile, title: fileName); | ||||
|       } | ||||
|  | ||||
|       if (entity != null) { | ||||
|         return true; | ||||
|       } | ||||
|       return entity != null; | ||||
|     } catch (e) { | ||||
|       debugPrint("Error saving file $e"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -15,81 +15,72 @@ class ExifBottomSheet extends ConsumerWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     _buildMap() { | ||||
|       return (assetDetail.exifInfo!.latitude != null && | ||||
|               assetDetail.exifInfo!.longitude != null) | ||||
|           ? Padding( | ||||
|               padding: const EdgeInsets.symmetric(vertical: 16.0), | ||||
|               child: Container( | ||||
|                 height: 150, | ||||
|                 width: MediaQuery.of(context).size.width, | ||||
|                 decoration: const BoxDecoration( | ||||
|                   borderRadius: BorderRadius.all(Radius.circular(15)), | ||||
|                 ), | ||||
|                 child: FlutterMap( | ||||
|                   options: MapOptions( | ||||
|                     center: LatLng(assetDetail.exifInfo!.latitude!, | ||||
|                         assetDetail.exifInfo!.longitude!), | ||||
|                     zoom: 16.0, | ||||
|                   ), | ||||
|                   layers: [ | ||||
|                     TileLayerOptions( | ||||
|                       urlTemplate: | ||||
|                           "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", | ||||
|                       subdomains: ['a', 'b', 'c'], | ||||
|                       attributionBuilder: (_) { | ||||
|                         return const Text( | ||||
|                           "© OpenStreetMap", | ||||
|                           style: TextStyle(fontSize: 10), | ||||
|                         ); | ||||
|                       }, | ||||
|                     ), | ||||
|                     MarkerLayerOptions( | ||||
|                       markers: [ | ||||
|                         Marker( | ||||
|                           anchorPos: AnchorPos.align(AnchorAlign.top), | ||||
|                           point: LatLng(assetDetail.exifInfo!.latitude!, | ||||
|                               assetDetail.exifInfo!.longitude!), | ||||
|                           builder: (ctx) => const Image( | ||||
|                               image: AssetImage('assets/location-pin.png')), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ], | ||||
|                 ), | ||||
|       return Padding( | ||||
|         padding: const EdgeInsets.symmetric(vertical: 16.0), | ||||
|         child: Container( | ||||
|           height: 150, | ||||
|           width: MediaQuery.of(context).size.width, | ||||
|           decoration: const BoxDecoration( | ||||
|             borderRadius: BorderRadius.all(Radius.circular(15)), | ||||
|           ), | ||||
|           child: FlutterMap( | ||||
|             options: MapOptions( | ||||
|               center: LatLng(assetDetail.exifInfo!.latitude!, | ||||
|                   assetDetail.exifInfo!.longitude!), | ||||
|               zoom: 16.0, | ||||
|             ), | ||||
|             layers: [ | ||||
|               TileLayerOptions( | ||||
|                 urlTemplate: | ||||
|                     "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", | ||||
|                 subdomains: ['a', 'b', 'c'], | ||||
|                 attributionBuilder: (_) { | ||||
|                   return const Text( | ||||
|                     "© OpenStreetMap", | ||||
|                     style: TextStyle(fontSize: 10), | ||||
|                   ); | ||||
|                 }, | ||||
|               ), | ||||
|             ) | ||||
|           : Container(); | ||||
|               MarkerLayerOptions( | ||||
|                 markers: [ | ||||
|                   Marker( | ||||
|                     anchorPos: AnchorPos.align(AnchorAlign.top), | ||||
|                     point: LatLng(assetDetail.exifInfo!.latitude!, | ||||
|                         assetDetail.exifInfo!.longitude!), | ||||
|                     builder: (ctx) => const Image( | ||||
|                         image: AssetImage('assets/location-pin.png')), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     _buildLocationText() { | ||||
|       return (assetDetail.exifInfo!.city != null && | ||||
|               assetDetail.exifInfo!.state != null) | ||||
|           ? Text( | ||||
|               "${assetDetail.exifInfo!.city}, ${assetDetail.exifInfo!.state}", | ||||
|               style: TextStyle( | ||||
|                   fontSize: 12, | ||||
|                   color: Colors.grey[200], | ||||
|                   fontWeight: FontWeight.bold), | ||||
|             ) | ||||
|           : Container(); | ||||
|       return Text( | ||||
|         "${assetDetail.exifInfo!.city}, ${assetDetail.exifInfo!.state}", | ||||
|         style: TextStyle( | ||||
|             fontSize: 12, color: Colors.grey[200], fontWeight: FontWeight.bold), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return Padding( | ||||
|       padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8), | ||||
|       child: ListView( | ||||
|         children: [ | ||||
|           assetDetail.exifInfo?.dateTimeOriginal != null | ||||
|               ? Text( | ||||
|                   DateFormat('E, LLL d, y • h:mm a').format( | ||||
|                     DateTime.parse(assetDetail.exifInfo!.dateTimeOriginal!), | ||||
|                   ), | ||||
|                   style: TextStyle( | ||||
|                     color: Colors.grey[400], | ||||
|                     fontWeight: FontWeight.bold, | ||||
|                     fontSize: 14, | ||||
|                   ), | ||||
|                 ) | ||||
|               : Container(), | ||||
|           if (assetDetail.exifInfo?.dateTimeOriginal != null) | ||||
|             Text( | ||||
|               DateFormat('E, LLL d, y • h:mm a').format( | ||||
|                 DateTime.parse(assetDetail.exifInfo!.dateTimeOriginal!), | ||||
|               ), | ||||
|               style: TextStyle( | ||||
|                 color: Colors.grey[400], | ||||
|                 fontWeight: FontWeight.bold, | ||||
|                 fontSize: 14, | ||||
|               ), | ||||
|             ), | ||||
|           Padding( | ||||
|             padding: const EdgeInsets.only(top: 16.0), | ||||
|             child: Text( | ||||
| @@ -102,84 +93,83 @@ class ExifBottomSheet extends ConsumerWidget { | ||||
|           ), | ||||
|  | ||||
|           // Location | ||||
|           assetDetail.exifInfo?.latitude != null | ||||
|               ? Padding( | ||||
|                   padding: const EdgeInsets.only(top: 32.0), | ||||
|                   child: Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     children: [ | ||||
|                       Divider( | ||||
|                         thickness: 1, | ||||
|                         color: Colors.grey[600], | ||||
|                       ), | ||||
|                       Text( | ||||
|                         "LOCATION", | ||||
|                         style: TextStyle(fontSize: 11, color: Colors.grey[400]), | ||||
|                       ), | ||||
|                       _buildMap(), | ||||
|                       _buildLocationText(), | ||||
|                       Text( | ||||
|                         "${assetDetail.exifInfo!.latitude!.toStringAsFixed(4)}, ${assetDetail.exifInfo!.longitude!.toStringAsFixed(4)}", | ||||
|                         style: TextStyle(fontSize: 12, color: Colors.grey[400]), | ||||
|                       ) | ||||
|                     ], | ||||
|           if (assetDetail.exifInfo?.latitude != null) | ||||
|             Padding( | ||||
|               padding: const EdgeInsets.only(top: 32.0), | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                 children: [ | ||||
|                   Divider( | ||||
|                     thickness: 1, | ||||
|                     color: Colors.grey[600], | ||||
|                   ), | ||||
|                 ) | ||||
|               : Container(), | ||||
|                   Text( | ||||
|                     "LOCATION", | ||||
|                     style: TextStyle(fontSize: 11, color: Colors.grey[400]), | ||||
|                   ), | ||||
|                   if (assetDetail.exifInfo?.latitude != null && | ||||
|                       assetDetail.exifInfo?.longitude != null) | ||||
|                     _buildMap(), | ||||
|                   if (assetDetail.exifInfo?.city != null && | ||||
|                       assetDetail.exifInfo?.state != null) | ||||
|                     _buildLocationText(), | ||||
|                   Text( | ||||
|                     "${assetDetail.exifInfo?.latitude?.toStringAsFixed(4)}, ${assetDetail.exifInfo?.longitude?.toStringAsFixed(4)}", | ||||
|                     style: TextStyle(fontSize: 12, color: Colors.grey[400]), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|           // Detail | ||||
|           assetDetail.exifInfo != null | ||||
|               ? Padding( | ||||
|                   padding: const EdgeInsets.only(top: 32.0), | ||||
|                   child: Column( | ||||
|                     crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                     children: [ | ||||
|                       Divider( | ||||
|                         thickness: 1, | ||||
|                         color: Colors.grey[600], | ||||
|                       ), | ||||
|                       Padding( | ||||
|                         padding: const EdgeInsets.only(bottom: 8.0), | ||||
|                         child: Text( | ||||
|                           "DETAILS", | ||||
|                           style: | ||||
|                               TextStyle(fontSize: 11, color: Colors.grey[400]), | ||||
|                         ), | ||||
|                       ), | ||||
|                       ListTile( | ||||
|                         contentPadding: const EdgeInsets.all(0), | ||||
|                         dense: true, | ||||
|                         textColor: Colors.grey[300], | ||||
|                         iconColor: Colors.grey[300], | ||||
|                         leading: const Icon(Icons.image), | ||||
|                         title: Text( | ||||
|                           "${assetDetail.exifInfo?.imageName!}${p.extension(assetDetail.originalPath)}", | ||||
|                           style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|                         ), | ||||
|                         subtitle: assetDetail.exifInfo?.exifImageHeight != null | ||||
|                             ? Text( | ||||
|                                 "${assetDetail.exifInfo?.exifImageHeight} x ${assetDetail.exifInfo?.exifImageWidth}  ${assetDetail.exifInfo?.fileSizeInByte!}B ") | ||||
|                             : Container(), | ||||
|                       ), | ||||
|                       assetDetail.exifInfo?.make != null | ||||
|                           ? ListTile( | ||||
|                               contentPadding: const EdgeInsets.all(0), | ||||
|                               dense: true, | ||||
|                               textColor: Colors.grey[300], | ||||
|                               iconColor: Colors.grey[300], | ||||
|                               leading: const Icon(Icons.camera), | ||||
|                               title: Text( | ||||
|                                 "${assetDetail.exifInfo?.make} ${assetDetail.exifInfo?.model}", | ||||
|                                 style: const TextStyle( | ||||
|                                     fontWeight: FontWeight.bold), | ||||
|                               ), | ||||
|                               subtitle: Text( | ||||
|                                   "ƒ/${assetDetail.exifInfo?.fNumber}   1/${(1 / assetDetail.exifInfo!.exposureTime!).toStringAsFixed(0)}   ${assetDetail.exifInfo?.focalLength}mm   ISO${assetDetail.exifInfo?.iso} "), | ||||
|                             ) | ||||
|                           : Container() | ||||
|                     ], | ||||
|           if (assetDetail.exifInfo != null) | ||||
|             Padding( | ||||
|               padding: const EdgeInsets.only(top: 32.0), | ||||
|               child: Column( | ||||
|                 crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                 children: [ | ||||
|                   Divider( | ||||
|                     thickness: 1, | ||||
|                     color: Colors.grey[600], | ||||
|                   ), | ||||
|                 ) | ||||
|               : Container() | ||||
|                   Padding( | ||||
|                     padding: const EdgeInsets.only(bottom: 8.0), | ||||
|                     child: Text( | ||||
|                       "DETAILS", | ||||
|                       style: TextStyle(fontSize: 11, color: Colors.grey[400]), | ||||
|                     ), | ||||
|                   ), | ||||
|                   ListTile( | ||||
|                     contentPadding: const EdgeInsets.all(0), | ||||
|                     dense: true, | ||||
|                     textColor: Colors.grey[300], | ||||
|                     iconColor: Colors.grey[300], | ||||
|                     leading: const Icon(Icons.image), | ||||
|                     title: Text( | ||||
|                       "${assetDetail.exifInfo?.imageName!}${p.extension(assetDetail.originalPath)}", | ||||
|                       style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|                     ), | ||||
|                     subtitle: assetDetail.exifInfo?.exifImageHeight != null | ||||
|                         ? Text( | ||||
|                             "${assetDetail.exifInfo?.exifImageHeight} x ${assetDetail.exifInfo?.exifImageWidth}  ${assetDetail.exifInfo?.fileSizeInByte!}B ") | ||||
|                         : null, | ||||
|                   ), | ||||
|                   if (assetDetail.exifInfo?.make != null) | ||||
|                     ListTile( | ||||
|                       contentPadding: const EdgeInsets.all(0), | ||||
|                       dense: true, | ||||
|                       textColor: Colors.grey[300], | ||||
|                       iconColor: Colors.grey[300], | ||||
|                       leading: const Icon(Icons.camera), | ||||
|                       title: Text( | ||||
|                         "${assetDetail.exifInfo?.make} ${assetDetail.exifInfo?.model}", | ||||
|                         style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|                       ), | ||||
|                       subtitle: Text( | ||||
|                           "ƒ/${assetDetail.exifInfo?.fNumber}   1/${(1 / (assetDetail.exifInfo?.exposureTime ?? 1)).toStringAsFixed(0)}   ${assetDetail.exifInfo?.focalLength}mm   ISO${assetDetail.exifInfo?.iso} "), | ||||
|                     ), | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -147,8 +147,7 @@ class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return chewieController != null && | ||||
|             chewieController!.videoPlayerController.value.isInitialized | ||||
|     return chewieController?.videoPlayerController.value.isInitialized == true | ||||
|         ? SizedBox( | ||||
|             child: Chewie( | ||||
|               controller: chewieController!, | ||||
|   | ||||
| @@ -56,7 +56,7 @@ class AlbumInfoCard extends HookConsumerWidget { | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       return Container(); | ||||
|       return const SizedBox(); | ||||
|     } | ||||
|  | ||||
|     _buildImageFilter() { | ||||
| @@ -151,7 +151,11 @@ class AlbumInfoCard extends HookConsumerWidget { | ||||
|                   ), | ||||
|                   child: null, | ||||
|                 ), | ||||
|                 Positioned(bottom: 10, left: 25, child: _buildSelectedTextBox()) | ||||
|                 Positioned( | ||||
|                   bottom: 10, | ||||
|                   left: 25, | ||||
|                   child: _buildSelectedTextBox(), | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|             Padding( | ||||
| @@ -176,8 +180,7 @@ class AlbumInfoCard extends HookConsumerWidget { | ||||
|                           Padding( | ||||
|                             padding: const EdgeInsets.only(top: 2.0), | ||||
|                             child: Text( | ||||
|                               albumInfo.assetCount.toString() + | ||||
|                                   (albumInfo.isAll ? " (ALL)" : ""), | ||||
|                               '${albumInfo.assetCount} ${(albumInfo.isAll ? " (ALL)" : "")}', | ||||
|                               style: TextStyle( | ||||
|                                   fontSize: 12, color: Colors.grey[600]), | ||||
|                             ), | ||||
|   | ||||
| @@ -188,11 +188,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { | ||||
|                           color: Colors.grey[700]), | ||||
|                     ), | ||||
|                     trailing: Text( | ||||
|                       ref | ||||
|                           .watch(backupProvider) | ||||
|                           .allUniqueAssets | ||||
|                           .length | ||||
|                           .toString(), | ||||
|                       '${ref.watch(backupProvider).allUniqueAssets.length}', | ||||
|                       style: const TextStyle(fontWeight: FontWeight.bold), | ||||
|                     ), | ||||
|                   ), | ||||
| @@ -203,7 +199,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { | ||||
|  | ||||
|           ListTile( | ||||
|             title: Text( | ||||
|               "Albums on device (${availableAlbums.length.toString()})", | ||||
|               "Albums on device (${availableAlbums.length})", | ||||
|               style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), | ||||
|             ), | ||||
|             subtitle: Padding( | ||||
|   | ||||
| @@ -96,12 +96,11 @@ class BackupControllerPage extends HookConsumerWidget { | ||||
|           child: Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
|             children: [ | ||||
|               !isAutoBackup | ||||
|                   ? const Text( | ||||
|                       "Turn on backup to automatically upload new assets to the server.", | ||||
|                       style: TextStyle(fontSize: 14), | ||||
|                     ) | ||||
|                   : Container(), | ||||
|               if (!isAutoBackup) | ||||
|                 const Text( | ||||
|                   "Turn on backup to automatically upload new assets to the server.", | ||||
|                   style: TextStyle(fontSize: 14), | ||||
|                 ), | ||||
|               Padding( | ||||
|                 padding: const EdgeInsets.only(top: 8.0), | ||||
|                 child: OutlinedButton( | ||||
| @@ -189,7 +188,7 @@ class BackupControllerPage extends HookConsumerWidget { | ||||
|           ), | ||||
|         ); | ||||
|       } else { | ||||
|         return Container(); | ||||
|         return const SizedBox(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,7 @@ class DisableMultiSelectButton extends ConsumerWidget { | ||||
|                   }, | ||||
|                   icon: const Icon(Icons.close_rounded), | ||||
|                   label: Text( | ||||
|                     selectedItemCount.toString(), | ||||
|                     '$selectedItemCount', | ||||
|                     style: const TextStyle( | ||||
|                         fontWeight: FontWeight.w600, fontSize: 18), | ||||
|                   )), | ||||
|   | ||||
| @@ -615,7 +615,7 @@ class SlideFadeTransition extends StatelessWidget { | ||||
|     return AnimatedBuilder( | ||||
|       animation: animation, | ||||
|       builder: (context, child) => | ||||
|           animation.value == 0.0 ? Container() : child!, | ||||
|           animation.value == 0.0 ? const SizedBox() : child!, | ||||
|       child: SlideTransition( | ||||
|         position: Tween( | ||||
|           begin: const Offset(0.3, 0.0), | ||||
|   | ||||
| @@ -25,30 +25,26 @@ class ImageGrid extends ConsumerWidget { | ||||
|             child: Stack( | ||||
|               children: [ | ||||
|                 ThumbnailImage(asset: assetGroup[index]), | ||||
|                 assetType == 'IMAGE' | ||||
|                     ? Container() | ||||
|                     : Positioned( | ||||
|                         top: 5, | ||||
|                         right: 5, | ||||
|                         child: Row( | ||||
|                           children: [ | ||||
|                             Text( | ||||
|                               assetGroup[index] | ||||
|                                   .duration | ||||
|                                   .toString() | ||||
|                                   .substring(0, 7), | ||||
|                               style: const TextStyle( | ||||
|                                 color: Colors.white, | ||||
|                                 fontSize: 10, | ||||
|                               ), | ||||
|                             ), | ||||
|                             const Icon( | ||||
|                               Icons.play_circle_outline_rounded, | ||||
|                               color: Colors.white, | ||||
|                             ), | ||||
|                           ], | ||||
|                 if (assetType != 'IMAGE') | ||||
|                   Positioned( | ||||
|                     top: 5, | ||||
|                     right: 5, | ||||
|                     child: Row( | ||||
|                       children: [ | ||||
|                         Text( | ||||
|                           assetGroup[index].duration.toString().substring(0, 7), | ||||
|                           style: const TextStyle( | ||||
|                             color: Colors.white, | ||||
|                             fontSize: 10, | ||||
|                           ), | ||||
|                         ), | ||||
|                       ) | ||||
|                         const Icon( | ||||
|                           Icons.play_circle_outline_rounded, | ||||
|                           color: Colors.white, | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|               ], | ||||
|             ), | ||||
|           ); | ||||
|   | ||||
| @@ -49,30 +49,29 @@ class ImmichSliverAppBar extends ConsumerWidget { | ||||
|                   }, | ||||
|                 ), | ||||
|               ), | ||||
|               serverInfoState.isVersionMismatch | ||||
|                   ? Positioned( | ||||
|                       bottom: 12, | ||||
|                       right: 12, | ||||
|                       child: GestureDetector( | ||||
|                         onTap: () => Scaffold.of(context).openDrawer(), | ||||
|                         child: Material( | ||||
|                           color: Colors.grey[200], | ||||
|                           elevation: 1, | ||||
|                           shape: RoundedRectangleBorder( | ||||
|                             borderRadius: BorderRadius.circular(50.0), | ||||
|                           ), | ||||
|                           child: const Padding( | ||||
|                             padding: EdgeInsets.all(2.0), | ||||
|                             child: Icon( | ||||
|                               Icons.info, | ||||
|                               color: Color.fromARGB(255, 243, 188, 106), | ||||
|                               size: 15, | ||||
|                             ), | ||||
|                           ), | ||||
|               if (serverInfoState.isVersionMismatch) | ||||
|                 Positioned( | ||||
|                   bottom: 12, | ||||
|                   right: 12, | ||||
|                   child: GestureDetector( | ||||
|                     onTap: () => Scaffold.of(context).openDrawer(), | ||||
|                     child: Material( | ||||
|                       color: Colors.grey[200], | ||||
|                       elevation: 1, | ||||
|                       shape: RoundedRectangleBorder( | ||||
|                         borderRadius: BorderRadius.circular(50.0), | ||||
|                       ), | ||||
|                       child: const Padding( | ||||
|                         padding: EdgeInsets.all(2.0), | ||||
|                         child: Icon( | ||||
|                           Icons.info, | ||||
|                           color: Color.fromARGB(255, 243, 188, 106), | ||||
|                           size: 15, | ||||
|                         ), | ||||
|                       ), | ||||
|                     ) | ||||
|                   : Container(), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|             ], | ||||
|           ); | ||||
|         }, | ||||
| @@ -90,21 +89,20 @@ class ImmichSliverAppBar extends ConsumerWidget { | ||||
|         Stack( | ||||
|           alignment: AlignmentDirectional.center, | ||||
|           children: [ | ||||
|             backupState.backupProgress == BackUpProgressEnum.inProgress | ||||
|                 ? Positioned( | ||||
|                     top: 10, | ||||
|                     right: 12, | ||||
|                     child: SizedBox( | ||||
|                       height: 8, | ||||
|                       width: 8, | ||||
|                       child: CircularProgressIndicator( | ||||
|                         strokeWidth: 1, | ||||
|                         valueColor: AlwaysStoppedAnimation<Color>( | ||||
|                             Theme.of(context).primaryColor), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ) | ||||
|                 : Container(), | ||||
|             if (backupState.backupProgress == BackUpProgressEnum.inProgress) | ||||
|               Positioned( | ||||
|                 top: 10, | ||||
|                 right: 12, | ||||
|                 child: SizedBox( | ||||
|                   height: 8, | ||||
|                   width: 8, | ||||
|                   child: CircularProgressIndicator( | ||||
|                     strokeWidth: 1, | ||||
|                     valueColor: AlwaysStoppedAnimation<Color>( | ||||
|                         Theme.of(context).primaryColor), | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|             IconButton( | ||||
|               splashRadius: 25, | ||||
|               iconSize: 30, | ||||
| @@ -129,18 +127,15 @@ class ImmichSliverAppBar extends ConsumerWidget { | ||||
|                 } | ||||
|               }, | ||||
|             ), | ||||
|             backupState.backupProgress == BackUpProgressEnum.inProgress | ||||
|                 ? Positioned( | ||||
|                     bottom: 5, | ||||
|                     child: Text( | ||||
|                       (backupState.allUniqueAssets.length - | ||||
|                               backupState.selectedAlbumsBackupAssetsIds.length) | ||||
|                           .toString(), | ||||
|                       style: const TextStyle( | ||||
|                           fontSize: 9, fontWeight: FontWeight.bold), | ||||
|                     ), | ||||
|                   ) | ||||
|                 : Container() | ||||
|             if (backupState.backupProgress == BackUpProgressEnum.inProgress) | ||||
|               Positioned( | ||||
|                 bottom: 5, | ||||
|                 child: Text( | ||||
|                   '${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}', | ||||
|                   style: | ||||
|                       const TextStyle(fontSize: 9, fontWeight: FontWeight.bold), | ||||
|                 ), | ||||
|               ), | ||||
|           ], | ||||
|         ), | ||||
|       ], | ||||
|   | ||||
| @@ -87,7 +87,7 @@ class ProfileDrawer extends HookConsumerWidget { | ||||
|         return const ImmichLoadingIndicator(); | ||||
|       } | ||||
|  | ||||
|       return Container(); | ||||
|       return const SizedBox(); | ||||
|     } | ||||
|  | ||||
|     _pickUserProfileImage() async { | ||||
|   | ||||
| @@ -122,17 +122,14 @@ class ThumbnailImage extends HookConsumerWidget { | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|             Container( | ||||
|               child: isMultiSelectEnable | ||||
|                   ? Padding( | ||||
|                       padding: const EdgeInsets.all(3.0), | ||||
|                       child: Align( | ||||
|                         alignment: Alignment.topLeft, | ||||
|                         child: _buildSelectionIcon(asset), | ||||
|                       ), | ||||
|                     ) | ||||
|                   : Container(), | ||||
|             ), | ||||
|             if (isMultiSelectEnable) | ||||
|               Padding( | ||||
|                 padding: const EdgeInsets.all(3.0), | ||||
|                 child: Align( | ||||
|                   alignment: Alignment.topLeft, | ||||
|                   child: _buildSelectionIcon(asset), | ||||
|                 ), | ||||
|               ), | ||||
|             Positioned( | ||||
|               right: 10, | ||||
|               bottom: 5, | ||||
|   | ||||
| @@ -38,17 +38,10 @@ class HomePage extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     _buildSelectedItemCountIndicator() { | ||||
|       return isMultiSelectEnable | ||||
|           ? DisableMultiSelectButton( | ||||
|               onPressed: | ||||
|                   ref.watch(homePageStateProvider.notifier).disableMultiSelect, | ||||
|               selectedItemCount: homePageState.selectedItems.length, | ||||
|             ) | ||||
|           : Container(); | ||||
|     } | ||||
|  | ||||
|     _buildBottomAppBar() { | ||||
|       return isMultiSelectEnable ? const ControlBottomAppBar() : Container(); | ||||
|       return DisableMultiSelectButton( | ||||
|         onPressed: ref.watch(homePageStateProvider.notifier).disableMultiSelect, | ||||
|         selectedItemCount: homePageState.selectedItems.length, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     Widget _buildBody() { | ||||
| @@ -121,8 +114,10 @@ class HomePage extends HookConsumerWidget { | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             _buildSelectedItemCountIndicator(), | ||||
|             _buildBottomAppBar(), | ||||
|             if (isMultiSelectEnable) ...[ | ||||
|               _buildSelectedItemCountIndicator(), | ||||
|               const ControlBottomAppBar(), | ||||
|             ], | ||||
|           ], | ||||
|         ), | ||||
|       ); | ||||
|   | ||||
| @@ -107,19 +107,12 @@ class ServerEndpointInput extends StatelessWidget { | ||||
|       : super(key: key); | ||||
|  | ||||
|   String? _validateInput(String? url) { | ||||
|     if (url == null) { | ||||
|    | ||||
|     if (url?.startsWith(RegExp(r'https?://')) == true) { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     if (url.isEmpty) { | ||||
|       return 'Server endpoint is required'; | ||||
|     } | ||||
|  | ||||
|     if (!url.startsWith(RegExp(r'https?://'))) { | ||||
|     } else { | ||||
|       return 'Please specify http:// or https://'; | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   | ||||
| @@ -62,11 +62,7 @@ final getCuratedLocationProvider = | ||||
|   final SearchService searchService = ref.watch(searchServiceProvider); | ||||
|  | ||||
|   var curatedLocation = await searchService.getCuratedLocation(); | ||||
|   if (curatedLocation != null) { | ||||
|     return curatedLocation; | ||||
|   } else { | ||||
|     return []; | ||||
|   } | ||||
|   return curatedLocation ?? []; | ||||
| }); | ||||
|  | ||||
| final getCuratedObjectProvider = | ||||
| @@ -74,9 +70,6 @@ final getCuratedObjectProvider = | ||||
|   final SearchService searchService = ref.watch(searchServiceProvider); | ||||
|  | ||||
|   var curatedObject = await searchService.getCuratedObjects(); | ||||
|   if (curatedObject != null) { | ||||
|     return curatedObject; | ||||
|   } else { | ||||
|     return []; | ||||
|   } | ||||
|  | ||||
|   return curatedObject ?? []; | ||||
| }); | ||||
|   | ||||
| @@ -176,9 +176,8 @@ class SearchPage extends HookConsumerWidget { | ||||
|                 _buildThings() | ||||
|               ], | ||||
|             ), | ||||
|             isSearchEnabled | ||||
|                 ? SearchSuggestionList(onSubmitted: _onSearchSubmitted) | ||||
|                 : Container(), | ||||
|             if (isSearchEnabled) | ||||
|               SearchSuggestionList(onSubmitted: _onSearchSubmitted), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|   | ||||
| @@ -166,7 +166,7 @@ class SearchResultPage extends HookConsumerWidget { | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return Container(); | ||||
|       return const SizedBox(); | ||||
|     } | ||||
|  | ||||
|     return Scaffold( | ||||
| @@ -198,9 +198,8 @@ class SearchResultPage extends HookConsumerWidget { | ||||
|         child: Stack( | ||||
|           children: [ | ||||
|             _buildSearchResult(), | ||||
|             isNewSearch.value | ||||
|                 ? SearchSuggestionList(onSubmitted: _onSearchSubmitted) | ||||
|                 : Container(), | ||||
|             if (isNewSearch.value) | ||||
|               SearchSuggestionList(onSubmitted: _onSearchSubmitted), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|   | ||||
| @@ -72,10 +72,7 @@ class SharedAlbum { | ||||
|       albumThumbnailAssetId: map['albumThumbnailAssetId'], | ||||
|       sharedUsers: | ||||
|           List<User>.from(map['sharedUsers']?.map((x) => User.fromMap(x))), | ||||
|       assets: map['assets'] != null | ||||
|           ? List<ImmichAsset>.from( | ||||
|               map['assets']?.map((x) => ImmichAsset.fromMap(x))) | ||||
|           : null, | ||||
|       assets: map['assets']?.map((x) => ImmichAsset.fromMap(x)).toList(), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -39,11 +39,7 @@ class SharedAlbumService { | ||||
|         "assetIds": assets.map((asset) => asset.id).toList(), | ||||
|       }); | ||||
|  | ||||
|       if (res == null) { | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|       return true; | ||||
|       return res != null; | ||||
|     } catch (e) { | ||||
|       debugPrint("Error createSharedAlbum  ${e.toString()}"); | ||||
|       return false; | ||||
| @@ -71,11 +67,7 @@ class SharedAlbumService { | ||||
|         "assetIds": assets.map((asset) => asset.id).toList(), | ||||
|       }); | ||||
|  | ||||
|       if (res == null) { | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|       return true; | ||||
|       return res != null; | ||||
|     } catch (e) { | ||||
|       debugPrint("Error addAdditionalAssetToAlbum  ${e.toString()}"); | ||||
|       return false; | ||||
| @@ -90,11 +82,7 @@ class SharedAlbumService { | ||||
|         "sharedUserIds": sharedUserIds, | ||||
|       }); | ||||
|  | ||||
|       if (res == null) { | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|       return true; | ||||
|       return res != null; | ||||
|     } catch (e) { | ||||
|       debugPrint("Error addAdditionalUserToAlbum  ${e.toString()}"); | ||||
|       return false; | ||||
|   | ||||
| @@ -114,7 +114,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { | ||||
|             onTap: () => _onRemoveFromAlbumPressed(albumId), | ||||
|           ); | ||||
|         } else { | ||||
|           return Container(); | ||||
|           return const SizedBox(); | ||||
|         } | ||||
|       } else { | ||||
|         if (_albumInfo.asData?.value.ownerId == userId) { | ||||
| @@ -198,8 +198,8 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { | ||||
|       elevation: 0, | ||||
|       leading: _buildLeadingButton(), | ||||
|       title: isMultiSelectionEnable | ||||
|           ? Text(selectedAssetsInAlbum.length.toString()) | ||||
|           : Container(), | ||||
|           ? Text('${selectedAssetsInAlbum.length}') | ||||
|           : null, | ||||
|       centerTitle: false, | ||||
|       actions: [ | ||||
|         IconButton( | ||||
|   | ||||
| @@ -71,29 +71,25 @@ class AlbumViewerThumbnail extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     _buildVideoLabel() { | ||||
|       if (asset.type == 'IMAGE') { | ||||
|         return Container(); | ||||
|       } else { | ||||
|         return Positioned( | ||||
|           top: 5, | ||||
|           right: 5, | ||||
|           child: Row( | ||||
|             children: [ | ||||
|               Text( | ||||
|                 asset.duration.toString().substring(0, 7), | ||||
|                 style: const TextStyle( | ||||
|                   color: Colors.white, | ||||
|                   fontSize: 10, | ||||
|                 ), | ||||
|               ), | ||||
|               const Icon( | ||||
|                 Icons.play_circle_outline_rounded, | ||||
|       return Positioned( | ||||
|         top: 5, | ||||
|         right: 5, | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             Text( | ||||
|               asset.duration.toString().substring(0, 7), | ||||
|               style: const TextStyle( | ||||
|                 color: Colors.white, | ||||
|                 fontSize: 10, | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ); | ||||
|       } | ||||
|             ), | ||||
|             const Icon( | ||||
|               Icons.play_circle_outline_rounded, | ||||
|               color: Colors.white, | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     _buildAssetStoreLocationIcon() { | ||||
| @@ -112,23 +108,20 @@ class AlbumViewerThumbnail extends HookConsumerWidget { | ||||
|  | ||||
|     _buildAssetSelectionIcon() { | ||||
|       bool isSelected = selectedAssetsInAlbumViewer.contains(asset); | ||||
|       if (isMultiSelectionEnable) { | ||||
|         return Positioned( | ||||
|           left: 10, | ||||
|           top: 5, | ||||
|           child: isSelected | ||||
|               ? Icon( | ||||
|                   Icons.check_circle_rounded, | ||||
|                   color: Theme.of(context).primaryColor, | ||||
|                 ) | ||||
|               : const Icon( | ||||
|                   Icons.check_circle_outline_rounded, | ||||
|                   color: Colors.white, | ||||
|                 ), | ||||
|         ); | ||||
|       } else { | ||||
|         return Container(); | ||||
|       } | ||||
|  | ||||
|       return Positioned( | ||||
|         left: 10, | ||||
|         top: 5, | ||||
|         child: isSelected | ||||
|             ? Icon( | ||||
|                 Icons.check_circle_rounded, | ||||
|                 color: Theme.of(context).primaryColor, | ||||
|               ) | ||||
|             : const Icon( | ||||
|                 Icons.check_circle_outline_rounded, | ||||
|                 color: Colors.white, | ||||
|               ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     _buildThumbnailImage() { | ||||
| @@ -183,8 +176,8 @@ class AlbumViewerThumbnail extends HookConsumerWidget { | ||||
|           children: [ | ||||
|             _buildThumbnailImage(), | ||||
|             _buildAssetStoreLocationIcon(), | ||||
|             _buildVideoLabel(), | ||||
|             _buildAssetSelectionIcon(), | ||||
|             if (asset.type != 'IMAGE') _buildVideoLabel(), | ||||
|             if (isMultiSelectionEnable) _buildAssetSelectionIcon(), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|   | ||||
| @@ -131,27 +131,26 @@ class SelectionThumbnailImage extends HookConsumerWidget { | ||||
|               child: _buildSelectionIcon(asset), | ||||
|             ), | ||||
|           ), | ||||
|           asset.type == 'IMAGE' | ||||
|               ? Container() | ||||
|               : Positioned( | ||||
|                   bottom: 5, | ||||
|                   right: 5, | ||||
|                   child: Row( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         asset.duration.toString().substring(0, 7), | ||||
|                         style: const TextStyle( | ||||
|                           color: Colors.white, | ||||
|                           fontSize: 10, | ||||
|                         ), | ||||
|                       ), | ||||
|                       const Icon( | ||||
|                         Icons.play_circle_outline_rounded, | ||||
|                         color: Colors.white, | ||||
|                       ), | ||||
|                     ], | ||||
|           if (asset.type != 'IMAGE') | ||||
|             Positioned( | ||||
|               bottom: 5, | ||||
|               right: 5, | ||||
|               child: Row( | ||||
|                 children: [ | ||||
|                   Text( | ||||
|                     '${asset.duration?.substring(0, 7)}', | ||||
|                     style: const TextStyle( | ||||
|                       color: Colors.white, | ||||
|                       fontSize: 10, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ) | ||||
|                   const Icon( | ||||
|                     Icons.play_circle_outline_rounded, | ||||
|                     color: Colors.white, | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -14,7 +14,8 @@ class SharingSliverAppBar extends StatelessWidget { | ||||
|       floating: false, | ||||
|       pinned: true, | ||||
|       snap: false, | ||||
|       leading: Container(), | ||||
|       automaticallyImplyLeading: false, | ||||
|       // leading: Container(), | ||||
|       // elevation: 0, | ||||
|       title: Text( | ||||
|         'IMMICH', | ||||
|   | ||||
| @@ -37,7 +37,7 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|     /// Find out if the assets in album exist on the device | ||||
|     /// If they exist, add to selected asset state to show they are already selected. | ||||
|     void _onAddPhotosPressed(SharedAlbum albumInfo) async { | ||||
|       if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) { | ||||
|       if (albumInfo.assets?.isNotEmpty == true) { | ||||
|         ref | ||||
|             .watch(assetSelectionProvider.notifier) | ||||
|             .addNewAssets(albumInfo.assets!.toList()); | ||||
| @@ -109,32 +109,28 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     Widget _buildAlbumDateRange(SharedAlbum albumInfo) { | ||||
|       if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) { | ||||
|         String startDate = ""; | ||||
|         DateTime parsedStartDate = | ||||
|             DateTime.parse(albumInfo.assets!.first.createdAt); | ||||
|         DateTime parsedEndDate = | ||||
|             DateTime.parse(albumInfo.assets!.last.createdAt); | ||||
|       String startDate = ""; | ||||
|       DateTime parsedStartDate = | ||||
|           DateTime.parse(albumInfo.assets!.first.createdAt); | ||||
|       DateTime parsedEndDate = DateTime.parse( | ||||
|           albumInfo.assets?.last.createdAt ?? '11111111'); //Need default. | ||||
|  | ||||
|         if (parsedStartDate.year == parsedEndDate.year) { | ||||
|           startDate = DateFormat('LLL d').format(parsedStartDate); | ||||
|         } else { | ||||
|           startDate = DateFormat('LLL d, y').format(parsedStartDate); | ||||
|         } | ||||
|  | ||||
|         String endDate = DateFormat('LLL d, y').format(parsedEndDate); | ||||
|  | ||||
|         return Padding( | ||||
|           padding: const EdgeInsets.only(left: 16.0, top: 8), | ||||
|           child: Text( | ||||
|             "$startDate-$endDate", | ||||
|             style: const TextStyle( | ||||
|                 fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey), | ||||
|           ), | ||||
|         ); | ||||
|       if (parsedStartDate.year == parsedEndDate.year) { | ||||
|         startDate = DateFormat('LLL d').format(parsedStartDate); | ||||
|       } else { | ||||
|         return Container(); | ||||
|         startDate = DateFormat('LLL d, y').format(parsedStartDate); | ||||
|       } | ||||
|  | ||||
|       String endDate = DateFormat('LLL d, y').format(parsedEndDate); | ||||
|  | ||||
|       return Padding( | ||||
|         padding: const EdgeInsets.only(left: 16.0, top: 8), | ||||
|         child: Text( | ||||
|           "$startDate-$endDate", | ||||
|           style: const TextStyle( | ||||
|               fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     Widget _buildHeader(SharedAlbum albumInfo) { | ||||
| @@ -143,7 +139,8 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|           crossAxisAlignment: CrossAxisAlignment.start, | ||||
|           children: [ | ||||
|             _buildTitle(albumInfo), | ||||
|             _buildAlbumDateRange(albumInfo), | ||||
|             if (albumInfo.assets?.isNotEmpty == true) | ||||
|               _buildAlbumDateRange(albumInfo), | ||||
|             SizedBox( | ||||
|               height: 60, | ||||
|               child: ListView.builder( | ||||
| @@ -175,7 +172,7 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     Widget _buildImageGrid(SharedAlbum albumInfo) { | ||||
|       if (albumInfo.assets != null && albumInfo.assets!.isNotEmpty) { | ||||
|       if (albumInfo.assets?.isNotEmpty == true) { | ||||
|         return SliverPadding( | ||||
|           padding: const EdgeInsets.only(top: 10.0), | ||||
|           sliver: SliverGrid( | ||||
| @@ -209,13 +206,12 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|                 onPressed: () => _onAddPhotosPressed(albumInfo), | ||||
|                 labelText: "Add photos", | ||||
|               ), | ||||
|               userId == albumInfo.ownerId | ||||
|                   ? AlbumActionOutlinedButton( | ||||
|                       iconData: Icons.person_add_alt_rounded, | ||||
|                       onPressed: () => _onAddUsersPressed(albumInfo), | ||||
|                       labelText: "Add users", | ||||
|                     ) | ||||
|                   : Container(), | ||||
|               if (userId == albumInfo.ownerId) | ||||
|                 AlbumActionOutlinedButton( | ||||
|                   iconData: Icons.person_add_alt_rounded, | ||||
|                   onPressed: () => _onAddUsersPressed(albumInfo), | ||||
|                   labelText: "Add users", | ||||
|                 ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|   | ||||
| @@ -74,23 +74,22 @@ class AssetSelectionPage extends HookConsumerWidget { | ||||
|               ), | ||||
|         centerTitle: false, | ||||
|         actions: [ | ||||
|           (!isAlbumExist && selectedAssets.isNotEmpty) || | ||||
|                   (isAlbumExist && newAssetsForAlbum.isNotEmpty) | ||||
|               ? TextButton( | ||||
|                   onPressed: () { | ||||
|                     var payload = AssetSelectionPageResult( | ||||
|                       isAlbumExist: isAlbumExist, | ||||
|                       selectedAdditionalAsset: newAssetsForAlbum, | ||||
|                       selectedNewAsset: selectedAssets, | ||||
|                     ); | ||||
|                     AutoRouter.of(context).pop(payload); | ||||
|                   }, | ||||
|                   child: const Text( | ||||
|                     "Add", | ||||
|                     style: TextStyle(fontWeight: FontWeight.bold), | ||||
|                   ), | ||||
|                 ) | ||||
|               : Container() | ||||
|           if ((!isAlbumExist && selectedAssets.isNotEmpty) || | ||||
|               (isAlbumExist && newAssetsForAlbum.isNotEmpty)) | ||||
|             TextButton( | ||||
|               onPressed: () { | ||||
|                 var payload = AssetSelectionPageResult( | ||||
|                   isAlbumExist: isAlbumExist, | ||||
|                   selectedAdditionalAsset: newAssetsForAlbum, | ||||
|                   selectedNewAsset: selectedAssets, | ||||
|                 ); | ||||
|                 AutoRouter.of(context).pop(payload); | ||||
|               }, | ||||
|               child: const Text( | ||||
|                 "Add", | ||||
|                 style: TextStyle(fontWeight: FontWeight.bold), | ||||
|               ), | ||||
|             ), | ||||
|         ], | ||||
|       ), | ||||
|       body: _buildBody(), | ||||
|   | ||||
| @@ -113,26 +113,22 @@ class CreateSharedAlbumPage extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     _buildControlButton() { | ||||
|       if (selectedAssets.isNotEmpty) { | ||||
|         return Padding( | ||||
|           padding: const EdgeInsets.only(left: 12.0, top: 16, bottom: 16), | ||||
|           child: SizedBox( | ||||
|             height: 30, | ||||
|             child: ListView( | ||||
|               scrollDirection: Axis.horizontal, | ||||
|               children: [ | ||||
|                 AlbumActionOutlinedButton( | ||||
|                   iconData: Icons.add_photo_alternate_outlined, | ||||
|                   onPressed: _onSelectPhotosButtonPressed, | ||||
|                   labelText: "Add photos", | ||||
|                 ), | ||||
|               ], | ||||
|             ), | ||||
|       return Padding( | ||||
|         padding: const EdgeInsets.only(left: 12.0, top: 16, bottom: 16), | ||||
|         child: SizedBox( | ||||
|           height: 30, | ||||
|           child: ListView( | ||||
|             scrollDirection: Axis.horizontal, | ||||
|             children: [ | ||||
|               AlbumActionOutlinedButton( | ||||
|                 iconData: Icons.add_photo_alternate_outlined, | ||||
|                 onPressed: _onSelectPhotosButtonPressed, | ||||
|                 labelText: "Add photos", | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       return Container(); | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     _buildSelectedImageGrid() { | ||||
| @@ -196,7 +192,8 @@ class CreateSharedAlbumPage extends HookConsumerWidget { | ||||
|             slivers: [ | ||||
|               SliverAppBar( | ||||
|                 elevation: 5, | ||||
|                 leading: Container(), | ||||
|                 automaticallyImplyLeading: false, | ||||
|                 // leading: Container(), | ||||
|                 pinned: true, | ||||
|                 floating: false, | ||||
|                 bottom: PreferredSize( | ||||
| @@ -204,7 +201,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget { | ||||
|                   child: Column( | ||||
|                     children: [ | ||||
|                       _buildTitleInputField(), | ||||
|                       _buildControlButton(), | ||||
|                       if (selectedAssets.isNotEmpty) _buildControlButton(), | ||||
|                     ], | ||||
|                   ), | ||||
|                 ), | ||||
|   | ||||
| @@ -104,10 +104,9 @@ class WebsocketNotifier extends StateNotifier<WebscoketState> { | ||||
|   disconnect() { | ||||
|     debugPrint("[WEBSOCKET] Attempting to disconnect"); | ||||
|     var socket = state.socket?.disconnect(); | ||||
|     if (socket != null) { | ||||
|       if (socket.disconnected) { | ||||
|         state = WebscoketState(isConnected: false, socket: null); | ||||
|       } | ||||
|  | ||||
|     if (socket?.disconnected == true) { | ||||
|       state = WebscoketState(isConnected: false, socket: null); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,7 @@ class SplashScreenPage extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     useEffect(() { | ||||
|       if (loginInfo != null && loginInfo.isSaveLogin) { | ||||
|       if (loginInfo?.isSaveLogin == true) { | ||||
|         performLoggingIn(); | ||||
|       } else { | ||||
|         AutoRouter.of(context).push(const LoginRoute()); | ||||
|   | ||||
| @@ -121,7 +121,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { | ||||
|             ), | ||||
|           ); | ||||
|         } else { | ||||
|           return Container(); | ||||
|           return const SizedBox(); | ||||
|         } | ||||
|       }, | ||||
|     ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user